ETH Price: $3,100.00 (+0.54%)
Gas: 5 Gwei

Token

rebase AAVE (rAAVE)
 

Overview

Max Total Supply

14,055.443893477903728 rAAVE

Holders

368

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
staboi.eth
Balance
26.17888135187893762 rAAVE

Value
$0.00
0xa66589142c46a20e747c68987a0cd46e5bc9ffc8
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
rAAVE

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-02-07
*/

// SPDX-License-Identifier: GPL-3.0-only

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


pragma solidity >=0.6.0 <0.8.0;

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

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

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


pragma solidity >=0.6.0 <0.8.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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

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

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

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


pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

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


pragma solidity >=0.6.0 <0.8.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.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @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() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

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


pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: contracts/ElasticERC20.sol

pragma solidity ^0.6.0;




/**
 * @dev This contract is based on the OpenZeppelin ERC20 implementation,
 * basically adding the elastic extensions.
 */
contract ElasticERC20 is Context, IERC20
{
	using SafeMath for uint256;

	uint8 constant UNSCALED_DECIMALS = 24;
	uint256 constant UNSCALED_FACTOR = 10 ** uint256(UNSCALED_DECIMALS);

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

	mapping (address => uint256) private unscaledBalances_;
	uint256 private unscaledTotalSupply_;

	string private name_;
	string private symbol_;
	uint8 private decimals_;

	uint256 private scalingFactor_;

	constructor (string memory _name, string memory _symbol) public
	{
		name_ = _name;
		symbol_ = _symbol;
		_setupDecimals(18);
	}

	function name() public view returns (string memory _name)
	{
		return name_;
	}

	function symbol() public view returns (string memory _symbol)
	{
		return symbol_;
	}

	function decimals() public view returns (uint8 _decimals)
	{
		return decimals_;
	}

	function totalSupply() public view override returns (uint256 _supply)
	{
		return _scale(unscaledTotalSupply_, scalingFactor_);
	}

	function balanceOf(address _account) public view override returns (uint256 _balance)
	{
		return _scale(unscaledBalances_[_account], scalingFactor_);
	}

	function allowance(address _owner, address _spender) public view virtual override returns (uint256 _allowance)
	{
		return allowances_[_owner][_spender];
	}

	function approve(address _spender, uint256 _amount) public virtual override returns (bool _success)
	{
		_approve(_msgSender(), _spender, _amount);
		return true;
	}

	function increaseAllowance(address _spender, uint256 _addedValue) public virtual returns (bool _success)
	{
		_approve(_msgSender(), _spender, allowances_[_msgSender()][_spender].add(_addedValue));
		return true;
	}

	function decreaseAllowance(address _spender, uint256 _subtractedValue) public virtual returns (bool _success)
	{
		_approve(_msgSender(), _spender, allowances_[_msgSender()][_spender].sub(_subtractedValue, "ERC20: decreased allowance below zero"));
		return true;
	}

	function transfer(address _recipient, uint256 _amount) public virtual override returns (bool _success)
	{
		_transfer(_msgSender(), _recipient, _amount);
		return true;
	}

	function transferFrom(address _sender, address _recipient, uint256 _amount) public virtual override returns (bool _success)
	{
		_transfer(_sender, _recipient, _amount);
		_approve(_sender, _msgSender(), allowances_[_sender][_msgSender()].sub(_amount, "ERC20: transfer amount exceeds allowance"));
		return true;
	}

	function _approve(address _owner, address _spender, uint256 _amount) internal virtual
	{
		require(_owner != address(0), "ERC20: approve from the zero address");
		require(_spender != address(0), "ERC20: approve to the zero address");
		allowances_[_owner][_spender] = _amount;
		emit Approval(_owner, _spender, _amount);
	}

	function _transfer(address _sender, address _recipient, uint256 _amount) internal virtual
	{
		uint256 _unscaledAmount = _unscale(_amount, scalingFactor_);
		require(_sender != address(0), "ERC20: transfer from the zero address");
		require(_recipient != address(0), "ERC20: transfer to the zero address");
		_beforeTokenTransfer(_sender, _recipient, _amount);
		unscaledBalances_[_sender] = unscaledBalances_[_sender].sub(_unscaledAmount, "ERC20: transfer amount exceeds balance");
		unscaledBalances_[_recipient] = unscaledBalances_[_recipient].add(_unscaledAmount);
		emit Transfer(_sender, _recipient, _amount);
	}

	function _mint(address _account, uint256 _amount) internal virtual
	{
		uint256 _unscaledAmount = _unscale(_amount, scalingFactor_);
		require(_account != address(0), "ERC20: mint to the zero address");
		_beforeTokenTransfer(address(0), _account, _amount);
		unscaledTotalSupply_ = unscaledTotalSupply_.add(_unscaledAmount);
		uint256 _maxScalingFactor = _calcMaxScalingFactor(unscaledTotalSupply_);
		require(scalingFactor_ <= _maxScalingFactor, "unsupported scaling factor");
		unscaledBalances_[_account] = unscaledBalances_[_account].add(_unscaledAmount);
		emit Transfer(address(0), _account, _amount);
	}

	function _burn(address _account, uint256 _amount) internal virtual
	{
		uint256 _unscaledAmount = _unscale(_amount, scalingFactor_);
		require(_account != address(0), "ERC20: burn from the zero address");
		_beforeTokenTransfer(_account, address(0), _amount);
		unscaledBalances_[_account] = unscaledBalances_[_account].sub(_unscaledAmount, "ERC20: burn amount exceeds balance");
		unscaledTotalSupply_ = unscaledTotalSupply_.sub(_unscaledAmount);
		emit Transfer(_account, address(0), _amount);
	}

	function _setupDecimals(uint8 _decimals) internal
	{
		decimals_ = _decimals;
		scalingFactor_ = 10 ** uint256(_decimals);
	}

	function _beforeTokenTransfer(address _from, address _to, uint256 _amount) internal virtual { }

	function unscaledTotalSupply() public view returns (uint256 _supply)
	{
		return unscaledTotalSupply_;
	}

	function unscaledBalanceOf(address _account) public view returns (uint256 _balance)
	{
		return unscaledBalances_[_account];
	}

	function scalingFactor() public view returns (uint256 _scalingFactor)
	{
		return scalingFactor_;
	}

	function maxScalingFactor() public view returns (uint256 _maxScalingFactor)
	{
		return _calcMaxScalingFactor(unscaledTotalSupply_);
	}

	function _calcMaxScalingFactor(uint256 _unscaledTotalSupply) internal pure returns (uint256 _maxScalingFactor)
	{
		return uint256(-1).div(_unscaledTotalSupply);
	}

	function _scale(uint256 _unscaledAmount, uint256 _scalingFactor) internal pure returns (uint256 _amount)
	{
		return _unscaledAmount.mul(_scalingFactor).div(UNSCALED_FACTOR);
	}

	function _unscale(uint256 _amount, uint256 _scalingFactor) internal pure returns (uint256 _unscaledAmount)
	{
		return _amount.mul(UNSCALED_FACTOR).div(_scalingFactor);
	}

	function _setScalingFactor(uint256 _scalingFactor) internal
	{
		uint256 _maxScalingFactor = _calcMaxScalingFactor(unscaledTotalSupply_);
		require(0 < _scalingFactor && _scalingFactor <= _maxScalingFactor, "unsupported scaling factor");
		scalingFactor_ = _scalingFactor;
	}
}

// File: contracts/Executor.sol

pragma solidity ^0.6.0;

/**
 * @dev This library provides support for the dynamic execution of external
 * contract calls.
 */
library Executor
{
	struct Target {
		address to;
		bytes data;
	}

	function addTarget(Target[] storage _targets, address _to, bytes memory _data) internal
	{
		_targets.push(Target({ to: _to, data: _data }));
	}

	function removeTarget(Target[] storage _targets, uint256 _index) internal
	{
		require(_index < _targets.length, "invalid index");
		_targets[_index] = _targets[_targets.length - 1];
		_targets.pop();
	}

	function executeAll(Target[] storage _targets) internal
	{
		for (uint256 _i = 0; _i < _targets.length; _i++) {
			Target storage _target = _targets[_i];
			bool _success = _externalCall(_target.to, _target.data);
			require(_success, "call failed");
		}
	}

	function _externalCall(address _to, bytes memory _data) private returns (bool _success)
	{
		assembly {
			_success := call(gas(), _to, 0, add(_data, 0x20), mload(_data), 0, 0)
		}
	}
}

// File: contracts/GElastic.sol

pragma solidity ^0.6.0;

/**
 * @dev This interface exposes the base functionality of GElasticToken.
 */
interface GElastic
{
	// view functions
	function referenceToken() external view returns (address _referenceToken);
	function treasury() external view returns (address _treasury);
	function rebaseMinimumDeviation() external view returns (uint256 _rebaseMinimumDeviation);
	function rebaseDampeningFactor() external view returns (uint256 _rebaseDampeningFactor);
	function rebaseTreasuryMintPercent() external view returns (uint256 _rebaseTreasuryMintPercent);
	function rebaseTimingParameters() external view returns (uint256 _rebaseMinimumInterval, uint256 _rebaseWindowOffset, uint256 _rebaseWindowLength);
	function rebaseActive() external view returns (bool _rebaseActive);
	function rebaseAvailable() external view returns (bool _available);
	function lastRebaseTime() external view returns (uint256 _lastRebaseTime);
	function epoch() external view returns (uint256 _epoch);
	function lastExchangeRate() external view returns (uint256 _exchangeRate);
	function currentExchangeRate() external view returns (uint256 _exchangeRate);
	function pair() external view returns (address _pair);

	// open functions
	function rebase() external;

	// priviledged functions
	function activateOracle(address _pair) external;
	function activateRebase() external;
	function setTreasury(address _newTreasury) external;
	function setRebaseMinimumDeviation(uint256 _newRebaseMinimumDeviation) external;
	function setRebaseDampeningFactor(uint256 _newRebaseDampeningFactor) external;
	function setRebaseTreasuryMintPercent(uint256 _newRebaseTreasuryMintPercent) external;
	function setRebaseTimingParameters(uint256 _newRebaseMinimumInterval, uint256 _newRebaseWindowOffset, uint256 _newRebaseWindowLength) external;
	function addPostRebaseTarget(address _to, bytes memory _data) external;
	function removePostRebaseTarget(uint256 _index) external;

	// emitted events
	event Rebase(uint256 indexed _epoch, uint256 _oldScalingFactor, uint256 _newScalingFactor);
	event ChangeTreasury(address _oldTreasury, address _newTreasury);
	event ChangeRebaseMinimumDeviation(uint256 _oldRebaseMinimumDeviation, uint256 _newRebaseMinimumDeviation);
	event ChangeRebaseDampeningFactor(uint256 _oldRebaseDampeningFactor, uint256 _newRebaseDampeningFactor);
	event ChangeRebaseTreasuryMintPercent(uint256 _oldRebaseTreasuryMintPercent, uint256 _newRebaseTreasuryMintPercent);
	event ChangeRebaseTimingParameters(uint256 _oldRebaseMinimumInterval, uint256 _oldRebaseWindowOffset, uint256 _oldRebaseWindowLength, uint256 _newRebaseMinimumInterval, uint256 _newRebaseWindowOffset, uint256 _newRebaseWindowLength);
	event AddPostRebaseTarget(address indexed _to, bytes _data);
	event RemovePostRebaseTarget(address indexed _to, bytes _data);
}

// File: contracts/GElasticTokenManager.sol

pragma solidity ^0.6.0;


/**
 * @dev This library helps managing rebase parameters and calculations.
 */
library GElasticTokenManager
{
	using SafeMath for uint256;
	using GElasticTokenManager for GElasticTokenManager.Self;

	uint256 constant MAXIMUM_REBASE_TREASURY_MINT_PERCENT = 25e16; // 25%

	uint256 constant DEFAULT_REBASE_MINIMUM_INTERVAL = 24 hours;
	uint256 constant DEFAULT_REBASE_WINDOW_OFFSET = 17 hours; // 5PM UTC
	uint256 constant DEFAULT_REBASE_WINDOW_LENGTH = 1 hours;
	uint256 constant DEFAULT_REBASE_MINIMUM_DEVIATION = 5e16; // 5%
	uint256 constant DEFAULT_REBASE_DAMPENING_FACTOR = 10; // 10x to reach 100%
	uint256 constant DEFAULT_REBASE_TREASURY_MINT_PERCENT = 10e16; // 10%

	struct Self {
		address treasury;

		uint256 rebaseMinimumDeviation;
		uint256 rebaseDampeningFactor;
		uint256 rebaseTreasuryMintPercent;

		uint256 rebaseMinimumInterval;
		uint256 rebaseWindowOffset;
		uint256 rebaseWindowLength;

		bool rebaseActive;
		uint256 lastRebaseTime;
		uint256 epoch;
	}

	function init(Self storage _self, address _treasury) public
	{
		_self.treasury = _treasury;

		_self.rebaseMinimumDeviation = DEFAULT_REBASE_MINIMUM_DEVIATION;
		_self.rebaseDampeningFactor = DEFAULT_REBASE_DAMPENING_FACTOR;
		_self.rebaseTreasuryMintPercent = DEFAULT_REBASE_TREASURY_MINT_PERCENT;

		_self.rebaseMinimumInterval = DEFAULT_REBASE_MINIMUM_INTERVAL;
		_self.rebaseWindowOffset = DEFAULT_REBASE_WINDOW_OFFSET;
		_self.rebaseWindowLength = DEFAULT_REBASE_WINDOW_LENGTH;

		_self.rebaseActive = false;
		_self.lastRebaseTime = 0;
		_self.epoch = 0;
	}

	function activateRebase(Self storage _self) public
	{
		require(!_self.rebaseActive, "already active");
		_self.rebaseActive = true;
		_self.lastRebaseTime = now.sub(now.mod(_self.rebaseMinimumInterval)).add(_self.rebaseWindowOffset);
	}

	function setTreasury(Self storage _self, address _treasury) public
	{
		require(_treasury != address(0), "invalid treasury");
		_self.treasury = _treasury;
	}

	function setRebaseMinimumDeviation(Self storage _self, uint256 _rebaseMinimumDeviation) public
	{
		require(_rebaseMinimumDeviation > 0, "invalid minimum deviation");
		_self.rebaseMinimumDeviation = _rebaseMinimumDeviation;
	}

	function setRebaseDampeningFactor(Self storage _self, uint256 _rebaseDampeningFactor) public
	{
		require(_rebaseDampeningFactor > 0, "invalid dampening factor");
		_self.rebaseDampeningFactor = _rebaseDampeningFactor;
	}

	function setRebaseTreasuryMintPercent(Self storage _self, uint256 _rebaseTreasuryMintPercent) public
	{
		require(_rebaseTreasuryMintPercent <= MAXIMUM_REBASE_TREASURY_MINT_PERCENT, "invalid percent");
		_self.rebaseTreasuryMintPercent = _rebaseTreasuryMintPercent;
	}

	function setRebaseTimingParameters(Self storage _self, uint256 _rebaseMinimumInterval, uint256 _rebaseWindowOffset, uint256 _rebaseWindowLength) public
	{
		require(_rebaseMinimumInterval > 0, "invalid interval");
		require(_rebaseWindowOffset.add(_rebaseWindowLength) <= _rebaseMinimumInterval, "invalid window");
		_self.rebaseMinimumInterval = _rebaseMinimumInterval;
		_self.rebaseWindowOffset = _rebaseWindowOffset;
		_self.rebaseWindowLength = _rebaseWindowLength;
	}

	function rebaseAvailable(Self storage _self) public view returns (bool _available)
	{
		return _self._rebaseAvailable();
	}

	function rebase(Self storage _self, uint256 _exchangeRate, uint256 _totalSupply) public returns (uint256 _delta, bool _positive, uint256 _mintAmount)
	{
		require(_self._rebaseAvailable(), "not available");

		_self.lastRebaseTime = now.sub(now.mod(_self.rebaseMinimumInterval)).add(_self.rebaseWindowOffset);
		_self.epoch = _self.epoch.add(1);

		_positive = _exchangeRate > 1e18;

		uint256 _deviation = _positive ? _exchangeRate.sub(1e18) : uint256(1e18).sub(_exchangeRate);
		if (_deviation < _self.rebaseMinimumDeviation) {
			_deviation = 0;
			_positive = false;
		}

		_delta = _deviation.div(_self.rebaseDampeningFactor);

		_mintAmount = 0;
		if (_positive) {
			uint256 _mintPercent = _delta.mul(_self.rebaseTreasuryMintPercent).div(1e18);
			_delta = _delta.sub(_mintPercent);
			_mintAmount = _totalSupply.mul(_mintPercent).div(1e18);
		}

		return (_delta, _positive, _mintAmount);
	}

	function _rebaseAvailable(Self storage _self) internal view returns (bool _available)
	{
		if (!_self.rebaseActive) return false;
		if (now < _self.lastRebaseTime.add(_self.rebaseMinimumInterval)) return false;
		uint256 _offset = now.mod(_self.rebaseMinimumInterval);
		return _self.rebaseWindowOffset <= _offset && _offset < _self.rebaseWindowOffset.add(_self.rebaseWindowLength);
	}
}

// File: @uniswap/lib/contracts/libraries/FullMath.sol

pragma solidity >=0.4.0;

// taken from https://medium.com/coinmonks/math-in-solidity-part-3-percents-and-proportions-4db014e080b1
// license is CC-BY-4.0
library FullMath {
    function fullMul(uint256 x, uint256 y) internal pure returns (uint256 l, uint256 h) {
        uint256 mm = mulmod(x, y, uint256(-1));
        l = x * y;
        h = mm - l;
        if (mm < l) h -= 1;
    }

    function fullDiv(
        uint256 l,
        uint256 h,
        uint256 d
    ) private pure returns (uint256) {
        uint256 pow2 = d & -d;
        d /= pow2;
        l /= pow2;
        l += h * ((-pow2) / pow2 + 1);
        uint256 r = 1;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        r *= 2 - d * r;
        return l * r;
    }

    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 d
    ) internal pure returns (uint256) {
        (uint256 l, uint256 h) = fullMul(x, y);

        uint256 mm = mulmod(x, y, d);
        if (mm > l) h -= 1;
        l -= mm;

        if (h == 0) return l / d;

        require(h < d, 'FullMath: FULLDIV_OVERFLOW');
        return fullDiv(l, h, d);
    }
}

// File: @uniswap/lib/contracts/libraries/Babylonian.sol


pragma solidity >=0.4.0;

// computes square roots using the babylonian method
// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
library Babylonian {
    // credit for this implementation goes to
    // https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687
    function sqrt(uint256 x) internal pure returns (uint256) {
        if (x == 0) return 0;
        // this block is equivalent to r = uint256(1) << (BitMath.mostSignificantBit(x) / 2);
        // however that code costs significantly more gas
        uint256 xx = x;
        uint256 r = 1;
        if (xx >= 0x100000000000000000000000000000000) {
            xx >>= 128;
            r <<= 64;
        }
        if (xx >= 0x10000000000000000) {
            xx >>= 64;
            r <<= 32;
        }
        if (xx >= 0x100000000) {
            xx >>= 32;
            r <<= 16;
        }
        if (xx >= 0x10000) {
            xx >>= 16;
            r <<= 8;
        }
        if (xx >= 0x100) {
            xx >>= 8;
            r <<= 4;
        }
        if (xx >= 0x10) {
            xx >>= 4;
            r <<= 2;
        }
        if (xx >= 0x8) {
            r <<= 1;
        }
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1; // Seven iterations should be enough
        uint256 r1 = x / r;
        return (r < r1 ? r : r1);
    }
}

// File: @uniswap/lib/contracts/libraries/BitMath.sol

pragma solidity >=0.5.0;

library BitMath {
    // returns the 0 indexed position of the most significant bit of the input x
    // s.t. x >= 2**msb and x < 2**(msb+1)
    function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
        require(x > 0, 'BitMath::mostSignificantBit: zero');

        if (x >= 0x100000000000000000000000000000000) {
            x >>= 128;
            r += 128;
        }
        if (x >= 0x10000000000000000) {
            x >>= 64;
            r += 64;
        }
        if (x >= 0x100000000) {
            x >>= 32;
            r += 32;
        }
        if (x >= 0x10000) {
            x >>= 16;
            r += 16;
        }
        if (x >= 0x100) {
            x >>= 8;
            r += 8;
        }
        if (x >= 0x10) {
            x >>= 4;
            r += 4;
        }
        if (x >= 0x4) {
            x >>= 2;
            r += 2;
        }
        if (x >= 0x2) r += 1;
    }

    // returns the 0 indexed position of the least significant bit of the input x
    // s.t. (x & 2**lsb) != 0 and (x & (2**(lsb) - 1)) == 0)
    // i.e. the bit at the index is set and the mask of all lower bits is 0
    function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {
        require(x > 0, 'BitMath::leastSignificantBit: zero');

        r = 255;
        if (x & uint128(-1) > 0) {
            r -= 128;
        } else {
            x >>= 128;
        }
        if (x & uint64(-1) > 0) {
            r -= 64;
        } else {
            x >>= 64;
        }
        if (x & uint32(-1) > 0) {
            r -= 32;
        } else {
            x >>= 32;
        }
        if (x & uint16(-1) > 0) {
            r -= 16;
        } else {
            x >>= 16;
        }
        if (x & uint8(-1) > 0) {
            r -= 8;
        } else {
            x >>= 8;
        }
        if (x & 0xf > 0) {
            r -= 4;
        } else {
            x >>= 4;
        }
        if (x & 0x3 > 0) {
            r -= 2;
        } else {
            x >>= 2;
        }
        if (x & 0x1 > 0) r -= 1;
    }
}

// File: @uniswap/lib/contracts/libraries/FixedPoint.sol

pragma solidity >=0.4.0;




// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
library FixedPoint {
    // range: [0, 2**112 - 1]
    // resolution: 1 / 2**112
    struct uq112x112 {
        uint224 _x;
    }

    // range: [0, 2**144 - 1]
    // resolution: 1 / 2**112
    struct uq144x112 {
        uint256 _x;
    }

    uint8 public constant RESOLUTION = 112;
    uint256 public constant Q112 = 0x10000000000000000000000000000; // 2**112
    uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; // 2**224
    uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)

    // encode a uint112 as a UQ112x112
    function encode(uint112 x) internal pure returns (uq112x112 memory) {
        return uq112x112(uint224(x) << RESOLUTION);
    }

    // encodes a uint144 as a UQ144x112
    function encode144(uint144 x) internal pure returns (uq144x112 memory) {
        return uq144x112(uint256(x) << RESOLUTION);
    }

    // decode a UQ112x112 into a uint112 by truncating after the radix point
    function decode(uq112x112 memory self) internal pure returns (uint112) {
        return uint112(self._x >> RESOLUTION);
    }

    // decode a UQ144x112 into a uint144 by truncating after the radix point
    function decode144(uq144x112 memory self) internal pure returns (uint144) {
        return uint144(self._x >> RESOLUTION);
    }

    // multiply a UQ112x112 by a uint, returning a UQ144x112
    // reverts on overflow
    function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) {
        uint256 z = 0;
        require(y == 0 || (z = self._x * y) / y == self._x, 'FixedPoint::mul: overflow');
        return uq144x112(z);
    }

    // multiply a UQ112x112 by an int and decode, returning an int
    // reverts on overflow
    function muli(uq112x112 memory self, int256 y) internal pure returns (int256) {
        uint256 z = FullMath.mulDiv(self._x, uint256(y < 0 ? -y : y), Q112);
        require(z < 2**255, 'FixedPoint::muli: overflow');
        return y < 0 ? -int256(z) : int256(z);
    }

    // multiply a UQ112x112 by a UQ112x112, returning a UQ112x112
    // lossy
    function muluq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) {
        if (self._x == 0 || other._x == 0) {
            return uq112x112(0);
        }
        uint112 upper_self = uint112(self._x >> RESOLUTION); // * 2^0
        uint112 lower_self = uint112(self._x & LOWER_MASK); // * 2^-112
        uint112 upper_other = uint112(other._x >> RESOLUTION); // * 2^0
        uint112 lower_other = uint112(other._x & LOWER_MASK); // * 2^-112

        // partial products
        uint224 upper = uint224(upper_self) * upper_other; // * 2^0
        uint224 lower = uint224(lower_self) * lower_other; // * 2^-224
        uint224 uppers_lowero = uint224(upper_self) * lower_other; // * 2^-112
        uint224 uppero_lowers = uint224(upper_other) * lower_self; // * 2^-112

        // so the bit shift does not overflow
        require(upper <= uint112(-1), 'FixedPoint::muluq: upper overflow');

        // this cannot exceed 256 bits, all values are 224 bits
        uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION);

        // so the cast does not overflow
        require(sum <= uint224(-1), 'FixedPoint::muluq: sum overflow');

        return uq112x112(uint224(sum));
    }

    // divide a UQ112x112 by a UQ112x112, returning a UQ112x112
    function divuq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) {
        require(other._x > 0, 'FixedPoint::divuq: division by zero');
        if (self._x == other._x) {
            return uq112x112(uint224(Q112));
        }
        if (self._x <= uint144(-1)) {
            uint256 value = (uint256(self._x) << RESOLUTION) / other._x;
            require(value <= uint224(-1), 'FixedPoint::divuq: overflow');
            return uq112x112(uint224(value));
        }

        uint256 result = FullMath.mulDiv(Q112, self._x, other._x);
        require(result <= uint224(-1), 'FixedPoint::divuq: overflow');
        return uq112x112(uint224(result));
    }

    // returns a UQ112x112 which represents the ratio of the numerator to the denominator
    // can be lossy
    function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {
        require(denominator > 0, 'FixedPoint::fraction: division by zero');
        if (numerator == 0) return FixedPoint.uq112x112(0);

        if (numerator <= uint144(-1)) {
            uint256 result = (numerator << RESOLUTION) / denominator;
            require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
            return uq112x112(uint224(result));
        } else {
            uint256 result = FullMath.mulDiv(numerator, Q112, denominator);
            require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
            return uq112x112(uint224(result));
        }
    }

    // take the reciprocal of a UQ112x112
    // reverts on overflow
    // lossy
    function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) {
        require(self._x != 0, 'FixedPoint::reciprocal: reciprocal of zero');
        require(self._x != 1, 'FixedPoint::reciprocal: overflow');
        return uq112x112(uint224(Q224 / self._x));
    }

    // square root of a UQ112x112
    // lossy between 0/1 and 40 bits
    function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) {
        if (self._x <= uint144(-1)) {
            return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112)));
        }

        uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x);
        safeShiftBits -= safeShiftBits % 2;
        return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2)));
    }
}

// File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

// File: @uniswap/v2-periphery/contracts/libraries/UniswapV2OracleLibrary.sol

pragma solidity >=0.5.0;



// library with helper methods for oracles that are concerned with computing average prices
library UniswapV2OracleLibrary {
    using FixedPoint for *;

    // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1]
    function currentBlockTimestamp() internal view returns (uint32) {
        return uint32(block.timestamp % 2 ** 32);
    }

    // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
    function currentCumulativePrices(
        address pair
    ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) {
        blockTimestamp = currentBlockTimestamp();
        price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();
        price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();

        // if time has elapsed since the last update on the pair, mock the accumulated price values
        (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves();
        if (blockTimestampLast != blockTimestamp) {
            // subtraction overflow is desired
            uint32 timeElapsed = blockTimestamp - blockTimestampLast;
            // addition overflow is desired
            // counterfactual
            price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
            // counterfactual
            price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
        }
    }
}

// File: contracts/interop/UniswapV2.sol

pragma solidity ^0.6.0;


/**
 * @dev Minimal set of declarations for Uniswap V2 interoperability.
 */
interface Factory
{
	function getPair(address _tokenA, address _tokenB) external view returns (address _pair);
	function createPair(address _tokenA, address _tokenB) external returns (address _pair);
}

interface PoolToken is IERC20
{
}

interface Pair is PoolToken
{
	function token0() external view returns (address _token0);
	function token1() external view returns (address _token1);
	function price0CumulativeLast() external view returns (uint256 _price0CumulativeLast);
	function price1CumulativeLast() external view returns (uint256 _price1CumulativeLast);
	function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);
	function mint(address _to) external returns (uint256 _liquidity);
	function sync() external;
}

interface Router01
{
	function WETH() external pure returns (address _token);
	function addLiquidity(address _tokenA, address _tokenB, uint256 _amountADesired, uint256 _amountBDesired, uint256 _amountAMin, uint256 _amountBMin, address _to, uint256 _deadline) external returns (uint256 _amountA, uint256 _amountB, uint256 _liquidity);
	function removeLiquidity(address _tokenA, address _tokenB, uint256 _liquidity, uint256 _amountAMin, uint256 _amountBMin, address _to, uint256 _deadline) external returns (uint256 _amountA, uint256 _amountB);
	function swapExactTokensForTokens(uint256 _amountIn, uint256 _amountOutMin, address[] calldata _path, address _to, uint256 _deadline) external returns (uint256[] memory _amounts);
	function swapETHForExactTokens(uint256 _amountOut, address[] calldata _path, address _to, uint256 _deadline) external payable returns (uint256[] memory _amounts);
	function getAmountOut(uint256 _amountIn, uint256 _reserveIn, uint256 _reserveOut) external pure returns (uint256 _amountOut);
}

interface Router02 is Router01
{
}

// File: contracts/GPriceOracle.sol

pragma solidity ^0.6.0;




/**
 * @dev This library implements a TWAP oracle on Uniswap V2. Based on
 * https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleOracleSimple.sol
 */
library GPriceOracle
{
	using FixedPoint for FixedPoint.uq112x112;
	using FixedPoint for FixedPoint.uq144x112;
	using GPriceOracle for GPriceOracle.Self;

	uint256 constant DEFAULT_MINIMUM_INTERVAL = 23 hours;

	struct Self {
		address pair;
		bool use0;

		uint256 minimumInterval;

		uint256 priceCumulativeLast;
		uint32 blockTimestampLast;
		FixedPoint.uq112x112 priceAverage;
	}

	function init(Self storage _self) public
	{
		_self.pair = address(0);

		_self.minimumInterval = DEFAULT_MINIMUM_INTERVAL;
	}

	function active(Self storage _self) public view returns (bool _isActive)
	{
		return _self._active();
	}

	function activate(Self storage _self, address _pair, bool _use0) public
	{
		require(!_self._active(), "already active");
		require(_pair != address(0), "invalid pair");

		_self.pair = _pair;
		_self.use0 = _use0;

		_self.priceCumulativeLast = _use0 ? Pair(_pair).price0CumulativeLast() : Pair(_pair).price1CumulativeLast();

		uint112 reserve0;
		uint112 reserve1;
		(reserve0, reserve1, _self.blockTimestampLast) = Pair(_pair).getReserves();
		require(reserve0 > 0 && reserve1 > 0, "no reserves"); // ensure that there's liquidity in the pair
	}

	function changeMinimumInterval(Self storage _self, uint256 _minimumInterval) public
	{
		require(_minimumInterval > 0, "invalid interval");
		_self.minimumInterval = _minimumInterval;
	}

	function consultLastPrice(Self storage _self, uint256 _amountIn) public view returns (uint256 _amountOut)
	{
		require(_self._active(), "not active");

		return _self.priceAverage.mul(_amountIn).decode144();
	}

	function consultCurrentPrice(Self storage _self, uint256 _amountIn) public view returns (uint256 _amountOut)
	{
		require(_self._active(), "not active");

		(,, FixedPoint.uq112x112 memory _priceAverage) = _self._estimatePrice(false);
		return _priceAverage.mul(_amountIn).decode144();
	}

	function updatePrice(Self storage _self) public
	{
		require(_self._active(), "not active");

		(_self.priceCumulativeLast, _self.blockTimestampLast, _self.priceAverage) = _self._estimatePrice(true);
	}

	function _active(Self storage _self) internal view returns (bool _isActive)
	{
		return _self.pair != address(0);
	}

	function _estimatePrice(Self storage _self, bool _enforceTimeElapsed) internal view returns (uint256 _priceCumulative, uint32 _blockTimestamp, FixedPoint.uq112x112 memory _priceAverage)
	{
		uint256 _price0Cumulative;
		uint256 _price1Cumulative;
		(_price0Cumulative, _price1Cumulative, _blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrices(_self.pair);
		_priceCumulative = _self.use0 ? _price0Cumulative : _price1Cumulative;

		uint32 _timeElapsed = _blockTimestamp - _self.blockTimestampLast; // overflow is desired

		// ensure that at least one full interval has passed since the last update
		if (_enforceTimeElapsed) {
			require(_timeElapsed >= _self.minimumInterval, "minimum interval not elapsed");
		}

		// overflow is desired, casting never truncates
		// cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed
		_priceAverage = FixedPoint.uq112x112(uint224((_priceCumulative - _self.priceCumulativeLast) / _timeElapsed));
	}
}

// File: contracts/modules/Math.sol

pragma solidity ^0.6.0;

/**
 * @dev This library implements auxiliary math definitions.
 */
library Math
{
	function _min(uint256 _amount1, uint256 _amount2) internal pure returns (uint256 _minAmount)
	{
		return _amount1 < _amount2 ? _amount1 : _amount2;
	}

	function _max(uint256 _amount1, uint256 _amount2) internal pure returns (uint256 _maxAmount)
	{
		return _amount1 > _amount2 ? _amount1 : _amount2;
	}
}

// File: contracts/GElasticToken.sol

pragma solidity ^0.6.0;











/**
 * @notice This contract implements an ERC20 compatible elastic token that
 * rebases according to the TWAP of another token. Inspired by AMPL and YAM.
 */
contract GElasticToken is ElasticERC20, Ownable, ReentrancyGuard, GElastic
{
	using SafeMath for uint256;
	using GElasticTokenManager for GElasticTokenManager.Self;
	using GPriceOracle for GPriceOracle.Self;
	using Executor for Executor.Target[];

	address public immutable override referenceToken;

	GElasticTokenManager.Self etm;
	GPriceOracle.Self oracle;

	Executor.Target[] public targets;

	modifier onlyEOA()
	{
		require(tx.origin == _msgSender(), "not an externally owned account");
		_;
	}

	constructor (string memory _name, string memory _symbol, uint8 _decimals, address _referenceToken, uint256 _initialSupply)
		ElasticERC20(_name, _symbol) public
	{
		address _treasury = msg.sender;
		_setupDecimals(_decimals);
		assert(_referenceToken != address(0));
		referenceToken = _referenceToken;
		etm.init(_treasury);
		oracle.init();
		_mint(_treasury, _initialSupply);
	}

	function treasury() external view override returns (address _treasury)
	{
		return etm.treasury;
	}

	function rebaseMinimumDeviation() external view override returns (uint256 _rebaseMinimumDeviation)
	{
		return etm.rebaseMinimumDeviation;
	}

	function rebaseDampeningFactor() external view override returns (uint256 _rebaseDampeningFactor)
	{
		return etm.rebaseDampeningFactor;
	}

	function rebaseTreasuryMintPercent() external view override returns (uint256 _rebaseTreasuryMintPercent)
	{
		return etm.rebaseTreasuryMintPercent;
	}

	function rebaseTimingParameters() external view override returns (uint256 _rebaseMinimumInterval, uint256 _rebaseWindowOffset, uint256 _rebaseWindowLength)
	{
		return (etm.rebaseMinimumInterval, etm.rebaseWindowOffset, etm.rebaseWindowLength);
	}

	function rebaseAvailable() external view override returns (bool _rebaseAvailable)
	{
		return etm.rebaseAvailable();
	}

	function rebaseActive() external view override returns (bool _rebaseActive)
	{
		return etm.rebaseActive;
	}

	function lastRebaseTime() external view override returns (uint256 _lastRebaseTime)
	{
		return etm.lastRebaseTime;
	}

	function epoch() external view override returns (uint256 _epoch)
	{
		return etm.epoch;
	}

	function lastExchangeRate() external view override returns (uint256 _exchangeRate)
	{
		return oracle.consultLastPrice(10 ** uint256(decimals()));
	}

	function currentExchangeRate() external view override returns (uint256 _exchangeRate)
	{
		return oracle.consultCurrentPrice(10 ** uint256(decimals()));
	}

	function pair() external view override returns (address _pair)
	{
		return oracle.pair;
	}

	function rebase() external override onlyEOA nonReentrant
	{
		oracle.updatePrice();

		uint256 _exchangeRate = oracle.consultLastPrice(10 ** uint256(decimals()));

		uint256 _totalSupply = totalSupply();

		(uint256 _delta, bool _positive, uint256 _mintAmount) = etm.rebase(_exchangeRate, _totalSupply);

		_rebase(etm.epoch, _delta, _positive);

		if (_mintAmount > 0) {
			_mint(etm.treasury, _mintAmount);
		}

		// updates cached reserve balances wherever necessary
		Pair(oracle.pair).sync();
		targets.executeAll();
	}

	function activateOracle(address _pair) external override onlyOwner nonReentrant
	{
		address _token0 = Pair(_pair).token0();
		address _token1 = Pair(_pair).token1();
		require(_token0 == address(this) && _token1 == referenceToken || _token1 == address(this) && _token0 == referenceToken, "invalid pair");
		oracle.activate(_pair, _token0 == address(this));
	}

	function activateRebase() external override onlyOwner nonReentrant
	{
		require(oracle.active(), "not available");
		etm.activateRebase();
	}

	function setTreasury(address _newTreasury) external override onlyOwner nonReentrant
	{
		address _oldTreasury = etm.treasury;
		etm.setTreasury(_newTreasury);
		emit ChangeTreasury(_oldTreasury, _newTreasury);
	}

	function setRebaseMinimumDeviation(uint256 _newRebaseMinimumDeviation) external override onlyOwner nonReentrant
	{
		uint256 _oldRebaseMinimumDeviation = etm.rebaseMinimumDeviation;
		etm.setRebaseMinimumDeviation(_newRebaseMinimumDeviation);
		emit ChangeRebaseMinimumDeviation(_oldRebaseMinimumDeviation, _newRebaseMinimumDeviation);
	}

	function setRebaseDampeningFactor(uint256 _newRebaseDampeningFactor) external override onlyOwner nonReentrant
	{
		uint256 _oldRebaseDampeningFactor = etm.rebaseDampeningFactor;
		etm.setRebaseDampeningFactor(_newRebaseDampeningFactor);
		emit ChangeRebaseDampeningFactor(_oldRebaseDampeningFactor, _newRebaseDampeningFactor);
	}

	function setRebaseTreasuryMintPercent(uint256 _newRebaseTreasuryMintPercent) external override onlyOwner nonReentrant
	{
		uint256 _oldRebaseTreasuryMintPercent = etm.rebaseTreasuryMintPercent;
		etm.setRebaseTreasuryMintPercent(_newRebaseTreasuryMintPercent);
		emit ChangeRebaseTreasuryMintPercent(_oldRebaseTreasuryMintPercent, _newRebaseTreasuryMintPercent);
	}

	function setRebaseTimingParameters(uint256 _newRebaseMinimumInterval, uint256 _newRebaseWindowOffset, uint256 _newRebaseWindowLength) external override onlyOwner nonReentrant
	{
		uint256 _oldRebaseMinimumInterval = etm.rebaseMinimumInterval;
		uint256 _oldRebaseWindowOffset = etm.rebaseWindowOffset;
		uint256 _oldRebaseWindowLength = etm.rebaseWindowLength;
		etm.setRebaseTimingParameters(_newRebaseMinimumInterval, _newRebaseWindowOffset, _newRebaseWindowLength);
		oracle.changeMinimumInterval(_newRebaseMinimumInterval.sub(_newRebaseWindowLength));
		emit ChangeRebaseTimingParameters(_oldRebaseMinimumInterval, _oldRebaseWindowOffset, _oldRebaseWindowLength, _newRebaseMinimumInterval, _newRebaseWindowOffset, _newRebaseWindowLength);
	}

	function addPostRebaseTarget(address _to, bytes memory _data) external override onlyOwner nonReentrant
	{
		_addPostRebaseTarget(_to, _data);
	}

	function removePostRebaseTarget(uint256 _index) external override onlyOwner nonReentrant
	{
		_removePostRebaseTarget(_index);
	}

	function addBalancerPostRebaseTarget(address _pool) external onlyOwner nonReentrant
	{
		_addPostRebaseTarget(_pool, abi.encodeWithSignature("gulp(address)", address(this)));
	}

	function addUniswapV2PostRebaseTarget(address _pair) external onlyOwner nonReentrant
	{
		_addPostRebaseTarget(_pair, abi.encodeWithSignature("sync()"));
	}

	function _addPostRebaseTarget(address _to, bytes memory _data) internal
	{
		targets.addTarget(_to, _data);
		emit AddPostRebaseTarget(_to, _data);
	}

	function _removePostRebaseTarget(uint256 _index) internal
	{
		Executor.Target storage _target = targets[_index];
		address _to = _target.to;
		bytes memory _data = _target.data;
		targets.removeTarget(_index);
		emit RemovePostRebaseTarget(_to, _data);
	}

	function _rebase(uint256 _epoch, uint256 _delta, bool _positive) internal virtual
	{
		uint256 _oldScalingFactor = scalingFactor();
		uint256 _newScalingFactor;
		if (_delta == 0) {
			_newScalingFactor = _oldScalingFactor;
		} else {
			if (_positive) {
				_newScalingFactor = _oldScalingFactor.mul(uint256(1e18).add(_delta)).div(1e18);
			} else {
				_newScalingFactor = _oldScalingFactor.mul(uint256(1e18).sub(_delta)).div(1e18);
			}
		}
		if (_newScalingFactor > _oldScalingFactor) {
			_newScalingFactor = Math._min(_newScalingFactor, maxScalingFactor());
		}
		_setScalingFactor(_newScalingFactor);
		emit Rebase(_epoch, _oldScalingFactor, _newScalingFactor);
	}
}

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


pragma solidity >=0.6.0 <0.8.0;




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

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

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

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

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

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

// File: contracts/GLPMining.sol

pragma solidity ^0.6.0;

/**
 * @dev This interface exposes the base functionality of GLPMiningToken.
 */
interface GLPMining
{
	// view functions
	function reserveToken() external view returns (address _reserveToken);
	function rewardsToken() external view returns (address _rewardsToken);
	function treasury() external view returns (address _treasury);
	function performanceFee() external view returns (uint256 _performanceFee);
	function rewardRatePerWeek() external view returns (uint256 _rewardRatePerWeek);
	function calcSharesFromCost(uint256 _cost) external view returns (uint256 _shares);
	function calcCostFromShares(uint256 _shares) external view returns (uint256 _cost);
	function calcSharesFromTokenAmount(address _token, uint256 _amount) external view returns (uint256 _shares);
	function calcTokenAmountFromShares(address _token, uint256 _shares) external view returns (uint256 _amount);
	function totalReserve() external view returns (uint256 _totalReserve);
	function rewardInfo() external view returns (uint256 _lockedReward, uint256 _unlockedReward, uint256 _rewardPerBlock);
	function pendingFees() external view returns (uint256 _feeShares);

	// open functions
	function deposit(uint256 _cost) external;
	function withdraw(uint256 _shares) external;
	function depositToken(address _token, uint256 _amount, uint256 _minShares) external;
	function withdrawToken(address _token, uint256 _shares, uint256 _minAmount) external;
	function gulpRewards(uint256 _minCost) external;
	function gulpFees() external;

	// priviledged functions
	function setTreasury(address _treasury) external;
	function setPerformanceFee(uint256 _performanceFee) external;
	function setRewardRatePerWeek(uint256 _rewardRatePerWeek) external;

	// emitted events
	event ChangeTreasury(address _oldTreasury, address _newTreasury);
	event ChangePerformanceFee(uint256 _oldPerformanceFee, uint256 _newPerformanceFee);
	event ChangeRewardRatePerWeek(uint256 _oldRewardRatePerWeek, uint256 _newRewardRatePerWeek);
}

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


pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

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

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


pragma solidity >=0.6.0 <0.8.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 IERC20;` 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));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    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. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "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/modules/Transfers.sol

pragma solidity ^0.6.0;



/**
 * @dev This library abstracts ERC-20 operations in the context of the current
 * contract.
 */
library Transfers
{
	using SafeERC20 for IERC20;

	/**
	 * @dev Retrieves a given ERC-20 token balance for the current contract.
	 * @param _token An ERC-20 compatible token address.
	 * @return _balance The current contract balance of the given ERC-20 token.
	 */
	function _getBalance(address _token) internal view returns (uint256 _balance)
	{
		return IERC20(_token).balanceOf(address(this));
	}

	/**
	 * @dev Allows a spender to access a given ERC-20 balance for the current contract.
	 * @param _token An ERC-20 compatible token address.
	 * @param _to The spender address.
	 * @param _amount The exact spending allowance amount.
	 */
	function _approveFunds(address _token, address _to, uint256 _amount) internal
	{
		uint256 _allowance = IERC20(_token).allowance(address(this), _to);
		if (_allowance > _amount) {
			IERC20(_token).safeDecreaseAllowance(_to, _allowance - _amount);
		}
		else
		if (_allowance < _amount) {
			IERC20(_token).safeIncreaseAllowance(_to, _amount - _allowance);
		}
	}

	/**
	 * @dev Transfer a given ERC-20 token amount into the current contract.
	 * @param _token An ERC-20 compatible token address.
	 * @param _from The source address.
	 * @param _amount The amount to be transferred.
	 */
	function _pullFunds(address _token, address _from, uint256 _amount) internal
	{
		if (_amount == 0) return;
		IERC20(_token).safeTransferFrom(_from, address(this), _amount);
	}

	/**
	 * @dev Transfer a given ERC-20 token amount from the current contract.
	 * @param _token An ERC-20 compatible token address.
	 * @param _to The target address.
	 * @param _amount The amount to be transferred.
	 */
	function _pushFunds(address _token, address _to, uint256 _amount) internal
	{
		if (_amount == 0) return;
		IERC20(_token).safeTransfer(_to, _amount);
	}
}

// File: contracts/network/$.sol

pragma solidity ^0.6.0;

/**
 * @dev This library is provided for convenience. It is the single source for
 *      the current network and all related hardcoded contract addresses.
 */
library $
{
	address constant AAVE = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;

	address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

	address constant UniswapV2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;

	address constant UniswapV2_ROUTER02 = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
}

// File: contracts/modules/UniswapV2LiquidityPoolAbstraction.sol

pragma solidity ^0.6.0;







/**
 * @dev This library provides functionality to facilitate adding/removing
 * single-asset liquidity to/from a Uniswap V2 pool.
 */
library UniswapV2LiquidityPoolAbstraction
{
	using SafeMath for uint256;

	function _estimateJoinPool(address _pair, address _token, uint256 _amount) internal view returns (uint256 _shares)
	{
		if (_amount == 0) return 0;
		address _router = $.UniswapV2_ROUTER02;
		address _token0 = Pair(_pair).token0();
		(uint256 _reserve0, uint256 _reserve1,) = Pair(_pair).getReserves();
		uint256 _balance = _token == _token0 ? _reserve0 : _reserve1;
		uint256 _otherBalance = _token == _token0 ? _reserve1 : _reserve0;
		uint256 _totalSupply = Pair(_pair).totalSupply();
		uint256 _swapAmount = _calcSwapOutputFromInput(_balance, _amount);
		if (_swapAmount == 0) _swapAmount = _amount / 2;
		uint256 _leftAmount = _amount.sub(_swapAmount);
		uint256 _otherAmount = Router02(_router).getAmountOut(_swapAmount, _balance, _otherBalance);
		_shares = Math._min(_totalSupply.mul(_leftAmount) / _balance.add(_swapAmount), _totalSupply.mul(_otherAmount) / _otherBalance.sub(_otherAmount));
		return _shares;
	}

	function _estimateExitPool(address _pair, address _token, uint256 _shares) internal view returns (uint256 _amount)
	{
		if (_shares == 0) return 0;
		address _router = $.UniswapV2_ROUTER02;
		address _token0 = Pair(_pair).token0();
		(uint256 _reserve0, uint256 _reserve1,) = Pair(_pair).getReserves();
		uint256 _balance = _token == _token0 ? _reserve0 : _reserve1;
		uint256 _otherBalance = _token == _token0 ? _reserve1 : _reserve0;
		uint256 _totalSupply = Pair(_pair).totalSupply();
		uint256 _baseAmount = _balance.mul(_shares) / _totalSupply;
		uint256 _swapAmount = _otherBalance.mul(_shares) / _totalSupply;
		uint256 _additionalAmount = Router02(_router).getAmountOut(_swapAmount, _otherBalance.sub(_swapAmount), _balance.sub(_baseAmount));
		_amount = _baseAmount.add(_additionalAmount);
		return _amount;
	}

	function _joinPool(address _pair, address _token, uint256 _amount, uint256 _minShares) internal returns (uint256 _shares)
	{
		if (_amount == 0) return 0;
		address _router = $.UniswapV2_ROUTER02;
		address _token0 = Pair(_pair).token0();
		address _token1 = Pair(_pair).token1();
		address _otherToken = _token == _token0 ? _token1 : _token0;
		(uint256 _reserve0, uint256 _reserve1,) = Pair(_pair).getReserves();
		uint256 _swapAmount = _calcSwapOutputFromInput(_token == _token0 ? _reserve0 : _reserve1, _amount);
		if (_swapAmount == 0) _swapAmount = _amount / 2;
		uint256 _leftAmount = _amount.sub(_swapAmount);
		Transfers._approveFunds(_token, _router, _amount);
		address[] memory _path = new address[](2);
		_path[0] = _token;
		_path[1] = _otherToken;
		uint256 _otherAmount = Router02(_router).swapExactTokensForTokens(_swapAmount, 1, _path, address(this), uint256(-1))[1];
		Transfers._approveFunds(_otherToken, _router, _otherAmount);
		(,,_shares) = Router02(_router).addLiquidity(_token, _otherToken, _leftAmount, _otherAmount, 1, 1, address(this), uint256(-1));
		require(_shares >= _minShares, "high slippage");
		return _shares;
	}

	function _exitPool(address _pair, address _token, uint256 _shares, uint256 _minAmount) internal returns (uint256 _amount)
	{
		if (_shares == 0) return 0;
		address _router = $.UniswapV2_ROUTER02;
		address _token0 = Pair(_pair).token0();
		address _token1 = Pair(_pair).token1();
		address _otherToken = _token == _token0 ? _token1 : _token0;
		Transfers._approveFunds(_pair, _router, _shares);
		(uint256 _baseAmount, uint256 _swapAmount) = Router02(_router).removeLiquidity(_token, _otherToken, _shares, 1, 1, address(this), uint256(-1));
		Transfers._approveFunds(_otherToken, _router, _swapAmount);
		address[] memory _path = new address[](2);
		_path[0] = _otherToken;
		_path[1] = _token;
		uint256 _additionalAmount = Router02(_router).swapExactTokensForTokens(_swapAmount, 1, _path, address(this), uint256(-1))[1];
		_amount = _baseAmount.add(_additionalAmount);
	        require(_amount >= _minAmount, "high slippage");
		return _amount;
	}

	function _calcSwapOutputFromInput(uint256 _reserveAmount, uint256 _inputAmount) private pure returns (uint256)
	{
		return Babylonian.sqrt(_reserveAmount.mul(_inputAmount.mul(3988000).add(_reserveAmount.mul(3988009)))).sub(_reserveAmount.mul(1997)) / 1994;
	}
}

// File: contracts/GLPMiningToken.sol

pragma solidity ^0.6.0;







/**
 * @notice This contract implements liquidity mining for staking Uniswap V2
 * shares.
 */
contract GLPMiningToken is ERC20, Ownable, ReentrancyGuard, GLPMining
{
	uint256 constant MAXIMUM_PERFORMANCE_FEE = 50e16; // 50%

	uint256 constant BLOCKS_PER_WEEK = 7 days / uint256(13 seconds);
	uint256 constant DEFAULT_PERFORMANCE_FEE = 10e16; // 10%
	uint256 constant DEFAULT_REWARD_RATE_PER_WEEK = 10e16; // 10%

	address public immutable override reserveToken;
	address public immutable override rewardsToken;

	address public override treasury;

	uint256 public override performanceFee = DEFAULT_PERFORMANCE_FEE;
	uint256 public override rewardRatePerWeek = DEFAULT_REWARD_RATE_PER_WEEK;

	uint256 lastContractBlock = block.number;
	uint256 lastRewardPerBlock = 0;
	uint256 lastUnlockedReward = 0;
	uint256 lastLockedReward = 0;

	uint256 lastTotalSupply = 1;
	uint256 lastTotalReserve = 1;

	constructor (string memory _name, string memory _symbol, uint8 _decimals, address _reserveToken, address _rewardsToken)
		ERC20(_name, _symbol) public
	{
		address _treasury = msg.sender;
		_setupDecimals(_decimals);
		assert(_reserveToken != address(0));
		assert(_rewardsToken != address(0));
		assert(_reserveToken != _rewardsToken);
		reserveToken = _reserveToken;
		rewardsToken = _rewardsToken;
		treasury = _treasury;
		// just after creation it must transfer 1 wei from reserveToken
		// into this contract
		// this must be performed manually because we cannot approve
		// the spending by this contract before it exists
		// Transfers._pullFunds(_reserveToken, _from, 1);
		_mint(address(this), 1);
	}

	function calcSharesFromCost(uint256 _cost) public view override returns (uint256 _shares)
	{
		return _cost.mul(totalSupply()).div(totalReserve());
	}

	function calcCostFromShares(uint256 _shares) public view override returns (uint256 _cost)
	{
		return _shares.mul(totalReserve()).div(totalSupply());
	}

	function calcSharesFromTokenAmount(address _token, uint256 _amount) external view override returns (uint256 _shares)
	{
		uint256 _cost = UniswapV2LiquidityPoolAbstraction._estimateJoinPool(reserveToken, _token, _amount);
		return calcSharesFromCost(_cost);
	}

	function calcTokenAmountFromShares(address _token, uint256 _shares) external view override returns (uint256 _amount)
	{
		uint256 _cost = calcCostFromShares(_shares);
		return UniswapV2LiquidityPoolAbstraction._estimateExitPool(reserveToken, _token, _cost);
	}

	function totalReserve() public view override returns (uint256 _totalReserve)
	{
		return Transfers._getBalance(reserveToken);
	}

	function rewardInfo() external view override returns (uint256 _lockedReward, uint256 _unlockedReward, uint256 _rewardPerBlock)
	{
		(, _rewardPerBlock, _unlockedReward, _lockedReward) = _calcCurrentRewards();
		return (_lockedReward, _unlockedReward, _rewardPerBlock);
	}

	function pendingFees() external view override returns (uint256 _feeShares)
	{
		return _calcFees();
	}

	function deposit(uint256 _cost) external override nonReentrant
	{
		address _from = msg.sender;
		uint256 _shares = calcSharesFromCost(_cost);
		Transfers._pullFunds(reserveToken, _from, _cost);
		_mint(_from, _shares);
	}

	function withdraw(uint256 _shares) external override nonReentrant
	{
		address _from = msg.sender;
		uint256 _cost = calcCostFromShares(_shares);
		Transfers._pushFunds(reserveToken, _from, _cost);
		_burn(_from, _shares);
	}

	function depositToken(address _token, uint256 _amount, uint256 _minShares) external override nonReentrant
	{
		address _from = msg.sender;
		uint256 _minCost = calcCostFromShares(_minShares);
		Transfers._pullFunds(_token, _from, _amount);
		uint256 _cost = UniswapV2LiquidityPoolAbstraction._joinPool(reserveToken, _token, _amount, _minCost);
		uint256 _shares = _cost.mul(totalSupply()).div(totalReserve().sub(_cost));
		_mint(_from, _shares);
	}

	function withdrawToken(address _token, uint256 _shares, uint256 _minAmount) external override nonReentrant
	{
		address _from = msg.sender;
		uint256 _cost = calcCostFromShares(_shares);
		uint256 _amount = UniswapV2LiquidityPoolAbstraction._exitPool(reserveToken, _token, _cost, _minAmount);
		Transfers._pushFunds(_token, _from, _amount);
		_burn(_from, _shares);
	}

	function gulpRewards(uint256 _minCost) external override nonReentrant
	{
		_updateRewards();
		UniswapV2LiquidityPoolAbstraction._joinPool(reserveToken, rewardsToken, lastUnlockedReward, _minCost);
		lastUnlockedReward = 0;
	}

	function gulpFees() external override nonReentrant
	{
		uint256 _feeShares = _calcFees();
		if (_feeShares > 0) {
			lastTotalSupply = totalSupply();
			lastTotalReserve = totalReserve();
			_mint(treasury, _feeShares);
		}
	}

	function setTreasury(address _newTreasury) external override onlyOwner nonReentrant
	{
		require(_newTreasury != address(0), "invalid address");
		address _oldTreasury = treasury;
		treasury = _newTreasury;
		emit ChangeTreasury(_oldTreasury, _newTreasury);
	}

	function setPerformanceFee(uint256 _newPerformanceFee) external override onlyOwner nonReentrant
	{
		require(_newPerformanceFee <= MAXIMUM_PERFORMANCE_FEE, "invalid rate");
		uint256 _oldPerformanceFee = performanceFee;
		performanceFee = _newPerformanceFee;
		emit ChangePerformanceFee(_oldPerformanceFee, _newPerformanceFee);
	}

	function setRewardRatePerWeek(uint256 _newRewardRatePerWeek) external override onlyOwner nonReentrant
	{
		require(_newRewardRatePerWeek <= 1e18, "invalid rate");
		uint256 _oldRewardRatePerWeek = rewardRatePerWeek;
		rewardRatePerWeek = _newRewardRatePerWeek;
		emit ChangeRewardRatePerWeek(_oldRewardRatePerWeek, _newRewardRatePerWeek);
	}

	function _updateRewards() internal
	{
		(lastContractBlock, lastRewardPerBlock, lastUnlockedReward, lastLockedReward) = _calcCurrentRewards();
		uint256 _balanceReward = Transfers._getBalance(rewardsToken);
		uint256 _totalReward = lastLockedReward.add(lastUnlockedReward);
		if (_balanceReward > _totalReward) {
			uint256 _newLockedReward = _balanceReward.sub(_totalReward);
			uint256 _newRewardPerBlock = _calcRewardPerBlock(_newLockedReward);
			lastRewardPerBlock = lastRewardPerBlock.add(_newRewardPerBlock);
			lastLockedReward = lastLockedReward.add(_newLockedReward);
		}
		else
		if (_balanceReward < _totalReward) {
			uint256 _removedLockedReward = _totalReward.sub(_balanceReward);
			if (_removedLockedReward >= lastLockedReward) {
				_removedLockedReward = lastLockedReward;
			}
			uint256 _removedRewardPerBlock = _calcRewardPerBlock(_removedLockedReward);
			if (_removedLockedReward >= lastLockedReward) {
				_removedRewardPerBlock = lastRewardPerBlock;
			}
			lastRewardPerBlock = lastRewardPerBlock.sub(_removedRewardPerBlock);
			lastLockedReward = lastLockedReward.sub(_removedLockedReward);
			lastUnlockedReward = _balanceReward.sub(lastLockedReward);
		}
	}

	function _calcFees() internal view returns (uint256 _feeShares)
	{
		uint256 _oldTotalSupply = lastTotalSupply;
		uint256 _oldTotalReserve = lastTotalReserve;

		uint256 _newTotalSupply = totalSupply();
		uint256 _newTotalReserve = totalReserve();

		// calculates the profit using the following formula
		// ((P1 - P0) * S1 * f) / P1
		// where P1 = R1 / S1 and P0 = R0 / S0
		uint256 _positive = _oldTotalSupply.mul(_newTotalReserve);
		uint256 _negative = _newTotalSupply.mul(_oldTotalReserve);
		if (_positive > _negative) {
			uint256 _profitCost = _positive.sub(_negative).div(_oldTotalSupply);
			uint256 _feeCost = _profitCost.mul(performanceFee).div(1e18);
			return calcSharesFromCost(_feeCost);
		}

		return 0;
	}

	function _calcCurrentRewards() internal view returns (uint256 _currentContractBlock, uint256 _currentRewardPerBlock, uint256 _currentUnlockedReward, uint256 _currentLockedReward)
	{
		uint256 _contractBlock = lastContractBlock;
		uint256 _rewardPerBlock = lastRewardPerBlock;
		uint256 _unlockedReward = lastUnlockedReward;
		uint256 _lockedReward = lastLockedReward;
		if (_contractBlock < block.number) {
			uint256 _week = _contractBlock.div(BLOCKS_PER_WEEK);
			uint256 _offset = _contractBlock.mod(BLOCKS_PER_WEEK);

			_contractBlock = block.number;
			uint256 _currentWeek = _contractBlock.div(BLOCKS_PER_WEEK);
			uint256 _currentOffset = _contractBlock.mod(BLOCKS_PER_WEEK);

			while (_week < _currentWeek) {
				uint256 _blocks = BLOCKS_PER_WEEK.sub(_offset);
				uint256 _reward = _blocks.mul(_rewardPerBlock);
				_unlockedReward = _unlockedReward.add(_reward);
				_lockedReward = _lockedReward.sub(_reward);
				_rewardPerBlock = _calcRewardPerBlock(_lockedReward);
				_week++;
				_offset = 0;
			}

			uint256 _blocks = _currentOffset.sub(_offset);
			uint256 _reward = _blocks.mul(_rewardPerBlock);
			_unlockedReward = _unlockedReward.add(_reward);
			_lockedReward = _lockedReward.sub(_reward);
		}
		return (_contractBlock, _rewardPerBlock, _unlockedReward, _lockedReward);
	}

	function _calcRewardPerBlock(uint256 _lockedReward) internal view returns (uint256 _rewardPerBlock)
	{
		return _lockedReward.mul(rewardRatePerWeek).div(1e18).div(BLOCKS_PER_WEEK);
	}
}

// File: contracts/interop/WrappedEther.sol

pragma solidity ^0.6.0;


/**
 * @dev Minimal set of declarations for WETH interoperability.
 */
interface WETH is IERC20
{
	function deposit() external payable;
	function withdraw(uint256 _amount) external;
}

// File: contracts/modules/Wrapping.sol

pragma solidity ^0.6.0;



/**
 * @dev This library abstracts Wrapped Ether operations.
 */
library Wrapping
{
	/**
	 * @dev Sends some ETH to the Wrapped Ether contract in exchange for WETH.
	 * @param _amount The amount of ETH to be wrapped.
	 */
	function _wrap(uint256 _amount) internal
	{
		WETH($.WETH).deposit{value: _amount}();
	}

	/**
	 * @dev Receives some ETH from the Wrapped Ether contract in exchange for WETH.
	 *      Note that the contract using this library function must declare a
	 *      payable receive/fallback function.
	 * @param _amount The amount of ETH to be unwrapped.
	 */
	function _unwrap(uint256 _amount) internal
	{
		WETH($.WETH).withdraw(_amount);
	}
}

// File: contracts/GEtherBridge.sol

pragma solidity ^0.6.0;




contract GEtherBridge
{
	function deposit(address _stakeToken, uint256 _minShares) external payable
	{
		address _from = msg.sender;
		uint256 _amount = msg.value;
		address _token = $.WETH;
		Wrapping._wrap(_amount);
		Transfers._approveFunds(_token, _stakeToken, _amount);
		GLPMining(_stakeToken).depositToken(_token, _amount, _minShares);
		uint256 _shares = Transfers._getBalance(_stakeToken);
		Transfers._pushFunds(_stakeToken, _from, _shares);
	}

	function withdraw(address _stakeToken, uint256 _shares, uint256 _minAmount) external
	{
		address payable _from = msg.sender;
		address _token = $.WETH;
		Transfers._pullFunds(_stakeToken, _from, _shares);
		GLPMining(_stakeToken).withdrawToken(_token, _shares, _minAmount);
		uint256 _amount = Transfers._getBalance(_token);
		Wrapping._unwrap(_amount);
		_from.transfer(_amount);
	}

	receive() external payable {} // not to be used directly
}

// File: contracts/GTokens.sol

pragma solidity ^0.6.0;






/**
 * @notice Definition of rAAVE. It is an elastic supply token that uses AAVE
 * as reference token.
 */
contract rAAVE is GElasticToken
{
	constructor (uint256 _initialSupply)
		GElasticToken("rebase AAVE", "rAAVE", 18, $.AAVE, _initialSupply) public
	{
	}
}

/**
 * @notice Definition of stkAAVE/rAAVE. It provides mining or reward rAAVE when
 * providing liquidity to the AAVE/rAAVE pool.
 */
contract stkAAVE_rAAVE is GLPMiningToken
{
	constructor (address _AAVE_rAAVE, address _rAAVE)
		GLPMiningToken("staked AAVE/rAAVE", "stkAAVE/rAAVE", 18, _AAVE_rAAVE, _rAAVE) public
	{
	}
}

/**
 * @notice Definition of stkGRO/rAAVE. It provides mining or reward rAAVE when
 * providing liquidity to the GRO/rAAVE pool.
 */
contract stkGRO_rAAVE is GLPMiningToken
{
	constructor (address _GRO_rAAVE, address _rAAVE)
		GLPMiningToken("staked GRO/rAAVE", "stkGRO/rAAVE", 18, _GRO_rAAVE, _rAAVE) public
	{
	}
}

/**
 * @notice Definition of stkETH/rAAVE. It provides mining or reward rAAVE when
 * providing liquidity to the WETH/rAAVE pool.
 */
contract stkETH_rAAVE is GLPMiningToken
{
	constructor (address _ETH_rAAVE, address _rAAVE)
		GLPMiningToken("staked ETH/rAAVE", "stkETH/rAAVE", 18, _ETH_rAAVE, _rAAVE) public
	{
	}
}

// File: contracts/GTokenRegistry.sol

pragma solidity ^0.6.0;


/**
 * @notice This contract allows external agents to detect when new GTokens
 *         are deployed to the network.
 */
contract GTokenRegistry is Ownable
{
	/**
	 * @notice Registers a new gToken.
	 * @param _growthToken The address of the token being registered.
	 * @param _oldGrowthToken The address of the token implementation
	 *                        being replaced, for upgrades, or 0x0 0therwise.
	 */
	function registerNewToken(address _growthToken, address _oldGrowthToken) public onlyOwner
	{
		emit NewToken(_growthToken, _oldGrowthToken);
	}

	event NewToken(address indexed _growthToken, address indexed _oldGrowthToken);
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_initialSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"AddPostRebaseTarget","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldRebaseDampeningFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseDampeningFactor","type":"uint256"}],"name":"ChangeRebaseDampeningFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldRebaseMinimumDeviation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseMinimumDeviation","type":"uint256"}],"name":"ChangeRebaseMinimumDeviation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldRebaseMinimumInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_oldRebaseWindowOffset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_oldRebaseWindowLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseMinimumInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseWindowOffset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseWindowLength","type":"uint256"}],"name":"ChangeRebaseTimingParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldRebaseTreasuryMintPercent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRebaseTreasuryMintPercent","type":"uint256"}],"name":"ChangeRebaseTreasuryMintPercent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldTreasury","type":"address"},{"indexed":false,"internalType":"address","name":"_newTreasury","type":"address"}],"name":"ChangeTreasury","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":true,"internalType":"uint256","name":"_epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_oldScalingFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newScalingFactor","type":"uint256"}],"name":"Rebase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"RemovePostRebaseTarget","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"activateOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"activateRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"addBalancerPostRebaseTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"addPostRebaseTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"addUniswapV2PostRebaseTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"_allowance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"_balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentExchangeRate","outputs":[{"internalType":"uint256","name":"_exchangeRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"_decimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"_epoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastExchangeRate","outputs":[{"internalType":"uint256","name":"_exchangeRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRebaseTime","outputs":[{"internalType":"uint256","name":"_lastRebaseTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxScalingFactor","outputs":[{"internalType":"uint256","name":"_maxScalingFactor","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"_pair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebaseActive","outputs":[{"internalType":"bool","name":"_rebaseActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseAvailable","outputs":[{"internalType":"bool","name":"_rebaseAvailable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseDampeningFactor","outputs":[{"internalType":"uint256","name":"_rebaseDampeningFactor","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseMinimumDeviation","outputs":[{"internalType":"uint256","name":"_rebaseMinimumDeviation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseTimingParameters","outputs":[{"internalType":"uint256","name":"_rebaseMinimumInterval","type":"uint256"},{"internalType":"uint256","name":"_rebaseWindowOffset","type":"uint256"},{"internalType":"uint256","name":"_rebaseWindowLength","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseTreasuryMintPercent","outputs":[{"internalType":"uint256","name":"_rebaseTreasuryMintPercent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referenceToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"removePostRebaseTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scalingFactor","outputs":[{"internalType":"uint256","name":"_scalingFactor","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRebaseDampeningFactor","type":"uint256"}],"name":"setRebaseDampeningFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRebaseMinimumDeviation","type":"uint256"}],"name":"setRebaseMinimumDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRebaseMinimumInterval","type":"uint256"},{"internalType":"uint256","name":"_newRebaseWindowOffset","type":"uint256"},{"internalType":"uint256","name":"_newRebaseWindowLength","type":"uint256"}],"name":"setRebaseTimingParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRebaseTreasuryMintPercent","type":"uint256"}],"name":"setRebaseTreasuryMintPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"targets","outputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"_supply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"_treasury","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"unscaledBalanceOf","outputs":[{"internalType":"uint256","name":"_balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unscaledTotalSupply","outputs":[{"internalType":"uint256","name":"_supply","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b50604051620057e2380380620057e2833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600b81526020017f72656261736520414156450000000000000000000000000000000000000000008152506040518060400160405280600581526020017f72414156450000000000000000000000000000000000000000000000000000008152506012737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98484848160039080519060200190620000e6929190620008e1565b508060049080519060200190620000ff929190620008e1565b506200011260126200036760201b60201c565b50506000620001266200039260201b60201c565b905080600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35060016008819055506000339050620001e3846200036760201b60201c565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156200021b57fe5b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600973c2905817f1e2cf283248288349b5ea26622bc75163d9a888b99091836040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060006040518083038186803b158015620002c357600080fd5b505af4158015620002d8573d6000803e3d6000fd5b50505050601373ac75ac9c4f1136041170663a347caca88d47a5dc63cbd0018890916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b1580156200032f57600080fd5b505af415801562000344573d6000803e3d6000fd5b505050506200035a81836200039a60201b60201c565b5050505050505062000987565b80600560006101000a81548160ff021916908360ff1602179055508060ff16600a0a60068190555050565b600033905090565b6000620003b0826006546200062460201b60201c565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141562000456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b6200046a600084846200066860201b60201c565b62000486816002546200066d60201b620037bf1790919060201c565b6002819055506000620004a1600254620006f660201b60201c565b90508060065411156200051c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f756e737570706f72746564207363616c696e6720666163746f7200000000000081525060200191505060405180910390fd5b6200057582600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200066d60201b620037bf1790919060201c565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a350505050565b600062000660826200064c601860ff16600a0a866200073960201b620038471790919060201c565b620007c460201b620038cd1790919060201c565b905092915050565b505050565b600080828401905083811015620006ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600062000732827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff620007c460201b620038cd1790919060201c565b9050919050565b6000808314156200074e5760009050620007be565b60008284029050828482816200076057fe5b0414620007b9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180620057c16021913960400191505060405180910390fd5b809150505b92915050565b60006200080e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200081660201b60201c565b905092915050565b60008083118290620008c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200088a5780820151818401526020810190506200086d565b50505050905090810190601f168015620008b85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581620008d357fe5b049050809150509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200092457805160ff191683800117855562000955565b8280016001018555821562000955579182015b828111156200095457825182559160200191906001019062000937565b5b50905062000964919062000968565b5090565b5b808211156200098357600081600090555060010162000969565b5090565b60805160601c614e12620009af60003980610f2a528061223352806122bf5250614e126000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637a8a014711610151578063b65e7fff116100c3578063dd62ed3e11610087578063dd62ed3e14610bcb578063ed3437f814610c43578063f0f4426014610c61578063f2fde38b14610ca5578063f552dbd714610ce9578063f911474514610d4157610274565b8063b65e7fff14610a42578063baf3da0f14610b1d578063d2304c3614610b3b578063d2e34c7514610b7f578063da82364c14610b9d57610274565b80639764e249116101155780639764e24914610900578063a36849771461091e578063a457c2d71461093c578063a8aa1b31146109a0578063a9059cbb146109d4578063af14052c14610a3857610274565b80637a8a0147146107b957806381e52be6146107fd5780638da5cb5b1461082b578063900cf0cf1461085f57806395d89b411461087d57610274565b806339509351116101ea57806360e9825a116101ae57806360e9825a146106b757806361d027b3146106e557806364eea6821461071957806367edde1d1461073757806370a0823114610757578063715018a6146107af57610274565b806339509351146105b757806341c0cccc1461061b57806349bdd0171461065f5780635a94687e146106695780635a9932031461069757610274565b806316250fd41161023c57806316250fd41461047657806318160ddd146104b85780631924063e146104d657806323b872dd146104f45780632a67296114610578578063313ce5671461059657610274565b806306fdde0314610279578063095ea7b3146102fc5780630a39ce021461036057806311d3e6c4146104245780631265b65114610442575b600080fd5b610281610d6d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102c15780820151818401526020810190506102a6565b50505050905090810190601f1680156102ee5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103486004803603604081101561031257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e0f565b60405180821515815260200191505060405180910390f35b61038c6004803603602081101561037657600080fd5b8101908080359060200190929190505050610e2d565b604051808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103e85780820151818401526020810190506103cd565b50505050905090810190601f1680156104155780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61042c610f16565b6040518082815260200191505060405180910390f35b61044a610f28565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104b66004803603606081101561048c57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610f4c565b005b6104c061122a565b6040518082815260200191505060405180910390f35b6104de61123f565b6040518082815260200191505060405180910390f35b6105606004803603606081101561050a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061124c565b60405180821515815260200191505060405180910390f35b610580611324565b6040518082815260200191505060405180910390f35b61059e611331565b604051808260ff16815260200191505060405180910390f35b610603600480360360408110156105cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611348565b60405180821515815260200191505060405180910390f35b61065d6004803603602081101561063157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113fa565b005b6106676115fd565b005b6106956004803603602081101561067f57600080fd5b81019080803590602001909291905050506118bb565b005b61069f611acd565b60405180821515815260200191505060405180910390f35b6106e3600480360360208110156106cd57600080fd5b8101908080359060200190929190505050611b61565b005b6106ed611d73565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610721611da0565b6040518082815260200191505060405180910390f35b61073f611dad565b60405180821515815260200191505060405180910390f35b6107996004803603602081101561076d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611dc7565b6040518082815260200191505060405180910390f35b6107b7611e1b565b005b6107fb600480360360208110156107cf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611fa6565b005b6108296004803603602081101561081357600080fd5b810190808035906020019092919050505061244d565b005b61083361265f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610867612689565b6040518082815260200191505060405180910390f35b610885612695565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108c55780820151818401526020810190506108aa565b50505050905090810190601f1680156108f25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610908612737565b6040518082815260200191505060405180910390f35b6109266127e0565b6040518082815260200191505060405180910390f35b6109886004803603604081101561095257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612889565b60405180821515815260200191505060405180910390f35b6109a8612955565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a20600480360360408110156109ea57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612982565b60405180821515815260200191505060405180910390f35b610a406129a0565b005b610b1b60048036036040811015610a5857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610a9557600080fd5b820183602082011115610aa757600080fd5b80359060200191846001830284011164010000000083111715610ac957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d87565b005b610b25612ee8565b6040518082815260200191505060405180910390f35b610b7d60048036036020811015610b5157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ef2565b005b610b876130d4565b6040518082815260200191505060405180910390f35b610bc960048036036020811015610bb357600080fd5b81019080803590602001909291905050506130e1565b005b610c2d60048036036040811015610be157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613240565b6040518082815260200191505060405180910390f35b610c4b6132c6565b6040518082815260200191505060405180910390f35b610ca360048036036020811015610c7757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506132d0565b005b610ce760048036036020811015610cbb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613544565b005b610d2b60048036036020811015610cff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613754565b6040518082815260200191505060405180910390f35b610d4961379d565b60405180848152602001838152602001828152602001935050505060405180910390f35b606060038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e055780601f10610dda57610100808354040283529160200191610e05565b820191906000526020600020905b815481529060010190602001808311610de857829003601f168201915b5050505050905090565b6000610e23610e1c613917565b848461391f565b6001905092915050565b60188181548110610e3a57fe5b90600052602060002090600202016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f0c5780601f10610ee157610100808354040283529160200191610f0c565b820191906000526020600020905b815481529060010190602001808311610eef57829003601f168201915b5050505050905082565b6000610f23600254613b15565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610f54613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611016576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6002600854141561108f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550600060096004015490506000600960050154905060006009600601549050600973c2905817f1e2cf283248288349b5ea26622bc751637944c78d90918888886040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060006040518083038186803b15801561111f57600080fd5b505af4158015611133573d6000803e3d6000fd5b50505050601373ac75ac9c4f1136041170663a347caca88d47a5dc63b6e05b399091611168878a613b5190919063ffffffff16565b6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156111a357600080fd5b505af41580156111b7573d6000803e3d6000fd5b505050507f67b96153d463108a59f5389db0f3107f004c874e2d388a64ce0b940d7bd8086783838389898960405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390a15050506001600881905550505050565b600061123a600254600654613b9b565b905090565b6000600960080154905090565b6000611259848484613bd1565b61131984611265613917565b61131485604051806060016040528060288152602001614d47602891396000808b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006112ca613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b61391f565b600190509392505050565b6000600960020154905090565b6000600560009054906101000a900460ff16905090565b60006113f0611355613917565b846113eb85600080611365613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b61391f565b6001905092915050565b611402613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6002600854141561153d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506115f28130604051602401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040527f8c28cbe8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613f67565b600160088190555050565b611605613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146116c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415611740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550601373ac75ac9c4f1136041170663a347caca88d47a5dc634d1efb2b90916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561179a57600080fd5b505af41580156117ae573d6000803e3d6000fd5b505050506040513d60208110156117c457600080fd5b8101908080519060200190929190505050611847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f6e6f7420617661696c61626c650000000000000000000000000000000000000081525060200191505060405180910390fd5b600973c2905817f1e2cf283248288349b5ea26622bc75163b512fe4290916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561189957600080fd5b505af41580156118ad573d6000803e3d6000fd5b505050506001600881905550565b6118c3613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611985576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600260085414156119fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600101549050600973c2905817f1e2cf283248288349b5ea26622bc751634872119c9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b158015611a6a57600080fd5b505af4158015611a7e573d6000803e3d6000fd5b505050507fecb2eeb8032664e34a027bd80ef670e19e411fab9bf7472b620871cb474113188183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600973c2905817f1e2cf283248288349b5ea26622bc751630ba6cea490916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611b2157600080fd5b505af4158015611b35573d6000803e3d6000fd5b505050506040513d6020811015611b4b57600080fd5b8101908080519060200190929190505050905090565b611b69613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415611ca4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600301549050600973c2905817f1e2cf283248288349b5ea26622bc751634aa0366b9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b158015611d1057600080fd5b505af4158015611d24573d6000803e3d6000fd5b505050507f4230edf3e2636a87470cf6312364eae0219f79d687995461db8d6ae8b86fcf7b8183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600960030154905090565b6000600960070160009054906101000a900460ff16905090565b6000611e14600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600654613b9b565b9050919050565b611e23613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611ee5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b611fae613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612070576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600260085414156120e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060008173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561213957600080fd5b505afa15801561214d573d6000803e3d6000fd5b505050506040513d602081101561216357600080fd5b8101908080519060200190929190505050905060008273ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156121be57600080fd5b505afa1580156121d2573d6000803e3d6000fd5b505050506040513d60208110156121e857600080fd5b810190808051906020019092919050505090503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614801561228157507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8061230e57503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614801561230d57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b5b612380576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f696e76616c69642070616972000000000000000000000000000000000000000081525060200191505060405180910390fd5b601373ac75ac9c4f1136041170663a347caca88d47a5dc63ed34f0ec9091853073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018215158152602001935050505060006040518083038186803b15801561242857600080fd5b505af415801561243c573d6000803e3d6000fd5b505050505050600160088190555050565b612455613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612517576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415612590576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600201549050600973c2905817f1e2cf283248288349b5ea26622bc7516307bf6adc9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156125fc57600080fd5b505af4158015612610573d6000803e3d6000fd5b505050507f5bb7e3415e95c953be69bf5cf610942be94d02e5368b0bbe212c387f14e90e3d8183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006009800154905090565b606060048054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561272d5780601f106127025761010080835404028352916020019161272d565b820191906000526020600020905b81548152906001019060200180831161271057829003601f168201915b5050505050905090565b6000601373ac75ac9c4f1136041170663a347caca88d47a5dc63872e344b909161275f611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156127a057600080fd5b505af41580156127b4573d6000803e3d6000fd5b505050506040513d60208110156127ca57600080fd5b8101908080519060200190929190505050905090565b6000601373ac75ac9c4f1136041170663a347caca88d47a5dc63fc4d5f9f9091612808611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561284957600080fd5b505af415801561285d573d6000803e3d6000fd5b505050506040513d602081101561287357600080fd5b8101908080519060200190929190505050905090565b600061294b612896613917565b8461294685604051806060016040528060258152602001614db8602591396000806128bf613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b61391f565b6001905092915050565b6000601360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061299661298f613917565b8484613bd1565b6001905092915050565b6129a8613917565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614612a48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6e6f7420616e2065787465726e616c6c79206f776e6564206163636f756e740081525060200191505060405180910390fd5b60026008541415612ac1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550601373ac75ac9c4f1136041170663a347caca88d47a5dc63087ba9b290916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015612b1b57600080fd5b505af4158015612b2f573d6000803e3d6000fd5b505050506000601373ac75ac9c4f1136041170663a347caca88d47a5dc63872e344b9091612b5b611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015612b9c57600080fd5b505af4158015612bb0573d6000803e3d6000fd5b505050506040513d6020811015612bc657600080fd5b810190808051906020019092919050505090506000612be361122a565b90506000806000600973c2905817f1e2cf283248288349b5ea26622bc75163fda27874909187876040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060606040518083038186803b158015612c4c57600080fd5b505af4158015612c60573d6000803e3d6000fd5b505050506040513d6060811015612c7657600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050925092509250612cb060098001548484614034565b6000811115612ce957612ce8600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168261415d565b5b601360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612d5657600080fd5b505af1158015612d6a573d6000803e3d6000fd5b50505050612d7860186143bf565b50505050506001600881905550565b612d8f613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612e51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415612eca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550612edc8282613f67565b60016008819055505050565b6000600254905090565b612efa613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612fbc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506130c9816040516024016040516020818303038152906040527ffff6cae9000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613f67565b600160088190555050565b6000600960010154905090565b6130e9613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613224576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555061323581614540565b600160088190555050565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600654905090565b6132d8613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461339a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613413576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506000600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600973c2905817f1e2cf283248288349b5ea26622bc751636efd69229091846040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060006040518083038186803b1580156134b557600080fd5b505af41580156134c9573d6000803e3d6000fd5b505050507fd61f9c9cda6dbf4d6540a8bc48cc55e51105333daa79c5fc3fde780d820bea5f8183604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150600160088190555050565b61354c613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461360e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613694576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614cb86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806000600960040154600960050154600960060154925092509250909192565b60008082840190508381101561383d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60008083141561385a57600090506138c7565b600082840290508284828161386b57fe5b04146138c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b809150505b92915050565b600061390f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506146f6565b905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156139a5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614d946024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613a2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180614cde6022913960400191505060405180910390fd5b806000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6000613b4a827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6138cd90919063ffffffff16565b9050919050565b6000613b9383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ea7565b905092915050565b6000613bc9601860ff16600a0a613bbb848661384790919063ffffffff16565b6138cd90919063ffffffff16565b905092915050565b6000613bdf826006546147bc565b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613c67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614d6f6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613ced576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614c956023913960400191505060405180910390fd5b613cf88484846147f2565b613d6481604051806060016040528060268152602001614d0060269139600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613df981600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a350505050565b6000838311158290613f54576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613f19578082015181840152602081019050613efe565b50505050905090810190601f168015613f465780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b613f7d828260186147f79092919063ffffffff16565b8173ffffffffffffffffffffffffffffffffffffffff167f8f41cc0e83c260c3b7599cf7c3b67f07b686570cad75fdb2ec197b36f01f6b02826040518080602001828103825283818151815260200191508051906020019080838360005b83811015613ff6578082015181840152602081019050613fdb565b50505050905090810190601f1680156140235780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b600061403e6132c6565b9050600080841415614052578190506140f1565b82156140a65761409f670de0b6b3a764000061409161408287670de0b6b3a76400006137bf90919063ffffffff16565b8561384790919063ffffffff16565b6138cd90919063ffffffff16565b90506140f0565b6140ed670de0b6b3a76400006140df6140d087670de0b6b3a7640000613b5190919063ffffffff16565b8561384790919063ffffffff16565b6138cd90919063ffffffff16565b90505b5b8181111561410d5761410a81614105610f16565b6148b7565b90505b614116816148d0565b847fc6642d24d84e7f3d36ca39f5cce10e75639d9b158d5193aa350e2f900653e4c08383604051808381526020018281526020019250505060405180910390a25050505050565b600061416b826006546147bc565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415614210576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b61421c600084846147f2565b614231816002546137bf90919063ffffffff16565b6002819055506000614244600254613b15565b90508060065411156142be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f756e737570706f72746564207363616c696e6720666163746f7200000000000081525060200191505060405180910390fd5b61431082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a350505050565b60005b818054905081101561453c5760008282815481106143dc57fe5b9060005260206000209060020201905060006144b88260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156144ae5780601f10614483576101008083540402835291602001916144ae565b820191906000526020600020905b81548152906001019060200180831161449157829003601f168201915b505050505061496c565b90508061452d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f63616c6c206661696c656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b505080806001019150506143c2565b5050565b60006018828154811061454f57fe5b9060005260206000209060020201905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506060826001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156146225780601f106145f757610100808354040283529160200191614622565b820191906000526020600020905b81548152906001019060200180831161460557829003601f168201915b5050505050905061463d84601861498490919063ffffffff16565b8173ffffffffffffffffffffffffffffffffffffffff167fae84d338be9188b4f4e1bf7d2ebe7db71e84053933e0bef1ff843bf1e76c86ee826040518080602001828103825283818151815260200191508051906020019080838360005b838110156146b657808201518184015260208101905061469b565b50505050905090810190601f1680156146e35780820380516001836020036101000a031916815260200191505b509250505060405180910390a250505050565b600080831182906147a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561476757808201518184015260208101905061474c565b50505050905090810190601f1680156147945780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816147ae57fe5b049050809150509392505050565b60006147ea826147dc601860ff16600a0a8661384790919063ffffffff16565b6138cd90919063ffffffff16565b905092915050565b505050565b8260405180604001604052808473ffffffffffffffffffffffffffffffffffffffff16815260200183815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010190805190602001906148af929190614b28565b505050505050565b60008183106148c657816148c8565b825b905092915050565b60006148dd600254613b15565b90508160001080156148ef5750808211155b614961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f756e737570706f72746564207363616c696e6720666163746f7200000000000081525060200191505060405180910390fd5b816006819055505050565b60008060008351602085016000875af1905092915050565b818054905081106149fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f696e76616c696420696e6465780000000000000000000000000000000000000081525060200191505060405180910390fd5b81600183805490500381548110614a1057fe5b9060005260206000209060020201828281548110614a2a57fe5b90600052602060002090600202016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018201816001019080546001816001161561010002031660029004614ac6929190614ba8565b5090505081805480614ad457fe5b6001900381819060005260206000209060020201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000614b209190614c2f565b505090555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614b6957805160ff1916838001178555614b97565b82800160010185558215614b97579182015b82811115614b96578251825591602001919060010190614b7b565b5b509050614ba49190614c77565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614be15780548555614c1e565b82800160010185558215614c1e57600052602060002091601f016020900482015b82811115614c1d578254825591600101919060010190614c02565b5b509050614c2b9190614c77565b5090565b50805460018160011615610100020316600290046000825580601f10614c555750614c74565b601f016020900490600052602060002090810190614c739190614c77565b5b50565b5b80821115614c90576000816000905550600101614c78565b509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212201eda3054f635f7cdeabfa567cfb9db31be229c1b33b925af20d15a517071bc1464736f6c634300060c0033536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7700000000000000000000000000000000000000000000028a857425466f800000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102745760003560e01c80637a8a014711610151578063b65e7fff116100c3578063dd62ed3e11610087578063dd62ed3e14610bcb578063ed3437f814610c43578063f0f4426014610c61578063f2fde38b14610ca5578063f552dbd714610ce9578063f911474514610d4157610274565b8063b65e7fff14610a42578063baf3da0f14610b1d578063d2304c3614610b3b578063d2e34c7514610b7f578063da82364c14610b9d57610274565b80639764e249116101155780639764e24914610900578063a36849771461091e578063a457c2d71461093c578063a8aa1b31146109a0578063a9059cbb146109d4578063af14052c14610a3857610274565b80637a8a0147146107b957806381e52be6146107fd5780638da5cb5b1461082b578063900cf0cf1461085f57806395d89b411461087d57610274565b806339509351116101ea57806360e9825a116101ae57806360e9825a146106b757806361d027b3146106e557806364eea6821461071957806367edde1d1461073757806370a0823114610757578063715018a6146107af57610274565b806339509351146105b757806341c0cccc1461061b57806349bdd0171461065f5780635a94687e146106695780635a9932031461069757610274565b806316250fd41161023c57806316250fd41461047657806318160ddd146104b85780631924063e146104d657806323b872dd146104f45780632a67296114610578578063313ce5671461059657610274565b806306fdde0314610279578063095ea7b3146102fc5780630a39ce021461036057806311d3e6c4146104245780631265b65114610442575b600080fd5b610281610d6d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102c15780820151818401526020810190506102a6565b50505050905090810190601f1680156102ee5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103486004803603604081101561031257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e0f565b60405180821515815260200191505060405180910390f35b61038c6004803603602081101561037657600080fd5b8101908080359060200190929190505050610e2d565b604051808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103e85780820151818401526020810190506103cd565b50505050905090810190601f1680156104155780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61042c610f16565b6040518082815260200191505060405180910390f35b61044a610f28565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104b66004803603606081101561048c57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610f4c565b005b6104c061122a565b6040518082815260200191505060405180910390f35b6104de61123f565b6040518082815260200191505060405180910390f35b6105606004803603606081101561050a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061124c565b60405180821515815260200191505060405180910390f35b610580611324565b6040518082815260200191505060405180910390f35b61059e611331565b604051808260ff16815260200191505060405180910390f35b610603600480360360408110156105cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611348565b60405180821515815260200191505060405180910390f35b61065d6004803603602081101561063157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113fa565b005b6106676115fd565b005b6106956004803603602081101561067f57600080fd5b81019080803590602001909291905050506118bb565b005b61069f611acd565b60405180821515815260200191505060405180910390f35b6106e3600480360360208110156106cd57600080fd5b8101908080359060200190929190505050611b61565b005b6106ed611d73565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610721611da0565b6040518082815260200191505060405180910390f35b61073f611dad565b60405180821515815260200191505060405180910390f35b6107996004803603602081101561076d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611dc7565b6040518082815260200191505060405180910390f35b6107b7611e1b565b005b6107fb600480360360208110156107cf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611fa6565b005b6108296004803603602081101561081357600080fd5b810190808035906020019092919050505061244d565b005b61083361265f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610867612689565b6040518082815260200191505060405180910390f35b610885612695565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108c55780820151818401526020810190506108aa565b50505050905090810190601f1680156108f25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610908612737565b6040518082815260200191505060405180910390f35b6109266127e0565b6040518082815260200191505060405180910390f35b6109886004803603604081101561095257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612889565b60405180821515815260200191505060405180910390f35b6109a8612955565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a20600480360360408110156109ea57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612982565b60405180821515815260200191505060405180910390f35b610a406129a0565b005b610b1b60048036036040811015610a5857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610a9557600080fd5b820183602082011115610aa757600080fd5b80359060200191846001830284011164010000000083111715610ac957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d87565b005b610b25612ee8565b6040518082815260200191505060405180910390f35b610b7d60048036036020811015610b5157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ef2565b005b610b876130d4565b6040518082815260200191505060405180910390f35b610bc960048036036020811015610bb357600080fd5b81019080803590602001909291905050506130e1565b005b610c2d60048036036040811015610be157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613240565b6040518082815260200191505060405180910390f35b610c4b6132c6565b6040518082815260200191505060405180910390f35b610ca360048036036020811015610c7757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506132d0565b005b610ce760048036036020811015610cbb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613544565b005b610d2b60048036036020811015610cff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613754565b6040518082815260200191505060405180910390f35b610d4961379d565b60405180848152602001838152602001828152602001935050505060405180910390f35b606060038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e055780601f10610dda57610100808354040283529160200191610e05565b820191906000526020600020905b815481529060010190602001808311610de857829003601f168201915b5050505050905090565b6000610e23610e1c613917565b848461391f565b6001905092915050565b60188181548110610e3a57fe5b90600052602060002090600202016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f0c5780601f10610ee157610100808354040283529160200191610f0c565b820191906000526020600020905b815481529060010190602001808311610eef57829003601f168201915b5050505050905082565b6000610f23600254613b15565b905090565b7f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae981565b610f54613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611016576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6002600854141561108f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550600060096004015490506000600960050154905060006009600601549050600973c2905817f1e2cf283248288349b5ea26622bc751637944c78d90918888886040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060006040518083038186803b15801561111f57600080fd5b505af4158015611133573d6000803e3d6000fd5b50505050601373ac75ac9c4f1136041170663a347caca88d47a5dc63b6e05b399091611168878a613b5190919063ffffffff16565b6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156111a357600080fd5b505af41580156111b7573d6000803e3d6000fd5b505050507f67b96153d463108a59f5389db0f3107f004c874e2d388a64ce0b940d7bd8086783838389898960405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390a15050506001600881905550505050565b600061123a600254600654613b9b565b905090565b6000600960080154905090565b6000611259848484613bd1565b61131984611265613917565b61131485604051806060016040528060288152602001614d47602891396000808b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006112ca613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b61391f565b600190509392505050565b6000600960020154905090565b6000600560009054906101000a900460ff16905090565b60006113f0611355613917565b846113eb85600080611365613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b61391f565b6001905092915050565b611402613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6002600854141561153d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506115f28130604051602401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040527f8c28cbe8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613f67565b600160088190555050565b611605613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146116c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415611740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550601373ac75ac9c4f1136041170663a347caca88d47a5dc634d1efb2b90916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561179a57600080fd5b505af41580156117ae573d6000803e3d6000fd5b505050506040513d60208110156117c457600080fd5b8101908080519060200190929190505050611847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f6e6f7420617661696c61626c650000000000000000000000000000000000000081525060200191505060405180910390fd5b600973c2905817f1e2cf283248288349b5ea26622bc75163b512fe4290916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561189957600080fd5b505af41580156118ad573d6000803e3d6000fd5b505050506001600881905550565b6118c3613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611985576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600260085414156119fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600101549050600973c2905817f1e2cf283248288349b5ea26622bc751634872119c9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b158015611a6a57600080fd5b505af4158015611a7e573d6000803e3d6000fd5b505050507fecb2eeb8032664e34a027bd80ef670e19e411fab9bf7472b620871cb474113188183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600973c2905817f1e2cf283248288349b5ea26622bc751630ba6cea490916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611b2157600080fd5b505af4158015611b35573d6000803e3d6000fd5b505050506040513d6020811015611b4b57600080fd5b8101908080519060200190929190505050905090565b611b69613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415611ca4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600301549050600973c2905817f1e2cf283248288349b5ea26622bc751634aa0366b9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b158015611d1057600080fd5b505af4158015611d24573d6000803e3d6000fd5b505050507f4230edf3e2636a87470cf6312364eae0219f79d687995461db8d6ae8b86fcf7b8183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600960030154905090565b6000600960070160009054906101000a900460ff16905090565b6000611e14600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600654613b9b565b9050919050565b611e23613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611ee5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b611fae613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612070576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600260085414156120e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060008173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561213957600080fd5b505afa15801561214d573d6000803e3d6000fd5b505050506040513d602081101561216357600080fd5b8101908080519060200190929190505050905060008273ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156121be57600080fd5b505afa1580156121d2573d6000803e3d6000fd5b505050506040513d60208110156121e857600080fd5b810190808051906020019092919050505090503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614801561228157507f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8061230e57503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614801561230d57507f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae973ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b5b612380576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f696e76616c69642070616972000000000000000000000000000000000000000081525060200191505060405180910390fd5b601373ac75ac9c4f1136041170663a347caca88d47a5dc63ed34f0ec9091853073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018215158152602001935050505060006040518083038186803b15801561242857600080fd5b505af415801561243c573d6000803e3d6000fd5b505050505050600160088190555050565b612455613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612517576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415612590576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555060006009600201549050600973c2905817f1e2cf283248288349b5ea26622bc7516307bf6adc9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156125fc57600080fd5b505af4158015612610573d6000803e3d6000fd5b505050507f5bb7e3415e95c953be69bf5cf610942be94d02e5368b0bbe212c387f14e90e3d8183604051808381526020018281526020019250505060405180910390a150600160088190555050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006009800154905090565b606060048054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561272d5780601f106127025761010080835404028352916020019161272d565b820191906000526020600020905b81548152906001019060200180831161271057829003601f168201915b5050505050905090565b6000601373ac75ac9c4f1136041170663a347caca88d47a5dc63872e344b909161275f611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156127a057600080fd5b505af41580156127b4573d6000803e3d6000fd5b505050506040513d60208110156127ca57600080fd5b8101908080519060200190929190505050905090565b6000601373ac75ac9c4f1136041170663a347caca88d47a5dc63fc4d5f9f9091612808611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561284957600080fd5b505af415801561285d573d6000803e3d6000fd5b505050506040513d602081101561287357600080fd5b8101908080519060200190929190505050905090565b600061294b612896613917565b8461294685604051806060016040528060258152602001614db8602591396000806128bf613917565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b61391f565b6001905092915050565b6000601360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061299661298f613917565b8484613bd1565b6001905092915050565b6129a8613917565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614612a48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6e6f7420616e2065787465726e616c6c79206f776e6564206163636f756e740081525060200191505060405180910390fd5b60026008541415612ac1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550601373ac75ac9c4f1136041170663a347caca88d47a5dc63087ba9b290916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015612b1b57600080fd5b505af4158015612b2f573d6000803e3d6000fd5b505050506000601373ac75ac9c4f1136041170663a347caca88d47a5dc63872e344b9091612b5b611331565b60ff16600a0a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015612b9c57600080fd5b505af4158015612bb0573d6000803e3d6000fd5b505050506040513d6020811015612bc657600080fd5b810190808051906020019092919050505090506000612be361122a565b90506000806000600973c2905817f1e2cf283248288349b5ea26622bc75163fda27874909187876040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060606040518083038186803b158015612c4c57600080fd5b505af4158015612c60573d6000803e3d6000fd5b505050506040513d6060811015612c7657600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050925092509250612cb060098001548484614034565b6000811115612ce957612ce8600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168261415d565b5b601360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612d5657600080fd5b505af1158015612d6a573d6000803e3d6000fd5b50505050612d7860186143bf565b50505050506001600881905550565b612d8f613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612e51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415612eca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600881905550612edc8282613f67565b60016008819055505050565b6000600254905090565b612efa613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612fbc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506130c9816040516024016040516020818303038152906040527ffff6cae9000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613f67565b600160088190555050565b6000600960010154905090565b6130e9613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613224576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260088190555061323581614540565b600160088190555050565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600654905090565b6132d8613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461339a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60026008541415613413576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026008819055506000600960000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600973c2905817f1e2cf283248288349b5ea26622bc751636efd69229091846040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060006040518083038186803b1580156134b557600080fd5b505af41580156134c9573d6000803e3d6000fd5b505050507fd61f9c9cda6dbf4d6540a8bc48cc55e51105333daa79c5fc3fde780d820bea5f8183604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150600160088190555050565b61354c613917565b73ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461360e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613694576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614cb86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806000600960040154600960050154600960060154925092509250909192565b60008082840190508381101561383d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60008083141561385a57600090506138c7565b600082840290508284828161386b57fe5b04146138c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b809150505b92915050565b600061390f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506146f6565b905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156139a5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614d946024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613a2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180614cde6022913960400191505060405180910390fd5b806000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6000613b4a827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6138cd90919063ffffffff16565b9050919050565b6000613b9383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ea7565b905092915050565b6000613bc9601860ff16600a0a613bbb848661384790919063ffffffff16565b6138cd90919063ffffffff16565b905092915050565b6000613bdf826006546147bc565b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613c67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614d6f6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613ced576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614c956023913960400191505060405180910390fd5b613cf88484846147f2565b613d6481604051806060016040528060268152602001614d0060269139600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613ea79092919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613df981600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a350505050565b6000838311158290613f54576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613f19578082015181840152602081019050613efe565b50505050905090810190601f168015613f465780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b613f7d828260186147f79092919063ffffffff16565b8173ffffffffffffffffffffffffffffffffffffffff167f8f41cc0e83c260c3b7599cf7c3b67f07b686570cad75fdb2ec197b36f01f6b02826040518080602001828103825283818151815260200191508051906020019080838360005b83811015613ff6578082015181840152602081019050613fdb565b50505050905090810190601f1680156140235780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b600061403e6132c6565b9050600080841415614052578190506140f1565b82156140a65761409f670de0b6b3a764000061409161408287670de0b6b3a76400006137bf90919063ffffffff16565b8561384790919063ffffffff16565b6138cd90919063ffffffff16565b90506140f0565b6140ed670de0b6b3a76400006140df6140d087670de0b6b3a7640000613b5190919063ffffffff16565b8561384790919063ffffffff16565b6138cd90919063ffffffff16565b90505b5b8181111561410d5761410a81614105610f16565b6148b7565b90505b614116816148d0565b847fc6642d24d84e7f3d36ca39f5cce10e75639d9b158d5193aa350e2f900653e4c08383604051808381526020018281526020019250505060405180910390a25050505050565b600061416b826006546147bc565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415614210576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b61421c600084846147f2565b614231816002546137bf90919063ffffffff16565b6002819055506000614244600254613b15565b90508060065411156142be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f756e737570706f72746564207363616c696e6720666163746f7200000000000081525060200191505060405180910390fd5b61431082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546137bf90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a350505050565b60005b818054905081101561453c5760008282815481106143dc57fe5b9060005260206000209060020201905060006144b88260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156144ae5780601f10614483576101008083540402835291602001916144ae565b820191906000526020600020905b81548152906001019060200180831161449157829003601f168201915b505050505061496c565b90508061452d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f63616c6c206661696c656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b505080806001019150506143c2565b5050565b60006018828154811061454f57fe5b9060005260206000209060020201905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506060826001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156146225780601f106145f757610100808354040283529160200191614622565b820191906000526020600020905b81548152906001019060200180831161460557829003601f168201915b5050505050905061463d84601861498490919063ffffffff16565b8173ffffffffffffffffffffffffffffffffffffffff167fae84d338be9188b4f4e1bf7d2ebe7db71e84053933e0bef1ff843bf1e76c86ee826040518080602001828103825283818151815260200191508051906020019080838360005b838110156146b657808201518184015260208101905061469b565b50505050905090810190601f1680156146e35780820380516001836020036101000a031916815260200191505b509250505060405180910390a250505050565b600080831182906147a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561476757808201518184015260208101905061474c565b50505050905090810190601f1680156147945780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816147ae57fe5b049050809150509392505050565b60006147ea826147dc601860ff16600a0a8661384790919063ffffffff16565b6138cd90919063ffffffff16565b905092915050565b505050565b8260405180604001604052808473ffffffffffffffffffffffffffffffffffffffff16815260200183815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010190805190602001906148af929190614b28565b505050505050565b60008183106148c657816148c8565b825b905092915050565b60006148dd600254613b15565b90508160001080156148ef5750808211155b614961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f756e737570706f72746564207363616c696e6720666163746f7200000000000081525060200191505060405180910390fd5b816006819055505050565b60008060008351602085016000875af1905092915050565b818054905081106149fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f696e76616c696420696e6465780000000000000000000000000000000000000081525060200191505060405180910390fd5b81600183805490500381548110614a1057fe5b9060005260206000209060020201828281548110614a2a57fe5b90600052602060002090600202016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018201816001019080546001816001161561010002031660029004614ac6929190614ba8565b5090505081805480614ad457fe5b6001900381819060005260206000209060020201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000614b209190614c2f565b505090555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614b6957805160ff1916838001178555614b97565b82800160010185558215614b97579182015b82811115614b96578251825591602001919060010190614b7b565b5b509050614ba49190614c77565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614be15780548555614c1e565b82800160010185558215614c1e57600052602060002091601f016020900482015b82811115614c1d578254825591600101919060010190614c02565b5b509050614c2b9190614c77565b5090565b50805460018160011615610100020316600290046000825580601f10614c555750614c74565b601f016020900490600052602060002090810190614c739190614c77565b5b50565b5b80821115614c90576000816000905550600101614c78565b509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212201eda3054f635f7cdeabfa567cfb9db31be229c1b33b925af20d15a517071bc1464736f6c634300060c0033

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

00000000000000000000000000000000000000000000028a857425466f800000

-----Decoded View---------------
Arg [0] : _initialSupply (uint256): 12000000000000000000000

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000028a857425466f800000


Deployed Bytecode Sourcemap

101355:160:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15062:82;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15795:169;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;51716:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19667:138;;;:::i;:::-;;;;;;;;;;;;;;;;;;;51599:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;56314:753;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;15333:133;;;:::i;:::-;;;;;;;;;;;;;;;;;;;53320:120;;;:::i;:::-;;;;;;;;;;;;;;;;;;;16648:320;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;52518:141;;;:::i;:::-;;;;;;;;;;;;;;;;;;;15242:86;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;15969:219;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;57361:180;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;54880:145;;;:::i;:::-;;55252:343;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;53077:122;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;55939:370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;52262:102;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;52664:153;;;:::i;:::-;;;;;;;;;;;;;;;;;;;53204:111;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;15471:155;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2781:148;;;:::i;:::-;;54509:366;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;55600:334;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;2139:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;53445:93;;;:::i;:::-;;;;;;;;;;;;;;;;;;;15149:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53543:152;;;:::i;:::-;;;;;;;;;;;;;;;;;;;53700:158;;;:::i;:::-;;;;;;;;;;;;;;;;;;;16193:270;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;53863:93;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;16468:175;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;53961:543;;;:::i;:::-;;57072:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;19311:108;;;:::i;:::-;;;;;;;;;;;;;;;;;;;57546:159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;52369:144;;;:::i;:::-;;;;;;;;;;;;;;;;;;;57224:132;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;15631:159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;19559:103;;;:::i;:::-;;;;;;;;;;;;;;;;;;;55030:217;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;3084:244;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;19424:130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;52822:250;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15062:82;15099:19;15134:5;15127:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15062:82;:::o;15795:169::-;15880:13;15902:41;15911:12;:10;:12::i;:::-;15925:8;15935:7;15902:8;:41::i;:::-;15955:4;15948:11;;15795:169;;;;:::o;51716:32::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;19667:138::-;19716:25;19757:43;19779:20;;19757:21;:43::i;:::-;19750:50;;19667:138;:::o;51599:48::-;;;:::o;56314:753::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;56496:33:::2;56532:3;:25;;;56496:61;;56562:30;56595:3;:22;;;56562:55;;56622:30;56655:3;:22;;;56622:55;;56682:3;:29;;;;56712:25;56739:22;56763;56682:104;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;56791:6;:28;;;;56820:53;56850:22;56820:25;:29;;:53;;;;:::i;:::-;56791:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;56884:178;56913:25;56940:22;56964;56988:25;57015:22;57039;56884:178;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11246:1;;;10432::::1;11394:7;:22;;;;56314:753:::0;;;:::o;15333:133::-;15386:15;15417:44;15424:20;;15446:14;;15417:6;:44::i;:::-;15410:51;;15333:133;:::o;53320:120::-;53378:23;53417:3;:18;;;53410:25;;53320:120;:::o;16648:320::-;16757:13;16779:39;16789:7;16798:10;16810:7;16779:9;:39::i;:::-;16823:124;16832:7;16841:12;:10;:12::i;:::-;16855:91;16894:7;16855:91;;;;;;;;;;;;;;;;;:11;:20;16867:7;16855:20;;;;;;;;;;;;;;;:34;16876:12;:10;:12::i;:::-;16855:34;;;;;;;;;;;;;;;;:38;;:91;;;;;:::i;:::-;16823:8;:124::i;:::-;16959:4;16952:11;;16648:320;;;;;:::o;52518:141::-;52583:30;52629:3;:25;;;52622:32;;52518:141;:::o;15242:86::-;15283:15;15314:9;;;;;;;;;;;15307:16;;15242:86;:::o;15969:219::-;16059:13;16081:86;16090:12;:10;:12::i;:::-;16104:8;16114:52;16154:11;16114;:25;16126:12;:10;:12::i;:::-;16114:25;;;;;;;;;;;;;;;:35;16140:8;16114:35;;;;;;;;;;;;;;;;:39;;:52;;;;:::i;:::-;16081:8;:86::i;:::-;16179:4;16172:11;;15969:219;;;;:::o;57361:180::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;57452:84:::2;57473:5;57529:4;57480:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57452:20;:84::i;:::-;10432:1:::1;11394:7;:22;;;;57361:180:::0;:::o;54880:145::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;54962:6:::2;:13;;;;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;54954:41;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;55000:3;:18;;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;10432:1:::1;11394:7;:22;;;;54880:145::o:0;55252:343::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;55371:34:::2;55408:3;:26;;;55371:63;;55439:3;:29;;;;55469:26;55439:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;55506:84;55535:26;55563;55506:84;;;;;;;;;;;;;;;;;;;;;;;;11246:1;10432::::1;11394:7;:22;;;;55252:343:::0;:::o;53077:122::-;53136:21;53173:3;:19;;;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53166:28;;53077:122;:::o;55939:370::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;56064:37:::2;56104:3;:29;;;56064:69;;56138:3;:32;;;;56171:29;56138:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;56211:93;56243:29;56274;56211:93;;;;;;;;;;;;;;;;;;;;;;;;11246:1;10432::::1;11394:7;:22;;;;55939:370:::0;:::o;52262:102::-;52314:17;52347:3;:12;;;;;;;;;;;;52340:19;;52262:102;:::o;52664:153::-;52733:34;52783:3;:29;;;52776:36;;52664:153;:::o;53204:111::-;53260:18;53294:3;:16;;;;;;;;;;;;53287:23;;53204:111;:::o;15471:155::-;15538:16;15570:51;15577:17;:27;15595:8;15577:27;;;;;;;;;;;;;;;;15606:14;;15570:6;:51::i;:::-;15563:58;;15471:155;;;:::o;2781:148::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2888:1:::1;2851:40;;2872:6;;;;;;;;;;;2851:40;;;;;;;;;;;;2919:1;2902:6;;:19;;;;;;;;;;;;;;;;;;2781:148::o:0;54509:366::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;54596:15:::2;54619:5;54614:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;54596:38;;54639:15;54662:5;54657:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;54639:38;;54709:4;54690:24;;:7;:24;;;:53;;;;;54729:14;54718:25;;:7;:25;;;54690:53;:110;;;;54766:4;54747:24;;:7;:24;;;:53;;;;;54786:14;54775:25;;:7;:25;;;54747:53;54690:110;54682:135;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;54822:6;:15;;;;54838:5;54864:4;54845:24;;:7;:24;;;54822:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;11246:1;;10432::::1;11394:7;:22;;;;54509:366:::0;:::o;55600:334::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;55717:33:::2;55753:3;:25;;;55717:61;;55783:3;:28;;;;55812:25;55783:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;55848:81;55876:25;55903;55848:81;;;;;;;;;;;;;;;;;;;;;;;;11246:1;10432::::1;11394:7;:22;;;;55600:334:::0;:::o;2139:79::-;2177:7;2204:6;;;;;;;;;;;2197:13;;2139:79;:::o;53445:93::-;53494:14;53524:3;:9;;;53517:16;;53445:93;:::o;15149:88::-;15188:21;15225:7;15218:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15149:88;:::o;53543:152::-;53603:21;53640:6;:23;;;;53678:10;:8;:10::i;:::-;53670:19;;53664:2;:25;53640:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53633:57;;53543:152;:::o;53700:158::-;53763:21;53800:6;:26;;;;53841:10;:8;:10::i;:::-;53833:19;;53827:2;:25;53800:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53793:60;;53700:158;:::o;16193:270::-;16288:13;16310:132;16319:12;:10;:12::i;:::-;16333:8;16343:98;16383:16;16343:98;;;;;;;;;;;;;;;;;:11;:25;16355:12;:10;:12::i;:::-;16343:25;;;;;;;;;;;;;;;:35;16369:8;16343:35;;;;;;;;;;;;;;;;:39;;:98;;;;;:::i;:::-;16310:8;:132::i;:::-;16454:4;16447:11;;16193:270;;;;:::o;53863:93::-;53911:13;53940:6;:11;;;;;;;;;;;;53933:18;;53863:93;:::o;16468:175::-;16556:13;16578:44;16588:12;:10;:12::i;:::-;16602:10;16614:7;16578:9;:44::i;:::-;16634:4;16627:11;;16468:175;;;;:::o;53961:543::-;51801:12;:10;:12::i;:::-;51788:25;;:9;:25;;;51780:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;54025:6:::2;:18;;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;54052:21;54076:6;:23;;;;54114:10;:8;:10::i;:::-;54106:19;;54100:2;:25;54076:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;54052:74;;54133:20;54156:13;:11;:13::i;:::-;54133:36;;54177:14;54193::::0;54209:19:::2;54232:3;:10;;;;54243:13;54258:12;54232:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54176:95;;;;;;54278:37;54286:3;:9:::0;::::2;;54297:6;54305:9;54278:7;:37::i;:::-;54340:1;54326:11;:15;54322:65;;;54349:32;54355:3;:12;;;;;;;;;;;;54369:11;54349:5;:32::i;:::-;54322:65;54455:6;:11;;;;;;;;;;;;54450:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;54479:20;:7;:18;:20::i;:::-;11246:1;;;;;10432::::1;11394:7;:22;;;;53961:543::o:0;57072:147::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;57182:32:::2;57203:3;57208:5;57182:20;:32::i;:::-;10432:1:::1;11394:7;:22;;;;57072:147:::0;;:::o;19311:108::-;19363:15;19394:20;;19387:27;;19311:108;:::o;57546:159::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;57638:62:::2;57659:5;57666:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57638:20;:62::i;:::-;10432:1:::1;11394:7;:22;;;;57546:159:::0;:::o;52369:144::-;52435:31;52482:3;:26;;;52475:33;;52369:144;:::o;57224:132::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;57320:31:::2;57344:6;57320:23;:31::i;:::-;10432:1:::1;11394:7;:22;;;;57224:132:::0;:::o;15631:159::-;15722:18;15756:11;:19;15768:6;15756:19;;;;;;;;;;;;;;;:29;15776:8;15756:29;;;;;;;;;;;;;;;;15749:36;;15631:159;;;;:::o;19559:103::-;19605:22;19643:14;;19636:21;;19559:103;:::o;55030:217::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10476:1:::1;11082:7;;:19;;11074:63;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;10476:1;11215:7;:18;;;;55121:20:::2;55144:3;:12;;;;;;;;;;;;55121:35;;55161:3;:15;;;;55177:12;55161:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;55200:42;55215:12;55229;55200:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;11246:1;10432::::1;11394:7;:22;;;;55030:217:::0;:::o;3084:244::-;2361:12;:10;:12::i;:::-;2351:22;;:6;;;;;;;;;;;:22;;;2343:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3193:1:::1;3173:22;;:8;:22;;;;3165:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3283:8;3254:38;;3275:6;;;;;;;;;;;3254:38;;;;;;;;;;;;3312:8;3303:6;;:17;;;;;;;;;;;;;;;;;;3084:244:::0;:::o;19424:130::-;19490:16;19522:17;:27;19540:8;19522:27;;;;;;;;;;;;;;;;19515:34;;19424:130;;;:::o;52822:250::-;52888:30;52920:27;52949;52993:3;:25;;;53020:3;:22;;;53044:3;:22;;;52985:82;;;;;;52822:250;;;:::o;4266:181::-;4324:7;4344:9;4360:1;4356;:5;4344:17;;4385:1;4380;:6;;4372:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4438:1;4431:8;;;4266:181;;;;:::o;5620:471::-;5678:7;5928:1;5923;:6;5919:47;;;5953:1;5946:8;;;;5919:47;5978:9;5994:1;5990;:5;5978:17;;6023:1;6018;6014;:5;;;;;;:10;6006:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6082:1;6075:8;;;5620:471;;;;;:::o;6567:132::-;6625:7;6652:39;6656:1;6659;6652:39;;;;;;;;;;;;;;;;;:3;:39::i;:::-;6645:46;;6567:132;;;;:::o;676:106::-;729:15;764:10;757:17;;676:106;:::o;16973:330::-;17092:1;17074:20;;:6;:20;;;;17066:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17168:1;17148:22;;:8;:22;;;;17140:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17246:7;17214:11;:19;17226:6;17214:19;;;;;;;;;;;;;;;:29;17234:8;17214:29;;;;;;;;;;;;;;;:39;;;;17280:8;17263:35;;17272:6;17263:35;;;17290:7;17263:35;;;;;;;;;;;;;;;;;;16973:330;;;:::o;19810:167::-;19894:25;19935:37;19951:20;19943:2;19935:15;;:37;;;;:::i;:::-;19928:44;;19810:167;;;:::o;4730:136::-;4788:7;4815:43;4819:1;4822;4815:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;4808:50;;4730:136;;;;:::o;19982:180::-;20070:15;20101:56;14554:2;14601:26;;14595:2;:32;20101:35;20121:14;20101:15;:19;;:35;;;;:::i;:::-;:39;;:56;;;;:::i;:::-;20094:63;;19982:180;;;;:::o;17308:627::-;17405:23;17431:33;17440:7;17449:14;;17431:8;:33::i;:::-;17405:59;;17496:1;17477:21;;:7;:21;;;;17469:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17575:1;17553:24;;:10;:24;;;;17545:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17622:50;17643:7;17652:10;17664:7;17622:20;:50::i;:::-;17706:89;17737:15;17706:89;;;;;;;;;;;;;;;;;:17;:26;17724:7;17706:26;;;;;;;;;;;;;;;;:30;;:89;;;;;:::i;:::-;17677:17;:26;17695:7;17677:26;;;;;;;;;;;;;;;:118;;;;17832:50;17866:15;17832:17;:29;17850:10;17832:29;;;;;;;;;;;;;;;;:33;;:50;;;;:::i;:::-;17800:17;:29;17818:10;17800:29;;;;;;;;;;;;;;;:82;;;;17910:10;17892:38;;17901:7;17892:38;;;17922:7;17892:38;;;;;;;;;;;;;;;;;;17308:627;;;;:::o;5169:192::-;5255:7;5288:1;5283;:6;;5291:12;5275:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5315:9;5331:1;5327;:5;5315:17;;5352:1;5345:8;;;5169:192;;;;;:::o;57710:154::-;57789:29;57807:3;57812:5;57789:7;:17;;:29;;;;;:::i;:::-;57848:3;57828:31;;;57853:5;57828:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57710:154;;:::o;58137:689::-;58226:25;58254:15;:13;:15::i;:::-;58226:43;;58274:25;58318:1;58308:6;:11;58304:288;;;58347:17;58327:37;;58304:288;;;58386:9;58382:205;;;58424:58;58477:4;58424:48;58446:25;58464:6;58454:4;58446:17;;:25;;;;:::i;:::-;58424:17;:21;;:48;;;;:::i;:::-;:52;;:58;;;;:::i;:::-;58404:78;;58382:205;;;58522:58;58575:4;58522:48;58544:25;58562:6;58552:4;58544:17;;:25;;;;:::i;:::-;58522:17;:21;;:48;;;;:::i;:::-;:52;;:58;;;;:::i;:::-;58502:78;;58382:205;58304:288;58620:17;58600;:37;58596:123;;;58665:48;58675:17;58694:18;:16;:18::i;:::-;58665:9;:48::i;:::-;58645:68;;58596:123;58723:36;58741:17;58723;:36::i;:::-;58776:6;58769:52;58784:17;58803;58769:52;;;;;;;;;;;;;;;;;;;;;;;;58137:689;;;;;:::o;17940:621::-;18014:23;18040:33;18049:7;18058:14;;18040:8;:33::i;:::-;18014:59;;18106:1;18086:22;;:8;:22;;;;18078:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18149:51;18178:1;18182:8;18192:7;18149:20;:51::i;:::-;18228:41;18253:15;18228:20;;:24;;:41;;;;:::i;:::-;18205:20;:64;;;;18274:25;18302:43;18324:20;;18302:21;:43::i;:::-;18274:71;;18376:17;18358:14;;:35;;18350:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18459:48;18491:15;18459:17;:27;18477:8;18459:27;;;;;;;;;;;;;;;;:31;;:48;;;;:::i;:::-;18429:17;:27;18447:8;18429:27;;;;;;;;;;;;;;;:78;;;;18538:8;18517:39;;18534:1;18517:39;;;18548:7;18517:39;;;;;;;;;;;;;;;;;;17940:621;;;;:::o;21243:264::-;21311:10;21306:197;21332:8;:15;;;;21327:2;:20;21306:197;;;21361:22;21386:8;21395:2;21386:12;;;;;;;;;;;;;;;;;;21361:37;;21404:13;21420:39;21434:7;:10;;;;;;;;;;;;21446:7;:12;;21420:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:13;:39::i;:::-;21404:55;;21473:8;21465:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21306:197;;21349:4;;;;;;;21306:197;;;;21243:264;:::o;57869:263::-;57934:31;57968:7;57976:6;57968:15;;;;;;;;;;;;;;;;;;57934:49;;57988:11;58002:7;:10;;;;;;;;;;;;57988:24;;58017:18;58038:7;:12;;58017:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58055:28;58076:6;58055:7;:20;;:28;;;;:::i;:::-;58116:3;58093:34;;;58121:5;58093:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57869:263;;;;:::o;7195:278::-;7281:7;7313:1;7309;:5;7316:12;7301:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7340:9;7356:1;7352;:5;;;;;;7340:17;;7464:1;7457:8;;;7195:278;;;;;:::o;20167:174::-;20249:23;20288:48;20321:14;20288:28;14554:2;14601:26;;14595:2;:32;20288:7;:11;;:28;;;;:::i;:::-;:32;;:48;;;;:::i;:::-;20281:55;;20167:174;;;;:::o;19211:95::-;;;;:::o;20878:147::-;20973:8;20987:32;;;;;;;;21000:3;20987:32;;;;;;21011:5;20987:32;;;20973:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;20878:147;;;:::o;50774:153::-;50847:18;50892:8;50881;:19;:41;;50914:8;50881:41;;;50903:8;50881:41;50874:48;;50774:153;;;;:::o;20346:280::-;20413:25;20441:43;20463:20;;20441:21;:43::i;:::-;20413:71;;20501:14;20497:1;:18;:57;;;;;20537:17;20519:14;:35;;20497:57;20489:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20607:14;20590;:31;;;;20346:280;;:::o;21512:188::-;21585:13;21689:1;21686;21678:5;21672:12;21665:4;21658:5;21654:16;21651:1;21646:3;21639:5;21634:57;21622:69;;21616:80;;;;:::o;21030:208::-;21128:8;:15;;;;21119:6;:24;21111:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21185:8;21212:1;21194:8;:15;;;;:19;21185:29;;;;;;;;;;;;;;;;;;21166:8;21175:6;21166:16;;;;;;;;;;;;;;;;;;:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;21219:8;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;21030:208;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

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