ETH Price: $4,041.54 (+3.70%)

Contract

0x1440ac02E0F8A8bbE1451d98a2A6b14b6f0179b7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Change Owner123776662021-05-06 1:10:071320 days ago1620263407IN
0x1440ac02...b6f0179b7
0 ETH0.0025484874
Withdraw123774772021-05-06 0:24:281320 days ago1620260668IN
0x1440ac02...b6f0179b7
0 ETH0.0160322754
Withdraw123727412021-05-05 6:54:301321 days ago1620197670IN
0x1440ac02...b6f0179b7
0 ETH0.0067897225
Withdraw123726092021-05-05 6:29:131321 days ago1620196153IN
0x1440ac02...b6f0179b7
0 ETH0.008950131
Withdraw123635762021-05-03 21:08:001322 days ago1620076080IN
0x1440ac02...b6f0179b7
0 ETH0.0282430793
Withdraw123607772021-05-03 10:49:481323 days ago1620038988IN
0x1440ac02...b6f0179b7
0 ETH0.0093276432
Withdraw123607362021-05-03 10:41:051323 days ago1620038465IN
0x1440ac02...b6f0179b7
0 ETH0.0089489831.00000134
Withdraw123586482021-05-03 2:51:501323 days ago1620010310IN
0x1440ac02...b6f0179b7
0 ETH0.0090361531
Withdraw123562142021-05-02 17:54:151324 days ago1619978055IN
0x1440ac02...b6f0179b7
0 ETH0.0102932935
Withdraw123560832021-05-02 17:24:101324 days ago1619976250IN
0x1440ac02...b6f0179b7
0 ETH0.011259839
Withdraw123540852021-05-02 9:59:481324 days ago1619949588IN
0x1440ac02...b6f0179b7
0 ETH0.0076038228
Withdraw123524732021-05-02 3:49:141324 days ago1619927354IN
0x1440ac02...b6f0179b7
0 ETH0.0070613126
Withdraw123524472021-05-02 3:43:161324 days ago1619926996IN
0x1440ac02...b6f0179b7
0 ETH0.0072178225
Withdraw123520842021-05-02 2:25:151324 days ago1619922315IN
0x1440ac02...b6f0179b7
0 ETH0.0072178225
Withdraw123492092021-05-01 15:49:201325 days ago1619884160IN
0x1440ac02...b6f0179b7
0 ETH0.0103923736
Withdraw123489832021-05-01 15:02:511325 days ago1619881371IN
0x1440ac02...b6f0179b7
0 ETH0.0103235435.10000023
Withdraw123467472021-05-01 6:45:451325 days ago1619851545IN
0x1440ac02...b6f0179b7
0 ETH0.0085056831
Withdraw123411812021-04-30 10:06:501326 days ago1619777210IN
0x1440ac02...b6f0179b7
0 ETH0.0113705240.70000023
Withdraw123381362021-04-29 22:38:341326 days ago1619735914IN
0x1440ac02...b6f0179b7
0 ETH0.0115587441.8
Withdraw123372792021-04-29 19:33:451326 days ago1619724825IN
0x1440ac02...b6f0179b7
0 ETH0.0138262550
Withdraw123372372021-04-29 19:23:411326 days ago1619724221IN
0x1440ac02...b6f0179b7
0 ETH0.0144356550
Withdraw123348992021-04-29 10:46:331327 days ago1619693193IN
0x1440ac02...b6f0179b7
0 ETH0.015145649
Withdraw123347112021-04-29 10:08:291327 days ago1619690909IN
0x1440ac02...b6f0179b7
0 ETH0.0197026267
Withdraw123312412021-04-28 21:03:281327 days ago1619643808IN
0x1440ac02...b6f0179b7
0 ETH0.03067258101
Withdraw123309292021-04-28 19:51:291327 days ago1619639489IN
0x1440ac02...b6f0179b7
0 ETH0.0249693991
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
112344712020-11-11 5:41:111496 days ago1605073271
0x1440ac02...b6f0179b7
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Lockup

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MPL-2.0 license

Contract Source Code (Solidity)

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

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

pragma solidity ^0.5.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

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

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

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

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

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

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

pragma solidity ^0.5.0;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

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

pragma solidity ^0.5.0;




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

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

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

pragma solidity ^0.5.0;

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

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

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

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

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

pragma solidity ^0.5.0;



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

    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);

    Roles.Role private _minters;

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

    modifier onlyMinter() {
        require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
        _;
    }

    function isMinter(address account) public view returns (bool) {
        return _minters.has(account);
    }

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(_msgSender());
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}

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

pragma solidity ^0.5.0;



/**
 * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole},
 * which have permission to mint (create) new tokens as they see fit.
 *
 * At construction, the deployer of the contract is the only minter.
 */
contract ERC20Mintable is ERC20, MinterRole {
    /**
     * @dev See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the {MinterRole}.
     */
    function mint(address account, uint256 amount) public onlyMinter returns (bool) {
        _mint(account, amount);
        return true;
    }
}

// File: contracts/src/common/libs/Decimals.sol

pragma solidity 0.5.17;


/**
 * Library for emulating calculations involving decimals.
 */
library Decimals {
	using SafeMath for uint256;
	uint120 private constant basisValue = 1000000000000000000;

	/**
	 * Returns the ratio of the first argument to the second argument.
	 */
	function outOf(uint256 _a, uint256 _b)
		internal
		pure
		returns (uint256 result)
	{
		if (_a == 0) {
			return 0;
		}
		uint256 a = _a.mul(basisValue);
		if (a < _b) {
			return 0;
		}
		return (a.div(_b));
	}

	/**
	 * Returns multiplied the number by 10^18.
	 * This is used when there is a very large difference between the two numbers passed to the `outOf` function.
	 */
	function mulBasis(uint256 _a) internal pure returns (uint256) {
		return _a.mul(basisValue);
	}

	/**
	 * Returns by changing the numerical value being emulated to the original number of digits.
	 */
	function divBasis(uint256 _a) internal pure returns (uint256) {
		return _a.div(basisValue);
	}
}

// File: contracts/src/common/interface/IGroup.sol

pragma solidity 0.5.17;

contract IGroup {
	function isGroup(address _addr) public view returns (bool);

	function addGroup(address _addr) external;

	function getGroupKey(address _addr) internal pure returns (bytes32) {
		return keccak256(abi.encodePacked("_group", _addr));
	}
}

// File: contracts/src/common/validate/AddressValidator.sol

pragma solidity 0.5.17;


/**
 * A module that provides common validations patterns.
 */
contract AddressValidator {
	string constant errorMessage = "this is illegal address";

	/**
	 * Validates passed address is not a zero address.
	 */
	function validateIllegalAddress(address _addr) external pure {
		require(_addr != address(0), errorMessage);
	}

	/**
	 * Validates passed address is included in an address set.
	 */
	function validateGroup(address _addr, address _groupAddr) external view {
		require(IGroup(_groupAddr).isGroup(_addr), errorMessage);
	}

	/**
	 * Validates passed address is included in two address sets.
	 */
	function validateGroups(
		address _addr,
		address _groupAddr1,
		address _groupAddr2
	) external view {
		if (IGroup(_groupAddr1).isGroup(_addr)) {
			return;
		}
		require(IGroup(_groupAddr2).isGroup(_addr), errorMessage);
	}

	/**
	 * Validates that the address of the first argument is equal to the address of the second argument.
	 */
	function validateAddress(address _addr, address _target) external pure {
		require(_addr == _target, errorMessage);
	}

	/**
	 * Validates passed address equals to the two addresses.
	 */
	function validateAddresses(
		address _addr,
		address _target1,
		address _target2
	) external pure {
		if (_addr == _target1) {
			return;
		}
		require(_addr == _target2, errorMessage);
	}

	/**
	 * Validates passed address equals to the three addresses.
	 */
	function validate3Addresses(
		address _addr,
		address _target1,
		address _target2,
		address _target3
	) external pure {
		if (_addr == _target1) {
			return;
		}
		if (_addr == _target2) {
			return;
		}
		require(_addr == _target3, errorMessage);
	}
}

// File: contracts/src/common/validate/UsingValidator.sol

pragma solidity 0.5.17;

// prettier-ignore


/**
 * Module for contrast handling AddressValidator.
 */
contract UsingValidator {
	AddressValidator private _validator;

	/**
	 * Create a new AddressValidator contract when initialize.
	 */
	constructor() public {
		_validator = new AddressValidator();
	}

	/**
	 * Returns the set AddressValidator address.
	 */
	function addressValidator() internal view returns (AddressValidator) {
		return _validator;
	}
}

// File: contracts/src/property/IProperty.sol

pragma solidity 0.5.17;

contract IProperty {
	function author() external view returns (address);

	function withdraw(address _sender, uint256 _value) external;
}

// File: contracts/src/common/lifecycle/Killable.sol

pragma solidity 0.5.17;

/**
 * A module that allows contracts to self-destruct.
 */
contract Killable {
	address payable public _owner;

	/**
	 * Initialized with the deployer as the owner.
	 */
	constructor() internal {
		_owner = msg.sender;
	}

	/**
	 * Self-destruct the contract.
	 * This function can only be executed by the owner.
	 */
	function kill() public {
		require(msg.sender == _owner, "only owner method");
		selfdestruct(_owner);
	}
}

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

pragma solidity ^0.5.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        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(isOwner(), "Ownable: caller is not the owner");
        _;
    }

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

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

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

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

// File: contracts/src/common/config/AddressConfig.sol

pragma solidity 0.5.17;




/**
 * A registry contract to hold the latest contract addresses.
 * Dev Protocol will be upgradeable by this contract.
 */
contract AddressConfig is Ownable, UsingValidator, Killable {
	address public token = 0x98626E2C9231f03504273d55f397409deFD4a093;
	address public allocator;
	address public allocatorStorage;
	address public withdraw;
	address public withdrawStorage;
	address public marketFactory;
	address public marketGroup;
	address public propertyFactory;
	address public propertyGroup;
	address public metricsGroup;
	address public metricsFactory;
	address public policy;
	address public policyFactory;
	address public policySet;
	address public policyGroup;
	address public lockup;
	address public lockupStorage;
	address public voteTimes;
	address public voteTimesStorage;
	address public voteCounter;
	address public voteCounterStorage;

	/**
	 * Set the latest Allocator contract address.
	 * Only the owner can execute this function.
	 */
	function setAllocator(address _addr) external onlyOwner {
		allocator = _addr;
	}

	/**
	 * Set the latest AllocatorStorage contract address.
	 * Only the owner can execute this function.
	 * NOTE: But currently, the AllocatorStorage contract is not used.
	 */
	function setAllocatorStorage(address _addr) external onlyOwner {
		allocatorStorage = _addr;
	}

	/**
	 * Set the latest Withdraw contract address.
	 * Only the owner can execute this function.
	 */
	function setWithdraw(address _addr) external onlyOwner {
		withdraw = _addr;
	}

	/**
	 * Set the latest WithdrawStorage contract address.
	 * Only the owner can execute this function.
	 */
	function setWithdrawStorage(address _addr) external onlyOwner {
		withdrawStorage = _addr;
	}

	/**
	 * Set the latest MarketFactory contract address.
	 * Only the owner can execute this function.
	 */
	function setMarketFactory(address _addr) external onlyOwner {
		marketFactory = _addr;
	}

	/**
	 * Set the latest MarketGroup contract address.
	 * Only the owner can execute this function.
	 */
	function setMarketGroup(address _addr) external onlyOwner {
		marketGroup = _addr;
	}

	/**
	 * Set the latest PropertyFactory contract address.
	 * Only the owner can execute this function.
	 */
	function setPropertyFactory(address _addr) external onlyOwner {
		propertyFactory = _addr;
	}

	/**
	 * Set the latest PropertyGroup contract address.
	 * Only the owner can execute this function.
	 */
	function setPropertyGroup(address _addr) external onlyOwner {
		propertyGroup = _addr;
	}

	/**
	 * Set the latest MetricsFactory contract address.
	 * Only the owner can execute this function.
	 */
	function setMetricsFactory(address _addr) external onlyOwner {
		metricsFactory = _addr;
	}

	/**
	 * Set the latest MetricsGroup contract address.
	 * Only the owner can execute this function.
	 */
	function setMetricsGroup(address _addr) external onlyOwner {
		metricsGroup = _addr;
	}

	/**
	 * Set the latest PolicyFactory contract address.
	 * Only the owner can execute this function.
	 */
	function setPolicyFactory(address _addr) external onlyOwner {
		policyFactory = _addr;
	}

	/**
	 * Set the latest PolicyGroup contract address.
	 * Only the owner can execute this function.
	 */
	function setPolicyGroup(address _addr) external onlyOwner {
		policyGroup = _addr;
	}

	/**
	 * Set the latest PolicySet contract address.
	 * Only the owner can execute this function.
	 */
	function setPolicySet(address _addr) external onlyOwner {
		policySet = _addr;
	}

	/**
	 * Set the latest Policy contract address.
	 * Only the latest PolicyFactory contract can execute this function.
	 */
	function setPolicy(address _addr) external {
		addressValidator().validateAddress(msg.sender, policyFactory);
		policy = _addr;
	}

	/**
	 * Set the latest Dev contract address.
	 * Only the owner can execute this function.
	 */
	function setToken(address _addr) external onlyOwner {
		token = _addr;
	}

	/**
	 * Set the latest Lockup contract address.
	 * Only the owner can execute this function.
	 */
	function setLockup(address _addr) external onlyOwner {
		lockup = _addr;
	}

	/**
	 * Set the latest LockupStorage contract address.
	 * Only the owner can execute this function.
	 * NOTE: But currently, the LockupStorage contract is not used as a stand-alone because it is inherited from the Lockup contract.
	 */
	function setLockupStorage(address _addr) external onlyOwner {
		lockupStorage = _addr;
	}

	/**
	 * Set the latest VoteTimes contract address.
	 * Only the owner can execute this function.
	 * NOTE: But currently, the VoteTimes contract is not used.
	 */
	function setVoteTimes(address _addr) external onlyOwner {
		voteTimes = _addr;
	}

	/**
	 * Set the latest VoteTimesStorage contract address.
	 * Only the owner can execute this function.
	 * NOTE: But currently, the VoteTimesStorage contract is not used.
	 */
	function setVoteTimesStorage(address _addr) external onlyOwner {
		voteTimesStorage = _addr;
	}

	/**
	 * Set the latest VoteCounter contract address.
	 * Only the owner can execute this function.
	 */
	function setVoteCounter(address _addr) external onlyOwner {
		voteCounter = _addr;
	}

	/**
	 * Set the latest VoteCounterStorage contract address.
	 * Only the owner can execute this function.
	 * NOTE: But currently, the VoteCounterStorage contract is not used as a stand-alone because it is inherited from the VoteCounter contract.
	 */
	function setVoteCounterStorage(address _addr) external onlyOwner {
		voteCounterStorage = _addr;
	}
}

// File: contracts/src/common/config/UsingConfig.sol

pragma solidity 0.5.17;


/**
 * Module for using AddressConfig contracts.
 */
contract UsingConfig {
	AddressConfig private _config;

	/**
	 * Initialize the argument as AddressConfig address.
	 */
	constructor(address _addressConfig) public {
		_config = AddressConfig(_addressConfig);
	}

	/**
	 * Returns the latest AddressConfig instance.
	 */
	function config() internal view returns (AddressConfig) {
		return _config;
	}

	/**
	 * Returns the latest AddressConfig address.
	 */
	function configAddress() external view returns (address) {
		return address(_config);
	}
}

// File: contracts/src/common/storage/EternalStorage.sol

pragma solidity 0.5.17;

/**
 * Module for persisting states.
 * Stores a map for `uint256`, `string`, `address`, `bytes32`, `bool`, and `int256` type with `bytes32` type as a key.
 */
contract EternalStorage {
	address private currentOwner = msg.sender;

	mapping(bytes32 => uint256) private uIntStorage;
	mapping(bytes32 => string) private stringStorage;
	mapping(bytes32 => address) private addressStorage;
	mapping(bytes32 => bytes32) private bytesStorage;
	mapping(bytes32 => bool) private boolStorage;
	mapping(bytes32 => int256) private intStorage;

	/**
	 * Modifiers to validate that only the owner can execute.
	 */
	modifier onlyCurrentOwner() {
		require(msg.sender == currentOwner, "not current owner");
		_;
	}

	/**
	 * Transfer the owner.
	 * Only the owner can execute this function.
	 */
	function changeOwner(address _newOwner) external {
		require(msg.sender == currentOwner, "not current owner");
		currentOwner = _newOwner;
	}

	// *** Getter Methods ***

	/**
	 * Returns the value of the `uint256` type that mapped to the given key.
	 */
	function getUint(bytes32 _key) external view returns (uint256) {
		return uIntStorage[_key];
	}

	/**
	 * Returns the value of the `string` type that mapped to the given key.
	 */
	function getString(bytes32 _key) external view returns (string memory) {
		return stringStorage[_key];
	}

	/**
	 * Returns the value of the `address` type that mapped to the given key.
	 */
	function getAddress(bytes32 _key) external view returns (address) {
		return addressStorage[_key];
	}

	/**
	 * Returns the value of the `bytes32` type that mapped to the given key.
	 */
	function getBytes(bytes32 _key) external view returns (bytes32) {
		return bytesStorage[_key];
	}

	/**
	 * Returns the value of the `bool` type that mapped to the given key.
	 */
	function getBool(bytes32 _key) external view returns (bool) {
		return boolStorage[_key];
	}

	/**
	 * Returns the value of the `int256` type that mapped to the given key.
	 */
	function getInt(bytes32 _key) external view returns (int256) {
		return intStorage[_key];
	}

	// *** Setter Methods ***

	/**
	 * Maps a value of `uint256` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setUint(bytes32 _key, uint256 _value) external onlyCurrentOwner {
		uIntStorage[_key] = _value;
	}

	/**
	 * Maps a value of `string` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setString(bytes32 _key, string calldata _value)
		external
		onlyCurrentOwner
	{
		stringStorage[_key] = _value;
	}

	/**
	 * Maps a value of `address` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setAddress(bytes32 _key, address _value)
		external
		onlyCurrentOwner
	{
		addressStorage[_key] = _value;
	}

	/**
	 * Maps a value of `bytes32` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setBytes(bytes32 _key, bytes32 _value) external onlyCurrentOwner {
		bytesStorage[_key] = _value;
	}

	/**
	 * Maps a value of `bool` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setBool(bytes32 _key, bool _value) external onlyCurrentOwner {
		boolStorage[_key] = _value;
	}

	/**
	 * Maps a value of `int256` type to a given key.
	 * Only the owner can execute this function.
	 */
	function setInt(bytes32 _key, int256 _value) external onlyCurrentOwner {
		intStorage[_key] = _value;
	}

	// *** Delete Methods ***

	/**
	 * Deletes the value of the `uint256` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteUint(bytes32 _key) external onlyCurrentOwner {
		delete uIntStorage[_key];
	}

	/**
	 * Deletes the value of the `string` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteString(bytes32 _key) external onlyCurrentOwner {
		delete stringStorage[_key];
	}

	/**
	 * Deletes the value of the `address` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteAddress(bytes32 _key) external onlyCurrentOwner {
		delete addressStorage[_key];
	}

	/**
	 * Deletes the value of the `bytes32` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteBytes(bytes32 _key) external onlyCurrentOwner {
		delete bytesStorage[_key];
	}

	/**
	 * Deletes the value of the `bool` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteBool(bytes32 _key) external onlyCurrentOwner {
		delete boolStorage[_key];
	}

	/**
	 * Deletes the value of the `int256` type that mapped to the given key.
	 * Only the owner can execute this function.
	 */
	function deleteInt(bytes32 _key) external onlyCurrentOwner {
		delete intStorage[_key];
	}
}

// File: contracts/src/common/storage/UsingStorage.sol

pragma solidity 0.5.17;



/**
 * Module for contrast handling EternalStorage.
 */
contract UsingStorage is Ownable {
	address private _storage;

	/**
	 * Modifier to verify that EternalStorage is set.
	 */
	modifier hasStorage() {
		require(_storage != address(0), "storage is not set");
		_;
	}

	/**
	 * Returns the set EternalStorage instance.
	 */
	function eternalStorage()
		internal
		view
		hasStorage
		returns (EternalStorage)
	{
		return EternalStorage(_storage);
	}

	/**
	 * Returns the set EternalStorage address.
	 */
	function getStorageAddress() external view hasStorage returns (address) {
		return _storage;
	}

	/**
	 * Create a new EternalStorage contract.
	 * This function call will fail if the EternalStorage contract is already set.
	 * Also, only the owner can execute it.
	 */
	function createStorage() external onlyOwner {
		require(_storage == address(0), "storage is set");
		EternalStorage tmp = new EternalStorage();
		_storage = address(tmp);
	}

	/**
	 * Assigns the EternalStorage contract that has already been created.
	 * Only the owner can execute this function.
	 */
	function setStorage(address _storageAddress) external onlyOwner {
		_storage = _storageAddress;
	}

	/**
	 * Delegates the owner of the current EternalStorage contract.
	 * Only the owner can execute this function.
	 */
	function changeOwner(address newOwner) external onlyOwner {
		EternalStorage(_storage).changeOwner(newOwner);
	}
}

// File: contracts/src/lockup/LockupStorage.sol

pragma solidity 0.5.17;



contract LockupStorage is UsingStorage {
	using SafeMath for uint256;

	uint256 public constant basis = 100000000000000000000000000000000;

	//AllValue
	function setStorageAllValue(uint256 _value) internal {
		bytes32 key = getStorageAllValueKey();
		eternalStorage().setUint(key, _value);
	}

	function getStorageAllValue() public view returns (uint256) {
		bytes32 key = getStorageAllValueKey();
		return eternalStorage().getUint(key);
	}

	function getStorageAllValueKey() private pure returns (bytes32) {
		return keccak256(abi.encodePacked("_allValue"));
	}

	//Value
	function setStorageValue(
		address _property,
		address _sender,
		uint256 _value
	) internal {
		bytes32 key = getStorageValueKey(_property, _sender);
		eternalStorage().setUint(key, _value);
	}

	function getStorageValue(address _property, address _sender)
		public
		view
		returns (uint256)
	{
		bytes32 key = getStorageValueKey(_property, _sender);
		return eternalStorage().getUint(key);
	}

	function getStorageValueKey(address _property, address _sender)
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_value", _property, _sender));
	}

	//PropertyValue
	function setStoragePropertyValue(address _property, uint256 _value)
		internal
	{
		bytes32 key = getStoragePropertyValueKey(_property);
		eternalStorage().setUint(key, _value);
	}

	function getStoragePropertyValue(address _property)
		public
		view
		returns (uint256)
	{
		bytes32 key = getStoragePropertyValueKey(_property);
		return eternalStorage().getUint(key);
	}

	function getStoragePropertyValueKey(address _property)
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_propertyValue", _property));
	}

	//InterestPrice
	function setStorageInterestPrice(address _property, uint256 _value)
		internal
	{
		// The previously used function
		// This function is only used in testing
		eternalStorage().setUint(getStorageInterestPriceKey(_property), _value);
	}

	function getStorageInterestPrice(address _property)
		public
		view
		returns (uint256)
	{
		return eternalStorage().getUint(getStorageInterestPriceKey(_property));
	}

	function getStorageInterestPriceKey(address _property)
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_interestTotals", _property));
	}

	//LastInterestPrice
	function setStorageLastInterestPrice(
		address _property,
		address _user,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStorageLastInterestPriceKey(_property, _user),
			_value
		);
	}

	function getStorageLastInterestPrice(address _property, address _user)
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageLastInterestPriceKey(_property, _user)
			);
	}

	function getStorageLastInterestPriceKey(address _property, address _user)
		private
		pure
		returns (bytes32)
	{
		return
			keccak256(
				abi.encodePacked("_lastLastInterestPrice", _property, _user)
			);
	}

	//LastSameRewardsAmountAndBlock
	function setStorageLastSameRewardsAmountAndBlock(
		uint256 _amount,
		uint256 _block
	) internal {
		uint256 record = _amount.mul(basis).add(_block);
		eternalStorage().setUint(
			getStorageLastSameRewardsAmountAndBlockKey(),
			record
		);
	}

	function getStorageLastSameRewardsAmountAndBlock()
		public
		view
		returns (uint256 _amount, uint256 _block)
	{
		uint256 record = eternalStorage().getUint(
			getStorageLastSameRewardsAmountAndBlockKey()
		);
		uint256 amount = record.div(basis);
		uint256 blockNumber = record.sub(amount.mul(basis));
		return (amount, blockNumber);
	}

	function getStorageLastSameRewardsAmountAndBlockKey()
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_LastSameRewardsAmountAndBlock"));
	}

	//CumulativeGlobalRewards
	function setStorageCumulativeGlobalRewards(uint256 _value) internal {
		eternalStorage().setUint(
			getStorageCumulativeGlobalRewardsKey(),
			_value
		);
	}

	function getStorageCumulativeGlobalRewards() public view returns (uint256) {
		return eternalStorage().getUint(getStorageCumulativeGlobalRewardsKey());
	}

	function getStorageCumulativeGlobalRewardsKey()
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_cumulativeGlobalRewards"));
	}

	//LastCumulativeGlobalReward
	function setStorageLastCumulativeGlobalReward(
		address _property,
		address _user,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStorageLastCumulativeGlobalRewardKey(_property, _user),
			_value
		);
	}

	function getStorageLastCumulativeGlobalReward(
		address _property,
		address _user
	) public view returns (uint256) {
		return
			eternalStorage().getUint(
				getStorageLastCumulativeGlobalRewardKey(_property, _user)
			);
	}

	function getStorageLastCumulativeGlobalRewardKey(
		address _property,
		address _user
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked(
					"_LastCumulativeGlobalReward",
					_property,
					_user
				)
			);
	}

	//LastCumulativePropertyInterest
	function setStorageLastCumulativePropertyInterest(
		address _property,
		address _user,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStorageLastCumulativePropertyInterestKey(_property, _user),
			_value
		);
	}

	function getStorageLastCumulativePropertyInterest(
		address _property,
		address _user
	) public view returns (uint256) {
		return
			eternalStorage().getUint(
				getStorageLastCumulativePropertyInterestKey(_property, _user)
			);
	}

	function getStorageLastCumulativePropertyInterestKey(
		address _property,
		address _user
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked(
					"_lastCumulativePropertyInterest",
					_property,
					_user
				)
			);
	}

	//CumulativeLockedUpUnitAndBlock
	function setStorageCumulativeLockedUpUnitAndBlock(
		address _addr,
		uint256 _unit,
		uint256 _block
	) internal {
		uint256 record = _unit.mul(basis).add(_block);
		eternalStorage().setUint(
			getStorageCumulativeLockedUpUnitAndBlockKey(_addr),
			record
		);
	}

	function getStorageCumulativeLockedUpUnitAndBlock(address _addr)
		public
		view
		returns (uint256 _unit, uint256 _block)
	{
		uint256 record = eternalStorage().getUint(
			getStorageCumulativeLockedUpUnitAndBlockKey(_addr)
		);
		uint256 unit = record.div(basis);
		uint256 blockNumber = record.sub(unit.mul(basis));
		return (unit, blockNumber);
	}

	function getStorageCumulativeLockedUpUnitAndBlockKey(address _addr)
		private
		pure
		returns (bytes32)
	{
		return
			keccak256(
				abi.encodePacked("_cumulativeLockedUpUnitAndBlock", _addr)
			);
	}

	//CumulativeLockedUpValue
	function setStorageCumulativeLockedUpValue(address _addr, uint256 _value)
		internal
	{
		eternalStorage().setUint(
			getStorageCumulativeLockedUpValueKey(_addr),
			_value
		);
	}

	function getStorageCumulativeLockedUpValue(address _addr)
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageCumulativeLockedUpValueKey(_addr)
			);
	}

	function getStorageCumulativeLockedUpValueKey(address _addr)
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("_cumulativeLockedUpValue", _addr));
	}

	//PendingWithdrawal
	function setStoragePendingInterestWithdrawal(
		address _property,
		address _user,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStoragePendingInterestWithdrawalKey(_property, _user),
			_value
		);
	}

	function getStoragePendingInterestWithdrawal(
		address _property,
		address _user
	) public view returns (uint256) {
		return
			eternalStorage().getUint(
				getStoragePendingInterestWithdrawalKey(_property, _user)
			);
	}

	function getStoragePendingInterestWithdrawalKey(
		address _property,
		address _user
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked("_pendingInterestWithdrawal", _property, _user)
			);
	}

	//DIP4GenesisBlock
	function setStorageDIP4GenesisBlock(uint256 _block) internal {
		eternalStorage().setUint(getStorageDIP4GenesisBlockKey(), _block);
	}

	function getStorageDIP4GenesisBlock() public view returns (uint256) {
		return eternalStorage().getUint(getStorageDIP4GenesisBlockKey());
	}

	function getStorageDIP4GenesisBlockKey() private pure returns (bytes32) {
		return keccak256(abi.encodePacked("_dip4GenesisBlock"));
	}

	//LastCumulativeLockedUpAndBlock
	function setStorageLastCumulativeLockedUpAndBlock(
		address _property,
		address _user,
		uint256 _cLocked,
		uint256 _block
	) internal {
		uint256 record = _cLocked.mul(basis).add(_block);
		eternalStorage().setUint(
			getStorageLastCumulativeLockedUpAndBlockKey(_property, _user),
			record
		);
	}

	function getStorageLastCumulativeLockedUpAndBlock(
		address _property,
		address _user
	) public view returns (uint256 _cLocked, uint256 _block) {
		uint256 record = eternalStorage().getUint(
			getStorageLastCumulativeLockedUpAndBlockKey(_property, _user)
		);
		uint256 cLocked = record.div(basis);
		uint256 blockNumber = record.sub(cLocked.mul(basis));

		return (cLocked, blockNumber);
	}

	function getStorageLastCumulativeLockedUpAndBlockKey(
		address _property,
		address _user
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked(
					"_lastCumulativeLockedUpAndBlock",
					_property,
					_user
				)
			);
	}

	//lastStakedInterestPrice
	function setStorageLastStakedInterestPrice(
		address _property,
		address _user,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStorageLastStakedInterestPriceKey(_property, _user),
			_value
		);
	}

	function getStorageLastStakedInterestPrice(address _property, address _user)
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageLastStakedInterestPriceKey(_property, _user)
			);
	}

	function getStorageLastStakedInterestPriceKey(
		address _property,
		address _user
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked("_lastStakedInterestPrice", _property, _user)
			);
	}

	//lastStakesChangedCumulativeReward
	function setStorageLastStakesChangedCumulativeReward(uint256 _value)
		internal
	{
		eternalStorage().setUint(
			getStorageLastStakesChangedCumulativeRewardKey(),
			_value
		);
	}

	function getStorageLastStakesChangedCumulativeReward()
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageLastStakesChangedCumulativeRewardKey()
			);
	}

	function getStorageLastStakesChangedCumulativeRewardKey()
		private
		pure
		returns (bytes32)
	{
		return
			keccak256(abi.encodePacked("_lastStakesChangedCumulativeReward"));
	}

	//LastCumulativeHoldersRewardPrice
	function setStorageLastCumulativeHoldersRewardPrice(uint256 _holders)
		internal
	{
		eternalStorage().setUint(
			getStorageLastCumulativeHoldersRewardPriceKey(),
			_holders
		);
	}

	function getStorageLastCumulativeHoldersRewardPrice()
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageLastCumulativeHoldersRewardPriceKey()
			);
	}

	function getStorageLastCumulativeHoldersRewardPriceKey()
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("0lastCumulativeHoldersRewardPrice"));
	}

	//LastCumulativeInterestPrice
	function setStorageLastCumulativeInterestPrice(uint256 _interest) internal {
		eternalStorage().setUint(
			getStorageLastCumulativeInterestPriceKey(),
			_interest
		);
	}

	function getStorageLastCumulativeInterestPrice()
		public
		view
		returns (uint256)
	{
		return
			eternalStorage().getUint(
				getStorageLastCumulativeInterestPriceKey()
			);
	}

	function getStorageLastCumulativeInterestPriceKey()
		private
		pure
		returns (bytes32)
	{
		return keccak256(abi.encodePacked("0lastCumulativeInterestPrice"));
	}

	//LastCumulativeHoldersRewardAmountPerProperty
	function setStorageLastCumulativeHoldersRewardAmountPerProperty(
		address _property,
		uint256 _value
	) internal {
		eternalStorage().setUint(
			getStorageLastCumulativeHoldersRewardAmountPerPropertyKey(
				_property
			),
			_value
		);
	}

	function getStorageLastCumulativeHoldersRewardAmountPerProperty(
		address _property
	) public view returns (uint256) {
		return
			eternalStorage().getUint(
				getStorageLastCumulativeHoldersRewardAmountPerPropertyKey(
					_property
				)
			);
	}

	function getStorageLastCumulativeHoldersRewardAmountPerPropertyKey(
		address _property
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked(
					"0lastCumulativeHoldersRewardAmountPerProperty",
					_property
				)
			);
	}

	//LastCumulativeHoldersRewardPricePerProperty
	function setStorageLastCumulativeHoldersRewardPricePerProperty(
		address _property,
		uint256 _price
	) internal {
		eternalStorage().setUint(
			getStorageLastCumulativeHoldersRewardPricePerPropertyKey(_property),
			_price
		);
	}

	function getStorageLastCumulativeHoldersRewardPricePerProperty(
		address _property
	) public view returns (uint256) {
		return
			eternalStorage().getUint(
				getStorageLastCumulativeHoldersRewardPricePerPropertyKey(
					_property
				)
			);
	}

	function getStorageLastCumulativeHoldersRewardPricePerPropertyKey(
		address _property
	) private pure returns (bytes32) {
		return
			keccak256(
				abi.encodePacked(
					"0lastCumulativeHoldersRewardPricePerProperty",
					_property
				)
			);
	}
}

// File: contracts/src/policy/IPolicy.sol

pragma solidity 0.5.17;

contract IPolicy {
	function rewards(uint256 _lockups, uint256 _assets)
		external
		view
		returns (uint256);

	function holdersShare(uint256 _amount, uint256 _lockups)
		external
		view
		returns (uint256);

	function assetValue(uint256 _value, uint256 _lockups)
		external
		view
		returns (uint256);

	function authenticationFee(uint256 _assets, uint256 _propertyAssets)
		external
		view
		returns (uint256);

	function marketApproval(uint256 _agree, uint256 _opposite)
		external
		view
		returns (bool);

	function policyApproval(uint256 _agree, uint256 _opposite)
		external
		view
		returns (bool);

	function marketVotingBlocks() external view returns (uint256);

	function policyVotingBlocks() external view returns (uint256);

	function abstentionPenalty(uint256 _count) external view returns (uint256);
}

// File: contracts/src/allocator/IAllocator.sol

pragma solidity 0.5.17;

contract IAllocator {
	function calculateMaxRewardsPerBlock() public view returns (uint256);

	function beforeBalanceChange(
		address _property,
		address _from,
		address _to
		// solium-disable-next-line indentation
	) external;
}

// File: contracts/src/lockup/ILockup.sol

pragma solidity 0.5.17;

contract ILockup {
	function lockup(
		address _from,
		address _property,
		uint256 _value
		// solium-disable-next-line indentation
	) external;

	function update() public;

	function withdraw(address _property, uint256 _amount) external;

	function calculateCumulativeRewardPrices()
		public
		view
		returns (
			uint256 _reward,
			uint256 _holders,
			uint256 _interest
		);

	function calculateCumulativeHoldersRewardAmount(address _property)
		public
		view
		returns (uint256);

	function getPropertyValue(address _property)
		external
		view
		returns (uint256);

	function getAllValue() external view returns (uint256);

	function getValue(address _property, address _sender)
		external
		view
		returns (uint256);

	function calculateWithdrawableInterestAmount(
		address _property,
		address _user
	)
		public
		view
		returns (
			// solium-disable-next-line indentation
			uint256
		);
}

// File: contracts/src/metrics/IMetricsGroup.sol

pragma solidity 0.5.17;


contract IMetricsGroup is IGroup {
	function removeGroup(address _addr) external;

	function totalIssuedMetrics() external view returns (uint256);

	function getMetricsCountPerProperty(address _property)
		public
		view
		returns (uint256);

	function hasAssets(address _property) public view returns (bool);
}

// File: contracts/src/lockup/Lockup.sol

pragma solidity 0.5.17;

// prettier-ignore












/**
 * A contract that manages the staking of DEV tokens and calculates rewards.
 * Staking and the following mechanism determines that reward calculation.
 *
 * Variables:
 * -`M`: Maximum mint amount per block determined by Allocator contract
 * -`B`: Number of blocks during staking
 * -`P`: Total number of staking locked up in a Property contract
 * -`S`: Total number of staking locked up in all Property contracts
 * -`U`: Number of staking per account locked up in a Property contract
 *
 * Formula:
 * Staking Rewards = M * B * (P / S) * (U / P)
 *
 * Note:
 * -`M`, `P` and `S` vary from block to block, and the variation cannot be predicted.
 * -`B` is added every time the Ethereum block is created.
 * - Only `U` and `B` are predictable variables.
 * - As `M`, `P` and `S` cannot be observed from a staker, the "cumulative sum" is often used to calculate ratio variation with history.
 * - Reward withdrawal always withdraws the total withdrawable amount.
 *
 * Scenario:
 * - Assume `M` is fixed at 500
 * - Alice stakes 100 DEV on Property-A (Alice's staking state on Property-A: `M`=500, `B`=0, `P`=100, `S`=100, `U`=100)
 * - After 10 blocks, Bob stakes 60 DEV on Property-B (Alice's staking state on Property-A: `M`=500, `B`=10, `P`=100, `S`=160, `U`=100)
 * - After 10 blocks, Carol stakes 40 DEV on Property-A (Alice's staking state on Property-A: `M`=500, `B`=20, `P`=140, `S`=200, `U`=100)
 * - After 10 blocks, Alice withdraws Property-A staking reward. The reward at this time is 5000 DEV (10 blocks * 500 DEV) + 3125 DEV (10 blocks * 62.5% * 500 DEV) + 2500 DEV (10 blocks * 50% * 500 DEV).
 */
contract Lockup is ILockup, UsingConfig, UsingValidator, LockupStorage {
	using SafeMath for uint256;
	using Decimals for uint256;
	struct RewardPrices {
		uint256 reward;
		uint256 holders;
		uint256 interest;
	}
	event Lockedup(address _from, address _property, uint256 _value);

	/**
	 * Initialize the passed address as AddressConfig address.
	 */
	// solium-disable-next-line no-empty-blocks
	constructor(address _config) public UsingConfig(_config) {}

	/**
	 * Adds staking.
	 * Only the Dev contract can execute this function.
	 */
	function lockup(
		address _from,
		address _property,
		uint256 _value
	) external {
		/**
		 * Validates the sender is Dev contract.
		 */
		addressValidator().validateAddress(msg.sender, config().token());

		/**
		 * Validates _value is not 0.
		 */
		require(_value != 0, "illegal lockup value");

		/**
		 * Validates the passed Property has greater than 1 asset.
		 */
		require(
			IMetricsGroup(config().metricsGroup()).hasAssets(_property),
			"unable to stake to unauthenticated property"
		);

		/**
		 * Since the reward per block that can be withdrawn will change with the addition of staking,
		 * saves the undrawn withdrawable reward before addition it.
		 */
		RewardPrices memory prices = updatePendingInterestWithdrawal(
			_property,
			_from
		);

		/**
		 * Saves variables that should change due to the addition of staking.
		 */
		updateValues(true, _from, _property, _value, prices);
		emit Lockedup(_from, _property, _value);
	}

	/**
	 * Withdraw staking.
	 * Releases staking, withdraw rewards, and transfer the staked and withdraw rewards amount to the sender.
	 */
	function withdraw(address _property, uint256 _amount) external {
		/**
		 * Validates the sender is staking to the target Property.
		 */
		require(
			hasValue(_property, msg.sender, _amount),
			"insufficient tokens staked"
		);

		/**
		 * Withdraws the staking reward
		 */
		RewardPrices memory prices = _withdrawInterest(_property);

		/**
		 * Transfer the staked amount to the sender.
		 */
		if (_amount != 0) {
			IProperty(_property).withdraw(msg.sender, _amount);
		}

		/**
		 * Saves variables that should change due to the canceling staking..
		 */
		updateValues(false, msg.sender, _property, _amount, prices);
	}

	/**
	 * Store staking states as a snapshot.
	 */
	function beforeStakesChanged(
		address _property,
		address _user,
		RewardPrices memory _prices
	) private {
		/**
		 * Gets latest cumulative holders reward for the passed Property.
		 */
		uint256 cHoldersReward = _calculateCumulativeHoldersRewardAmount(
			_prices.holders,
			_property
		);

		/**
		 * Store each value.
		 */
		setStorageLastStakedInterestPrice(_property, _user, _prices.interest);
		setStorageLastStakesChangedCumulativeReward(_prices.reward);
		setStorageLastCumulativeHoldersRewardPrice(_prices.holders);
		setStorageLastCumulativeInterestPrice(_prices.interest);
		setStorageLastCumulativeHoldersRewardAmountPerProperty(
			_property,
			cHoldersReward
		);
		setStorageLastCumulativeHoldersRewardPricePerProperty(
			_property,
			_prices.holders
		);
	}

	/**
	 * Gets latest value of cumulative sum of the reward amount, cumulative sum of the holders reward per stake, and cumulative sum of the stakers reward per stake.
	 */
	function calculateCumulativeRewardPrices()
		public
		view
		returns (
			uint256 _reward,
			uint256 _holders,
			uint256 _interest
		)
	{
		uint256 lastReward = getStorageLastStakesChangedCumulativeReward();
		uint256 lastHoldersPrice = getStorageLastCumulativeHoldersRewardPrice();
		uint256 lastInterestPrice = getStorageLastCumulativeInterestPrice();
		uint256 allStakes = getStorageAllValue();

		/**
		 * Gets latest cumulative sum of the reward amount.
		 */
		(uint256 reward, ) = dry();
		uint256 mReward = reward.mulBasis();

		/**
		 * Calculates reward unit price per staking.
		 * Later, the last cumulative sum of the reward amount is subtracted because to add the last recorded holder/staking reward.
		 */
		uint256 price = allStakes > 0
			? mReward.sub(lastReward).div(allStakes)
			: 0;

		/**
		 * Calculates the holders reward out of the total reward amount.
		 */
		uint256 holdersShare = IPolicy(config().policy()).holdersShare(
			price,
			allStakes
		);

		/**
		 * Calculates and returns each reward.
		 */
		uint256 holdersPrice = holdersShare.add(lastHoldersPrice);
		uint256 interestPrice = price.sub(holdersShare).add(lastInterestPrice);
		return (mReward, holdersPrice, interestPrice);
	}

	/**
	 * Calculates cumulative sum of the holders reward per Property.
	 * To save computing resources, it receives the latest holder rewards from a caller.
	 */
	function _calculateCumulativeHoldersRewardAmount(
		uint256 _reward,
		address _property
	) private view returns (uint256) {
		(uint256 cHoldersReward, uint256 lastReward) = (
			getStorageLastCumulativeHoldersRewardAmountPerProperty(_property),
			getStorageLastCumulativeHoldersRewardPricePerProperty(_property)
		);

		/**
		 * `cHoldersReward` contains the calculation of `lastReward`, so subtract it here.
		 */
		uint256 additionalHoldersReward = _reward.sub(lastReward).mul(
			getStoragePropertyValue(_property)
		);

		/**
		 * Calculates and returns the cumulative sum of the holder reward by adds the last recorded holder reward and the latest holder reward.
		 */
		return cHoldersReward.add(additionalHoldersReward);
	}

	/**
	 * Calculates cumulative sum of the holders reward per Property.
	 */
	function calculateCumulativeHoldersRewardAmount(address _property)
		public
		view
		returns (uint256)
	{
		(, uint256 holders, ) = calculateCumulativeRewardPrices();
		return _calculateCumulativeHoldersRewardAmount(holders, _property);
	}

	/**
	 * Updates cumulative sum of the maximum mint amount calculated by Allocator contract, the latest maximum mint amount per block,
	 * and the last recorded block number.
	 * The cumulative sum of the maximum mint amount is always added.
	 * By recording that value when the staker last stakes, the difference from the when the staker stakes can be calculated.
	 */
	function update() public {
		/**
		 * Gets the cumulative sum of the maximum mint amount and the maximum mint number per block.
		 */
		(uint256 _nextRewards, uint256 _amount) = dry();

		/**
		 * Records each value and the latest block number.
		 */
		setStorageCumulativeGlobalRewards(_nextRewards);
		setStorageLastSameRewardsAmountAndBlock(_amount, block.number);
	}

	/**
	 * Referring to the values recorded in each storage to returns the latest cumulative sum of the maximum mint amount and the latest maximum mint amount per block.
	 */
	function dry()
		private
		view
		returns (uint256 _nextRewards, uint256 _amount)
	{
		/**
		 * Gets the latest mint amount per block from Allocator contract.
		 */
		uint256 rewardsAmount = IAllocator(config().allocator())
			.calculateMaxRewardsPerBlock();

		/**
		 * Gets the maximum mint amount per block, and the last recorded block number from `LastSameRewardsAmountAndBlock` storage.
		 */
		(
			uint256 lastAmount,
			uint256 lastBlock
		) = getStorageLastSameRewardsAmountAndBlock();

		/**
		 * If the recorded maximum mint amount per block and the result of the Allocator contract are different,
		 * the result of the Allocator contract takes precedence as a maximum mint amount per block.
		 */
		uint256 lastMaxRewards = lastAmount == rewardsAmount
			? rewardsAmount
			: lastAmount;

		/**
		 * Calculates the difference between the latest block number and the last recorded block number.
		 */
		uint256 blocks = lastBlock > 0 ? block.number.sub(lastBlock) : 0;

		/**
		 * Adds the calculated new cumulative maximum mint amount to the recorded cumulative maximum mint amount.
		 */
		uint256 additionalRewards = lastMaxRewards.mul(blocks);
		uint256 nextRewards = getStorageCumulativeGlobalRewards().add(
			additionalRewards
		);

		/**
		 * Returns the latest theoretical cumulative sum of maximum mint amount and maximum mint amount per block.
		 */
		return (nextRewards, rewardsAmount);
	}

	/**
	 * Returns the staker reward as interest.
	 */
	function _calculateInterestAmount(address _property, address _user)
		private
		view
		returns (
			uint256 _amount,
			uint256 _interestPrice,
			RewardPrices memory _prices
		)
	{
		/**
		 * Get the amount the user is staking for the Property.
		 */
		uint256 lockedUpPerAccount = getStorageValue(_property, _user);

		/**
		 * Gets the cumulative sum of the interest price recorded the last time you withdrew.
		 */
		uint256 lastInterest = getStorageLastStakedInterestPrice(
			_property,
			_user
		);

		/**
		 * Gets the latest cumulative sum of the interest price.
		 */
		(
			uint256 reward,
			uint256 holders,
			uint256 interest
		) = calculateCumulativeRewardPrices();

		/**
		 * Calculates and returns the latest withdrawable reward amount from the difference.
		 */
		uint256 result = interest >= lastInterest
			? interest.sub(lastInterest).mul(lockedUpPerAccount).divBasis()
			: 0;
		return (result, interest, RewardPrices(reward, holders, interest));
	}

	/**
	 * Returns the total rewards currently available for withdrawal. (For calling from inside the contract)
	 */
	function _calculateWithdrawableInterestAmount(
		address _property,
		address _user
	) private view returns (uint256 _amount, RewardPrices memory _prices) {
		/**
		 * If the passed Property has not authenticated, returns always 0.
		 */
		if (
			IMetricsGroup(config().metricsGroup()).hasAssets(_property) == false
		) {
			return (0, RewardPrices(0, 0, 0));
		}

		/**
		 * Gets the reward amount in saved without withdrawal.
		 */
		uint256 pending = getStoragePendingInterestWithdrawal(_property, _user);

		/**
		 * Gets the reward amount of before DIP4.
		 */
		uint256 legacy = __legacyWithdrawableInterestAmount(_property, _user);

		/**
		 * Gets the latest withdrawal reward amount.
		 */
		(
			uint256 amount,
			,
			RewardPrices memory prices
		) = _calculateInterestAmount(_property, _user);

		/**
		 * Returns the sum of all values.
		 */
		uint256 withdrawableAmount = amount
			.add(pending) // solium-disable-next-line indentation
			.add(legacy);
		return (withdrawableAmount, prices);
	}

	/**
	 * Returns the total rewards currently available for withdrawal. (For calling from external of the contract)
	 */
	function calculateWithdrawableInterestAmount(
		address _property,
		address _user
	) public view returns (uint256) {
		(uint256 amount, ) = _calculateWithdrawableInterestAmount(
			_property,
			_user
		);
		return amount;
	}

	/**
	 * Withdraws staking reward as an interest.
	 */
	function _withdrawInterest(address _property)
		private
		returns (RewardPrices memory _prices)
	{
		/**
		 * Gets the withdrawable amount.
		 */
		(
			uint256 value,
			RewardPrices memory prices
		) = _calculateWithdrawableInterestAmount(_property, msg.sender);

		/**
		 * Sets the unwithdrawn reward amount to 0.
		 */
		setStoragePendingInterestWithdrawal(_property, msg.sender, 0);

		/**
		 * Creates a Dev token instance.
		 */
		ERC20Mintable erc20 = ERC20Mintable(config().token());

		/**
		 * Updates the staking status to avoid double rewards.
		 */
		setStorageLastStakedInterestPrice(
			_property,
			msg.sender,
			prices.interest
		);
		__updateLegacyWithdrawableInterestAmount(_property, msg.sender);

		/**
		 * Mints the reward.
		 */
		require(erc20.mint(msg.sender, value), "dev mint failed");

		/**
		 * Since the total supply of tokens has changed, updates the latest maximum mint amount.
		 */
		update();

		return prices;
	}

	/**
	 * Status updates with the addition or release of staking.
	 */
	function updateValues(
		bool _addition,
		address _account,
		address _property,
		uint256 _value,
		RewardPrices memory _prices
	) private {
		beforeStakesChanged(_property, _account, _prices);
		/**
		 * If added staking:
		 */
		if (_addition) {
			/**
			 * Updates the current staking amount of the protocol total.
			 */
			addAllValue(_value);

			/**
			 * Updates the current staking amount of the Property.
			 */
			addPropertyValue(_property, _value);

			/**
			 * Updates the user's current staking amount in the Property.
			 */
			addValue(_property, _account, _value);

			/**
			 * If released staking:
			 */
		} else {
			/**
			 * Updates the current staking amount of the protocol total.
			 */
			subAllValue(_value);

			/**
			 * Updates the current staking amount of the Property.
			 */
			subPropertyValue(_property, _value);

			/**
			 * Updates the current staking amount of the Property.
			 */
			subValue(_property, _account, _value);
		}

		/**
		 * Since each staking amount has changed, updates the latest maximum mint amount.
		 */
		update();
	}

	/**
	 * Returns the staking amount of the protocol total.
	 */
	function getAllValue() external view returns (uint256) {
		return getStorageAllValue();
	}

	/**
	 * Adds the staking amount of the protocol total.
	 */
	function addAllValue(uint256 _value) private {
		uint256 value = getStorageAllValue();
		value = value.add(_value);
		setStorageAllValue(value);
	}

	/**
	 * Subtracts the staking amount of the protocol total.
	 */
	function subAllValue(uint256 _value) private {
		uint256 value = getStorageAllValue();
		value = value.sub(_value);
		setStorageAllValue(value);
	}

	/**
	 * Returns the user's staking amount in the Property.
	 */
	function getValue(address _property, address _sender)
		external
		view
		returns (uint256)
	{
		return getStorageValue(_property, _sender);
	}

	/**
	 * Adds the user's staking amount in the Property.
	 */
	function addValue(
		address _property,
		address _sender,
		uint256 _value
	) private {
		uint256 value = getStorageValue(_property, _sender);
		value = value.add(_value);
		setStorageValue(_property, _sender, value);
	}

	/**
	 * Subtracts the user's staking amount in the Property.
	 */
	function subValue(
		address _property,
		address _sender,
		uint256 _value
	) private {
		uint256 value = getStorageValue(_property, _sender);
		value = value.sub(_value);
		setStorageValue(_property, _sender, value);
	}

	/**
	 * Returns whether the user is staking in the Property.
	 */
	function hasValue(
		address _property,
		address _sender,
		uint256 _amount
	) private view returns (bool) {
		uint256 value = getStorageValue(_property, _sender);
		return value >= _amount;
	}

	/**
	 * Returns the staking amount of the Property.
	 */
	function getPropertyValue(address _property)
		external
		view
		returns (uint256)
	{
		return getStoragePropertyValue(_property);
	}

	/**
	 * Adds the staking amount of the Property.
	 */
	function addPropertyValue(address _property, uint256 _value) private {
		uint256 value = getStoragePropertyValue(_property);
		value = value.add(_value);
		setStoragePropertyValue(_property, value);
	}

	/**
	 * Subtracts the staking amount of the Property.
	 */
	function subPropertyValue(address _property, uint256 _value) private {
		uint256 value = getStoragePropertyValue(_property);
		uint256 nextValue = value.sub(_value);
		setStoragePropertyValue(_property, nextValue);
	}

	/**
	 * Saves the latest reward amount as an undrawn amount.
	 */
	function updatePendingInterestWithdrawal(address _property, address _user)
		private
		returns (RewardPrices memory _prices)
	{
		/**
		 * Gets the latest reward amount.
		 */
		(
			uint256 withdrawableAmount,
			RewardPrices memory prices
		) = _calculateWithdrawableInterestAmount(_property, _user);

		/**
		 * Saves the amount to `PendingInterestWithdrawal` storage.
		 */
		setStoragePendingInterestWithdrawal(
			_property,
			_user,
			withdrawableAmount
		);

		/**
		 * Updates the reward amount of before DIP4 to prevent further addition it.
		 */
		__updateLegacyWithdrawableInterestAmount(_property, _user);

		return prices;
	}

	/**
	 * Returns the reward amount of the calculation model before DIP4.
	 * It can be calculated by subtracting "the last cumulative sum of reward unit price" from
	 * "the current cumulative sum of reward unit price," and multiplying by the staking amount.
	 */
	function __legacyWithdrawableInterestAmount(
		address _property,
		address _user
	) private view returns (uint256) {
		uint256 _last = getStorageLastInterestPrice(_property, _user);
		uint256 price = getStorageInterestPrice(_property);
		uint256 priceGap = price.sub(_last);
		uint256 lockedUpValue = getStorageValue(_property, _user);
		uint256 value = priceGap.mul(lockedUpValue);
		return value.divBasis();
	}

	/**
	 * Updates and treats the reward of before DIP4 as already received.
	 */
	function __updateLegacyWithdrawableInterestAmount(
		address _property,
		address _user
	) private {
		uint256 interestPrice = getStorageInterestPrice(_property);
		if (getStorageLastInterestPrice(_property, _user) != interestPrice) {
			setStorageLastInterestPrice(_property, _user, interestPrice);
		}
	}

	/**
	 * Updates the block number of the time of DIP4 release.
	 */
	function setDIP4GenesisBlock(uint256 _block) external onlyOwner {
		/**
		 * Validates the value is not set.
		 */
		require(getStorageDIP4GenesisBlock() == 0, "already set the value");

		/**
		 * Sets the value.
		 */
		setStorageDIP4GenesisBlock(_block);
	}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_config","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_property","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Lockedup","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"},{"constant":true,"inputs":[],"name":"basis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"calculateCumulativeHoldersRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"calculateCumulativeRewardPrices","outputs":[{"internalType":"uint256","name":"_reward","type":"uint256"},{"internalType":"uint256","name":"_holders","type":"uint256"},{"internalType":"uint256","name":"_interest","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"calculateWithdrawableInterestAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"configAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"createStorage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAllValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"getPropertyValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageAllValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageCumulativeGlobalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"getStorageCumulativeLockedUpUnitAndBlock","outputs":[{"internalType":"uint256","name":"_unit","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"getStorageCumulativeLockedUpValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageDIP4GenesisBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"getStorageInterestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStorageLastCumulativeGlobalReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"getStorageLastCumulativeHoldersRewardAmountPerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageLastCumulativeHoldersRewardPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"getStorageLastCumulativeHoldersRewardPricePerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageLastCumulativeInterestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStorageLastCumulativeLockedUpAndBlock","outputs":[{"internalType":"uint256","name":"_cLocked","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStorageLastCumulativePropertyInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStorageLastInterestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageLastSameRewardsAmountAndBlock","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStorageLastStakedInterestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStorageLastStakesChangedCumulativeReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStoragePendingInterestWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"}],"name":"getStoragePropertyValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_sender","type":"address"}],"name":"getStorageValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_sender","type":"address"}],"name":"getValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_property","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"lockup","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"setDIP4GenesisBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_storageAddress","type":"address"}],"name":"setStorage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_property","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200436138038062004361833981810160405260208110156200003757600080fd5b5051600080546001600160a01b0319166001600160a01b038316179055604051620000629062000105565b604051809103906000f0801580156200007f573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b03929092169190911790556000620000ac62000101565b600280546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3505062000113565b3390565b61072b8062003c3683390190565b613b1380620001236000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80638f32d59b1161013b578063e35e8cf1116100b8578063f385cecb1161007c578063f385cecb1461067f578063f3fef3a314610687578063f9c514e4146106b3578063fb971d01146106e1578063fd1ac3d8146106e957610248565b8063e35e8cf1146105d8578063edaf329f1461060e578063eebf293614610616578063f11248d21461063c578063f2fde38b1461065957610248565b8063af61a9c5116100ff578063af61a9c51461054e578063c311c53614610574578063c7ab3a221461057c578063d6c31871146105a2578063d85c7f4a146105aa57610248565b80638f32d59b146104b05780639137c1a7146104cc57806395490d6c146104f2578063a2e6204514610520578063a6f9dae11461052857610248565b80636afa639c116101c95780637654f7ab1161018d5780637654f7ab1461046a5780638017333d1461047257806381136f5a1461047a57806387407e4c146104a05780638da5cb5b146104a857610248565b80636afa639c146103ce5780636f968c9f146103fc578063714d69581461042a578063715018a61461043257806375b9504a1461043c57610248565b80634484ef69116102105780634484ef6914610305578063523f91b61461034457806355fac3be1461036a578063603da01d1461039857806360cec370146103c657610248565b8063076ae4771461024d5780630c71c3e814610285578063270d33bc1461028d578063322d19eb146102bb578063393a4d34146102e1575b600080fd5b6102736004803603602081101561026357600080fd5b50356001600160a01b031661070f565b60408051918252519081900360200190f35b610273610796565b610273600480360360408110156102a357600080fd5b506001600160a01b038135811691602001351661081b565b610273600480360360208110156102d157600080fd5b50356001600160a01b03166108a6565b6102e96108c7565b604080516001600160a01b039092168252519081900360200190f35b61032b6004803603602081101561031b57600080fd5b50356001600160a01b031661092c565b6040805192835260208301919091528051918290030190f35b6102736004803603602081101561035a57600080fd5b50356001600160a01b0316610a0f565b6102736004803603604081101561038057600080fd5b506001600160a01b0381358116916020013516610a30565b610273600480360360408110156103ae57600080fd5b506001600160a01b0381358116916020013516610a43565b610273610a65565b610273600480360360408110156103e457600080fd5b506001600160a01b0381358116916020013516610a85565b6102736004803603604081101561041257600080fd5b506001600160a01b0381358116916020013516610aa7565b610273610ac9565b61043a610ae9565b005b61032b6004803603604081101561045257600080fd5b506001600160a01b0381358116916020013516610b7a565b610273610c54565b610273610c63565b6102736004803603602081101561049057600080fd5b50356001600160a01b0316610c83565b610273610d0f565b6102e9610d99565b6104b8610da8565b604080519115158252519081900360200190f35b61043a600480360360208110156104e257600080fd5b50356001600160a01b0316610dce565b6102736004803603604081101561050857600080fd5b506001600160a01b0381358116916020013516610e37565b61043a610ec5565b61043a6004803603602081101561053e57600080fd5b50356001600160a01b0316610eeb565b610556610f9b565b60408051938452602084019290925282820152519081900360600190f35b610273611151565b6102736004803603602081101561059257600080fd5b50356001600160a01b0316611171565b6102e9611192565b610273600480360360408110156105c057600080fd5b506001600160a01b03813581169160200135166111a1565b61043a600480360360608110156105ee57600080fd5b506001600160a01b038135811691602081013590911690604001356111c3565b61032b611488565b6102736004803603602081101561062c57600080fd5b50356001600160a01b031661155c565b61043a6004803603602081101561065257600080fd5b5035611575565b61043a6004803603602081101561066f57600080fd5b50356001600160a01b031661161a565b61027361166a565b61043a6004803603604081101561069d57600080fd5b506001600160a01b03813516906020013561167b565b610273600480360360408110156106c957600080fd5b506001600160a01b038135811691602001351661176a565b61043a611780565b610273600480360360208110156106ff57600080fd5b50356001600160a01b0316611864565b60006107196108c7565b6001600160a01b031663bd02d0f56107308461186f565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561076457600080fd5b505afa158015610778573d6000803e3d6000fd5b505050506040513d602081101561078e57600080fd5b505192915050565b60006107a06108c7565b6001600160a01b031663bd02d0f56107b66118bf565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156107ea57600080fd5b505afa1580156107fe573d6000803e3d6000fd5b505050506040513d602081101561081457600080fd5b5051905090565b60006108256108c7565b6001600160a01b031663bd02d0f561083d85856118f0565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561087157600080fd5b505afa158015610885573d6000803e3d6000fd5b505050506040513d602081101561089b57600080fd5b505190505b92915050565b60006108b06108c7565b6001600160a01b031663bd02d0f561073084611959565b6003546000906001600160a01b031661091c576040805162461bcd60e51b81526020600482015260126024820152711cdd1bdc9859d9481a5cc81b9bdd081cd95d60721b604482015290519081900360640190fd5b506003546001600160a01b031690565b60008060006109396108c7565b6001600160a01b031663bd02d0f5610950866119b6565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561098457600080fd5b505afa158015610998573d6000803e3d6000fd5b505050506040513d60208110156109ae57600080fd5b5051905060006109d1826904ee2d6d415b85acef8160201b63ffffffff611a1316565b90506000610a026109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b849063ffffffff611aae16565b9194509092505050915091565b6000610a196108c7565b6001600160a01b031663bd02d0f561073084611af0565b6000610a3c8383610e37565b9392505050565b6000610a4d6108c7565b6001600160a01b031663bd02d0f561083d8585611b3f565b6000610a6f6108c7565b6001600160a01b031663bd02d0f56107b6611ba2565b6000610a8f6108c7565b6001600160a01b031663bd02d0f561083d8585611bde565b6000610ab16108c7565b6001600160a01b031663bd02d0f561083d8585611c40565b6000610ad36108c7565b6001600160a01b031663bd02d0f56107b6611ca9565b610af1610da8565b610b30576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6002546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600280546001600160a01b0319169055565b6000806000610b876108c7565b6001600160a01b031663bd02d0f5610b9f8787611cf1565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610bd357600080fd5b505afa158015610be7573d6000803e3d6000fd5b505050506040513d6020811015610bfd57600080fd5b505190506000610c20826904ee2d6d415b85acef8160201b63ffffffff611a1316565b90506000610c446109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b91945090925050505b9250929050565b6000610c5e610d0f565b905090565b6000610c6d6108c7565b6001600160a01b031663bd02d0f56107b6611d5a565b600080610c8f83611da2565b9050610c996108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610cdc57600080fd5b505afa158015610cf0573d6000803e3d6000fd5b505050506040513d6020811015610d0657600080fd5b50519392505050565b600080610d1a611df0565b9050610d246108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d6020811015610d9157600080fd5b505191505090565b6002546001600160a01b031690565b6002546000906001600160a01b0316610dbf611e24565b6001600160a01b031614905090565b610dd6610da8565b610e15576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600080610e448484611e28565b9050610e4e6108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610e9157600080fd5b505afa158015610ea5573d6000803e3d6000fd5b505050506040513d6020811015610ebb57600080fd5b5051949350505050565b600080610ed0611e7a565b91509150610edd82611fd0565b610ee7814361202c565b5050565b610ef3610da8565b610f32576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6003546040805163a6f9dae160e01b81526001600160a01b0384811660048301529151919092169163a6f9dae191602480830192600092919082900301818387803b158015610f8057600080fd5b505af1158015610f94573d6000803e3d6000fd5b5050505050565b600080600080610fa9610796565b90506000610fb5611151565b90506000610fc1610ac9565b90506000610fcd610d0f565b90506000610fd9611e7a565b5090506000610fe7826120ca565b90506000808411610ff9576000611019565b6110198461100d848a63ffffffff611aae16565b9063ffffffff611a1316565b90506000611025611192565b6001600160a01b0316630505c8c96040518163ffffffff1660e01b815260040160206040518083038186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d602081101561108757600080fd5b505160408051631759a88560e31b8152600481018590526024810188905290516001600160a01b039092169163bacd442891604480820192602092909190829003018186803b1580156110d957600080fd5b505afa1580156110ed573d6000803e3d6000fd5b505050506040513d602081101561110357600080fd5b505190506000611119828963ffffffff6120e416565b9050600061113d88611131868663ffffffff611aae16565b9063ffffffff6120e416565b949d919c50939a5098505050505050505050565b600061115b6108c7565b6001600160a01b031663bd02d0f56107b661213e565b600061117b6108c7565b6001600160a01b031663bd02d0f56107308461216f565b6000546001600160a01b031690565b60006111ab6108c7565b6001600160a01b031663bd02d0f561083d85856121bf565b6111cb612228565b6001600160a01b03166349616d79336111e2611192565b6001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561121a57600080fd5b505afa15801561122e573d6000803e3d6000fd5b505050506040513d602081101561124457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152516044808301926000929190829003018186803b15801561129457600080fd5b505afa1580156112a8573d6000803e3d6000fd5b5050505080600014156112f9576040805162461bcd60e51b8152602060048201526014602482015273696c6c6567616c206c6f636b75702076616c756560601b604482015290519081900360640190fd5b611301611192565b6001600160a01b031663628f043d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561133957600080fd5b505afa15801561134d573d6000803e3d6000fd5b505050506040513d602081101561136357600080fd5b505160408051638b234cb160e01b81526001600160a01b03858116600483015291519190921691638b234cb1916024808301926020929190829003018186803b1580156113af57600080fd5b505afa1580156113c3573d6000803e3d6000fd5b505050506040513d60208110156113d957600080fd5b50516114165760405162461bcd60e51b815260040180806020018281038252602b815260200180613ab4602b913960400191505060405180910390fd5b61141e612d58565b6114288385612237565b9050611438600185858585612274565b604080516001600160a01b0380871682528516602082015280820184905290517f71601c75cd9722fdbd6d57dbb30980d4a4bd6169ba3d456dc18b7f878629d7bf9181900360600190a150505050565b60008060006114956108c7565b6001600160a01b031663bd02d0f56114ab6122ce565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156114df57600080fd5b505afa1580156114f3573d6000803e3d6000fd5b505050506040513d602081101561150957600080fd5b50519050600061152c826904ee2d6d415b85acef8160201b63ffffffff611a1316565b905060006115506109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b91945090925050509091565b600080611567610f9b565b50915050610a3c8184612316565b61157d610da8565b6115bc576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6115c4610a65565b1561160e576040805162461bcd60e51b8152602060048201526015602482015274616c726561647920736574207468652076616c756560581b604482015290519081900360640190fd5b61161781612377565b50565b611622610da8565b611661576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b61161781612395565b6904ee2d6d415b85acef8160201b81565b611686823383612436565b6116d7576040805162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420746f6b656e73207374616b6564000000000000604482015290519081900360640190fd5b6116df612d58565b6116e88361244f565b90508115611757576040805163f3fef3a360e01b81523360048201526024810184905290516001600160a01b0385169163f3fef3a391604480830192600092919082900301818387803b15801561173e57600080fd5b505af1158015611752573d6000803e3d6000fd5b505050505b611765600033858585612274565b505050565b60008061177784846125d6565b50949350505050565b611788610da8565b6117c7576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6003546001600160a01b031615611816576040805162461bcd60e51b815260206004820152600e60248201526d1cdd1bdc9859d9481a5cc81cd95d60921b604482015290519081900360640190fd5b600060405161182490612d79565b604051809103906000f080158015611840573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b039290921691909117905550565b60006108a082610c83565b60008160405160200180806139b1602d9139602d01826001600160a01b03166001600160a01b031660601b8152601401915050604051602081830303815290604052805190602001209050919050565b60006040516020018080613a2560229139602201905060405160208183030381529060405280519060200120905090565b604080517f5f70656e64696e67496e7465726573745769746864726177616c0000000000006020808301919091526001600160601b0319606086811b8216603a85015285901b16604e830152825160428184030181526062909201909252805191012092915050565b604080517f5f63756d756c61746976654c6f636b6564557056616c7565000000000000000060208083019190915260609390931b6001600160601b03191660388201528151808203602c018152604c909101909152805191012090565b604080517f5f63756d756c61746976654c6f636b65645570556e6974416e64426c6f636b0060208083019190915260609390931b6001600160601b031916603f820152815180820360330181526053909101909152805191012090565b6000610a3c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612746565b600082611a64575060006108a0565b82820282848281611a7157fe5b0414610a3c5760405162461bcd60e51b8152600401808060200182810382526021815260200180613a736021913960400191505060405180910390fd5b6000610a3c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506127e8565b604080516e5f696e746572657374546f74616c7360881b60208083019190915260609390931b6001600160601b031916602f820152815180820360230181526043909101909152805191012090565b604080517f5f6c6173745374616b6564496e746572657374507269636500000000000000006020808301919091526001600160601b0319606095861b8116603884015293851b909316604c82015281518082038301815293019052815191012090565b60408051705f6469703447656e65736973426c6f636b60781b602080830191909152825180830360110181526031909201909252805191012090565b60408051755f6c6173744c617374496e746572657374507269636560501b6020808301919091526001600160601b0319606086811b8216603685015285901b16604a8301528251603e818403018152605e909201909252805191012092915050565b604080517f5f6c61737443756d756c617469766550726f7065727479496e746572657374006020808301919091526001600160601b0319606086811b8216603f85015285901b166053830152825160478184030181526067909201909252805191012092915050565b604080517f306c61737443756d756c6174697665496e7465726573745072696365000000006020808301919091528251808303601c018152603c909201909252805191012090565b604080517f5f6c61737443756d756c61746976654c6f636b65645570416e64426c6f636b006020808301919091526001600160601b0319606086811b8216603f85015285901b166053830152825160478184030181526067909201909252805191012092915050565b604080517f5f63756d756c6174697665476c6f62616c526577617264730000000000000000602080830191909152825180830360180181526038909201909252805191012090565b604080516d5f70726f706572747956616c756560901b60208083019190915260609390931b6001600160601b031916602e820152815180820360220181526042909101909152805191012090565b60408051685f616c6c56616c756560b81b602080830191909152825180830360090181526029909201909252805191012090565b3390565b60408051655f76616c756560d01b6020808301919091526001600160601b0319606086811b8216602685015285901b16603a8301528251602e818403018152604e909201909252805191012092915050565b6000806000611e87611192565b6001600160a01b031663aa5dcecc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505160408051633aa5460b60e01b815290516001600160a01b0390921691633aa5460b91600480820192602092909190829003018186803b158015611f2d57600080fd5b505afa158015611f41573d6000803e3d6000fd5b505050506040513d6020811015611f5757600080fd5b50519050600080611f66611488565b915091506000838314611f795782611f7b565b835b90506000808311611f8d576000611f9d565b611f9d438463ffffffff611aae16565b90506000611fb1838363ffffffff611a5516565b90506000611fc182611131610c63565b98509596505050505050509091565b611fd86108c7565b6001600160a01b031663e2a4853a611fee611d5a565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015610f8057600080fd5b600061204f82611131856904ee2d6d415b85acef8160201b63ffffffff611a5516565b90506120596108c7565b6001600160a01b031663e2a4853a61206f6122ce565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156120ad57600080fd5b505af11580156120c1573d6000803e3d6000fd5b50505050505050565b60006108a082670de0b6b3a764000063ffffffff611a5516565b600082820183811015610a3c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006040516020018080613a0460219139602101905060405160208183030381529060405280519060200120905090565b6000816040516020018080613a47602c9139602c01826001600160a01b03166001600160a01b031660601b8152601401915050604051602081830303815290604052805190602001209050919050565b604080517f5f4c61737443756d756c6174697665476c6f62616c52657761726400000000006020808301919091526001600160601b0319606086811b8216603b85015285901b16604f830152825160438184030181526063909201909252805191012092915050565b6001546001600160a01b031690565b61223f612d58565b6000612249612d58565b61225385856125d6565b91509150612262858584612842565b61226c8585612862565b949350505050565b61227f83858361288a565b84156122a85761228e826128ee565b6122988383612915565b6122a383858461293e565b6122c6565b6122b182612969565b6122bb8383612985565b6122c68385846129b0565b610f94610ec5565b604080517f5f4c61737453616d6552657761726473416d6f756e74416e64426c6f636b00006020808301919091528251808303601e018152603e909201909252805191012090565b60008060006123248461070f565b61232d85611171565b91509150600061235b61233f86610c83565b61234f888563ffffffff611aae16565b9063ffffffff611a5516565b905061236d838263ffffffff6120e416565b9695505050505050565b61237f6108c7565b6001600160a01b031663e2a4853a611fee611ba2565b6001600160a01b0381166123da5760405162461bcd60e51b81526004018080602001828103825260268152602001806139de6026913960400191505060405180910390fd5b6002546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806124438585610e37565b90921115949350505050565b612457612d58565b6000612461612d58565b61246b84336125d6565b9150915061247b84336000612842565b6000612485611192565b6001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124bd57600080fd5b505afa1580156124d1573d6000803e3d6000fd5b505050506040513d60208110156124e757600080fd5b505160408301519091506124fe90869033906129ce565b6125088533612862565b604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b038316916340c10f199160448083019260209291908290030181600087803b15801561255757600080fd5b505af115801561256b573d6000803e3d6000fd5b505050506040513d602081101561258157600080fd5b50516125c6576040805162461bcd60e51b815260206004820152600f60248201526e19195d881b5a5b9d0819985a5b1959608a1b604482015290519081900360640190fd5b6125ce610ec5565b509392505050565b60006125e0612d58565b6125e8611192565b6001600160a01b031663628f043d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561262057600080fd5b505afa158015612634573d6000803e3d6000fd5b505050506040513d602081101561264a57600080fd5b505160408051638b234cb160e01b81526001600160a01b03878116600483015291519190921691638b234cb1916024808301926020929190829003018186803b15801561269657600080fd5b505afa1580156126aa573d6000803e3d6000fd5b505050506040513d60208110156126c057600080fd5b50516126e957505060408051606081018252600080825260208201819052918101829052610c4d565b60006126f5858561081b565b9050600061270386866129ee565b9050600061270f612d58565b6127198888612a55565b925050915060006127378461113187866120e490919063ffffffff16565b99919850909650505050505050565b600081836127d25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561279757818101518382015260200161277f565b50505050905090810190601f1680156127c45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816127de57fe5b0495945050505050565b6000818484111561283a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561279757818101518382015260200161277f565b505050900390565b61284a6108c7565b6001600160a01b031663e2a4853a61206f85856118f0565b600061286d83610a0f565b90508061287a8484610a85565b1461176557611765838383612ae8565b600061289a826020015185612316565b90506128ab848484604001516129ce565b81516128b690612b08565b6128c38260200151612b26565b6128d08260400151612b44565b6128da8482612b62565b6128e8848360200151612bdb565b50505050565b60006128f8610d0f565b905061290a818363ffffffff6120e416565b9050610ee781612bfa565b600061292083610c83565b9050612932818363ffffffff6120e416565b90506117658382612c5b565b600061294a8484610e37565b905061295c818363ffffffff6120e416565b90506128e8848483612cbd565b6000612973610d0f565b905061290a818363ffffffff611aae16565b600061299083610c83565b905060006129a4828463ffffffff611aae16565b90506128e88482612c5b565b60006129bc8484610e37565b905061295c818363ffffffff611aae16565b6129d66108c7565b6001600160a01b031663e2a4853a61206f8585611b3f565b6000806129fb8484610a85565b90506000612a0885610a0f565b90506000612a1c828463ffffffff611aae16565b90506000612a2a8787610e37565b90506000612a3e838363ffffffff611a5516565b9050612a4981612d3e565b98975050505050505050565b600080612a60612d58565b6000612a6c8686610e37565b90506000612a7a8787610a43565b90506000806000612a89610f9b565b925092509250600084821015612aa0576000612abc565b612abc612ab78761234f858963ffffffff611aae16565b612d3e565b604080516060810182529586526020860194909452928401829052509096509450925050509250925092565b612af06108c7565b6001600160a01b031663e2a4853a61206f8585611bde565b612b106108c7565b6001600160a01b031663e2a4853a611fee6118bf565b612b2e6108c7565b6001600160a01b031663e2a4853a611fee61213e565b612b4c6108c7565b6001600160a01b031663e2a4853a611fee611ca9565b612b6a6108c7565b6001600160a01b031663e2a4853a612b818461186f565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612bbf57600080fd5b505af1158015612bd3573d6000803e3d6000fd5b505050505050565b612be36108c7565b6001600160a01b031663e2a4853a612b818461216f565b6000612c04611df0565b9050612c0e6108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612bbf57600080fd5b6000612c6683611da2565b9050612c706108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156120ad57600080fd5b6000612cc98484611e28565b9050612cd36108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612d2057600080fd5b505af1158015612d34573d6000803e3d6000fd5b5050505050505050565b60006108a082670de0b6b3a764000063ffffffff611a1316565b60405180606001604052806000815260200160008152602001600081525090565b610c2a80612d878339019056fe6080604052600080546001600160a01b0319163317905534801561002257600080fd5b50610bf8806100326000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063a6f9dae1116100ad578063d5d2c56011610071578063d5d2c560146103f5578063dc97d96214610418578063e2a4853a14610435578063e2b202bf14610458578063f6bb3cc41461047557610121565b8063a6f9dae114610332578063abfdcced14610358578063bd02d0f51461037d578063c031a180146103ac578063ca446dd9146103c957610121565b8063616b59f6116100f4578063616b59f6146101be5780636e899550146101db5780637ae1cfca146102525780638c16009514610283578063986e791a146102a057610121565b80630e14a3761461012657806321f8a721146101455780632c62ff2d1461017e5780633e49bed01461019b575b600080fd5b6101436004803603602081101561013c57600080fd5b5035610492565b005b6101626004803603602081101561015b57600080fd5b50356104fd565b604080516001600160a01b039092168252519081900360200190f35b6101436004803603602081101561019457600080fd5b5035610518565b610143600480360360408110156101b157600080fd5b508035906020013561057d565b610143600480360360208110156101d457600080fd5b50356105dc565b610143600480360360408110156101f157600080fd5b8135919081019060408101602082013564010000000081111561021357600080fd5b82018360208201111561022557600080fd5b8035906020019184600183028401116401000000008311171561024757600080fd5b50909250905061063a565b61026f6004803603602081101561026857600080fd5b50356106a6565b604080519115158252519081900360200190f35b6101436004803603602081101561029957600080fd5b50356106bb565b6102bd600480360360208110156102b657600080fd5b5035610719565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102f75781810151838201526020016102df565b50505050905090810190601f1680156103245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101436004803603602081101561034857600080fd5b50356001600160a01b03166107b8565b6101436004803603604081101561036e57600080fd5b50803590602001351515610827565b61039a6004803603602081101561039357600080fd5b5035610894565b60408051918252519081900360200190f35b61039a600480360360208110156103c257600080fd5b50356108a6565b610143600480360360408110156103df57600080fd5b50803590602001356001600160a01b03166108b8565b6101436004803603604081101561040b57600080fd5b5080359060200135610933565b61039a6004803603602081101561042e57600080fd5b5035610992565b6101436004803603604081101561044b57600080fd5b50803590602001356109a4565b6101436004803603602081101561046e57600080fd5b5035610a03565b6101436004803603602081101561048b57600080fd5b5035610a61565b6000546001600160a01b031633146104df576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260036020526040902080546001600160a01b0319169055565b6000908152600360205260409020546001600160a01b031690565b6000546001600160a01b03163314610565576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b6000908152600560205260409020805460ff19169055565b6000546001600160a01b031633146105ca576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526006602052604090912055565b6000546001600160a01b03163314610629576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260046020526040812055565b6000546001600160a01b03163314610687576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60008381526002602052604090206106a0908383610ac8565b50505050565b60009081526005602052604090205460ff1690565b6000546001600160a01b03163314610708576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260066020526040812055565b600081815260026020818152604092839020805484516001821615610100026000190190911693909304601f810183900483028401830190945283835260609390918301828280156107ac5780601f10610781576101008083540402835291602001916107ac565b820191906000526020600020905b81548152906001019060200180831161078f57829003601f168201915b50505050509050919050565b6000546001600160a01b03163314610805576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610874576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600091825260056020526040909120805460ff1916911515919091179055565b60009081526001602052604090205490565b60009081526004602052604090205490565b6000546001600160a01b03163314610905576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526003602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b03163314610980576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526004602052604090912055565b60009081526006602052604090205490565b6000546001600160a01b031633146109f1576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526001602052604090912055565b6000546001600160a01b03163314610a50576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260016020526040812055565b6000546001600160a01b03163314610aae576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b6000818152600260205260408120610ac591610b46565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610b095782800160ff19823516178555610b36565b82800160010185558215610b36579182015b82811115610b36578235825591602001919060010190610b1b565b50610b42929150610b86565b5090565b50805460018160011615610100020316600290046000825580601f10610b6c5750610ac5565b601f016020900490600052602060002090810190610ac591905b610ba091905b80821115610b425760008155600101610b8c565b9056fe6e6f742063757272656e74206f776e6572000000000000000000000000000000a265627a7a7231582057b8f79d63d7401460f294f799b49ede95894ae9e0caba7b38d88fb5d7c66fd364736f6c63430005110032306c61737443756d756c6174697665486f6c64657273526577617264416d6f756e7450657250726f70657274794f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373306c61737443756d756c6174697665486f6c6465727352657761726450726963655f6c6173745374616b65734368616e67656443756d756c6174697665526577617264306c61737443756d756c6174697665486f6c64657273526577617264507269636550657250726f7065727479536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572756e61626c6520746f207374616b6520746f20756e61757468656e746963617465642070726f7065727479a265627a7a723158205d54435503e59cd9260c03e4b2d4887800a0a05ae2aad2e5a34b69acfe9f9b8464736f6c63430005110032608060405234801561001057600080fd5b5061070b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80631bde7d8f1461006757806349616d79146100a75780636dd893b9146100d5578063a21929631461010d578063b292b54914610145578063d16ff4701461016b575b600080fd5b6100a56004803603608081101561007d57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516610199565b005b6100a5600480360360408110156100bd57600080fd5b506001600160a01b03813581169160200135166102a1565b6100a5600480360360608110156100eb57600080fd5b506001600160a01b03813581169160208101358216916040909101351661032b565b6100a56004803603606081101561012357600080fd5b506001600160a01b0381358116916020810135821691604090910135166103cf565b6100a56004803603602081101561015b57600080fd5b50356001600160a01b031661054b565b6100a56004803603604081101561018157600080fd5b506001600160a01b03813581169160200135166105c6565b826001600160a01b0316846001600160a01b031614156101b85761029b565b816001600160a01b0316846001600160a01b031614156101d75761029b565b806001600160a01b0316846001600160a01b0316146040518060400160405280601781526020016000805160206106b7833981519152815250906102995760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561025e578181015183820152602001610246565b50505050905090810190601f16801561028b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505b50505050565b806001600160a01b0316826001600160a01b0316146040518060400160405280601781526020016000805160206106b7833981519152815250906103265760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561025e578181015183820152602001610246565b505050565b816001600160a01b0316836001600160a01b0316141561034a57610326565b806001600160a01b0316836001600160a01b0316146040518060400160405280601781526020016000805160206106b78339815191528152509061029b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561025e578181015183820152602001610246565b816001600160a01b0316639e0cc3c4846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561042557600080fd5b505afa158015610439573d6000803e3d6000fd5b505050506040513d602081101561044f57600080fd5b50511561045b57610326565b806001600160a01b0316639e0cc3c4846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156104b157600080fd5b505afa1580156104c5573d6000803e3d6000fd5b505050506040513d60208110156104db57600080fd5b505160408051808201909152601781526000805160206106b783398151915260208201529061029b5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561025e578181015183820152602001610246565b60408051808201909152601781526000805160206106b783398151915260208201526001600160a01b0382166105c25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561025e578181015183820152602001610246565b5050565b806001600160a01b0316639e0cc3c4836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561061c57600080fd5b505afa158015610630573d6000803e3d6000fd5b505050506040513d602081101561064657600080fd5b505160408051808201909152601781526000805160206106b78339815191526020820152906103265760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561025e57818101518382015260200161024656fe7468697320697320696c6c6567616c2061646472657373000000000000000000a265627a7a723158203f56f68666d8539eb2b32e34ee2367d8fa1c02fcfd94cf25d12f11de94b1dfc464736f6c634300051100320000000000000000000000001d415aa39d647834786eb9b5a333a50e9935b796

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c80638f32d59b1161013b578063e35e8cf1116100b8578063f385cecb1161007c578063f385cecb1461067f578063f3fef3a314610687578063f9c514e4146106b3578063fb971d01146106e1578063fd1ac3d8146106e957610248565b8063e35e8cf1146105d8578063edaf329f1461060e578063eebf293614610616578063f11248d21461063c578063f2fde38b1461065957610248565b8063af61a9c5116100ff578063af61a9c51461054e578063c311c53614610574578063c7ab3a221461057c578063d6c31871146105a2578063d85c7f4a146105aa57610248565b80638f32d59b146104b05780639137c1a7146104cc57806395490d6c146104f2578063a2e6204514610520578063a6f9dae11461052857610248565b80636afa639c116101c95780637654f7ab1161018d5780637654f7ab1461046a5780638017333d1461047257806381136f5a1461047a57806387407e4c146104a05780638da5cb5b146104a857610248565b80636afa639c146103ce5780636f968c9f146103fc578063714d69581461042a578063715018a61461043257806375b9504a1461043c57610248565b80634484ef69116102105780634484ef6914610305578063523f91b61461034457806355fac3be1461036a578063603da01d1461039857806360cec370146103c657610248565b8063076ae4771461024d5780630c71c3e814610285578063270d33bc1461028d578063322d19eb146102bb578063393a4d34146102e1575b600080fd5b6102736004803603602081101561026357600080fd5b50356001600160a01b031661070f565b60408051918252519081900360200190f35b610273610796565b610273600480360360408110156102a357600080fd5b506001600160a01b038135811691602001351661081b565b610273600480360360208110156102d157600080fd5b50356001600160a01b03166108a6565b6102e96108c7565b604080516001600160a01b039092168252519081900360200190f35b61032b6004803603602081101561031b57600080fd5b50356001600160a01b031661092c565b6040805192835260208301919091528051918290030190f35b6102736004803603602081101561035a57600080fd5b50356001600160a01b0316610a0f565b6102736004803603604081101561038057600080fd5b506001600160a01b0381358116916020013516610a30565b610273600480360360408110156103ae57600080fd5b506001600160a01b0381358116916020013516610a43565b610273610a65565b610273600480360360408110156103e457600080fd5b506001600160a01b0381358116916020013516610a85565b6102736004803603604081101561041257600080fd5b506001600160a01b0381358116916020013516610aa7565b610273610ac9565b61043a610ae9565b005b61032b6004803603604081101561045257600080fd5b506001600160a01b0381358116916020013516610b7a565b610273610c54565b610273610c63565b6102736004803603602081101561049057600080fd5b50356001600160a01b0316610c83565b610273610d0f565b6102e9610d99565b6104b8610da8565b604080519115158252519081900360200190f35b61043a600480360360208110156104e257600080fd5b50356001600160a01b0316610dce565b6102736004803603604081101561050857600080fd5b506001600160a01b0381358116916020013516610e37565b61043a610ec5565b61043a6004803603602081101561053e57600080fd5b50356001600160a01b0316610eeb565b610556610f9b565b60408051938452602084019290925282820152519081900360600190f35b610273611151565b6102736004803603602081101561059257600080fd5b50356001600160a01b0316611171565b6102e9611192565b610273600480360360408110156105c057600080fd5b506001600160a01b03813581169160200135166111a1565b61043a600480360360608110156105ee57600080fd5b506001600160a01b038135811691602081013590911690604001356111c3565b61032b611488565b6102736004803603602081101561062c57600080fd5b50356001600160a01b031661155c565b61043a6004803603602081101561065257600080fd5b5035611575565b61043a6004803603602081101561066f57600080fd5b50356001600160a01b031661161a565b61027361166a565b61043a6004803603604081101561069d57600080fd5b506001600160a01b03813516906020013561167b565b610273600480360360408110156106c957600080fd5b506001600160a01b038135811691602001351661176a565b61043a611780565b610273600480360360208110156106ff57600080fd5b50356001600160a01b0316611864565b60006107196108c7565b6001600160a01b031663bd02d0f56107308461186f565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561076457600080fd5b505afa158015610778573d6000803e3d6000fd5b505050506040513d602081101561078e57600080fd5b505192915050565b60006107a06108c7565b6001600160a01b031663bd02d0f56107b66118bf565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156107ea57600080fd5b505afa1580156107fe573d6000803e3d6000fd5b505050506040513d602081101561081457600080fd5b5051905090565b60006108256108c7565b6001600160a01b031663bd02d0f561083d85856118f0565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561087157600080fd5b505afa158015610885573d6000803e3d6000fd5b505050506040513d602081101561089b57600080fd5b505190505b92915050565b60006108b06108c7565b6001600160a01b031663bd02d0f561073084611959565b6003546000906001600160a01b031661091c576040805162461bcd60e51b81526020600482015260126024820152711cdd1bdc9859d9481a5cc81b9bdd081cd95d60721b604482015290519081900360640190fd5b506003546001600160a01b031690565b60008060006109396108c7565b6001600160a01b031663bd02d0f5610950866119b6565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561098457600080fd5b505afa158015610998573d6000803e3d6000fd5b505050506040513d60208110156109ae57600080fd5b5051905060006109d1826904ee2d6d415b85acef8160201b63ffffffff611a1316565b90506000610a026109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b849063ffffffff611aae16565b9194509092505050915091565b6000610a196108c7565b6001600160a01b031663bd02d0f561073084611af0565b6000610a3c8383610e37565b9392505050565b6000610a4d6108c7565b6001600160a01b031663bd02d0f561083d8585611b3f565b6000610a6f6108c7565b6001600160a01b031663bd02d0f56107b6611ba2565b6000610a8f6108c7565b6001600160a01b031663bd02d0f561083d8585611bde565b6000610ab16108c7565b6001600160a01b031663bd02d0f561083d8585611c40565b6000610ad36108c7565b6001600160a01b031663bd02d0f56107b6611ca9565b610af1610da8565b610b30576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6002546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600280546001600160a01b0319169055565b6000806000610b876108c7565b6001600160a01b031663bd02d0f5610b9f8787611cf1565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610bd357600080fd5b505afa158015610be7573d6000803e3d6000fd5b505050506040513d6020811015610bfd57600080fd5b505190506000610c20826904ee2d6d415b85acef8160201b63ffffffff611a1316565b90506000610c446109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b91945090925050505b9250929050565b6000610c5e610d0f565b905090565b6000610c6d6108c7565b6001600160a01b031663bd02d0f56107b6611d5a565b600080610c8f83611da2565b9050610c996108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610cdc57600080fd5b505afa158015610cf0573d6000803e3d6000fd5b505050506040513d6020811015610d0657600080fd5b50519392505050565b600080610d1a611df0565b9050610d246108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d6020811015610d9157600080fd5b505191505090565b6002546001600160a01b031690565b6002546000906001600160a01b0316610dbf611e24565b6001600160a01b031614905090565b610dd6610da8565b610e15576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600080610e448484611e28565b9050610e4e6108c7565b6001600160a01b031663bd02d0f5826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610e9157600080fd5b505afa158015610ea5573d6000803e3d6000fd5b505050506040513d6020811015610ebb57600080fd5b5051949350505050565b600080610ed0611e7a565b91509150610edd82611fd0565b610ee7814361202c565b5050565b610ef3610da8565b610f32576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6003546040805163a6f9dae160e01b81526001600160a01b0384811660048301529151919092169163a6f9dae191602480830192600092919082900301818387803b158015610f8057600080fd5b505af1158015610f94573d6000803e3d6000fd5b5050505050565b600080600080610fa9610796565b90506000610fb5611151565b90506000610fc1610ac9565b90506000610fcd610d0f565b90506000610fd9611e7a565b5090506000610fe7826120ca565b90506000808411610ff9576000611019565b6110198461100d848a63ffffffff611aae16565b9063ffffffff611a1316565b90506000611025611192565b6001600160a01b0316630505c8c96040518163ffffffff1660e01b815260040160206040518083038186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d602081101561108757600080fd5b505160408051631759a88560e31b8152600481018590526024810188905290516001600160a01b039092169163bacd442891604480820192602092909190829003018186803b1580156110d957600080fd5b505afa1580156110ed573d6000803e3d6000fd5b505050506040513d602081101561110357600080fd5b505190506000611119828963ffffffff6120e416565b9050600061113d88611131868663ffffffff611aae16565b9063ffffffff6120e416565b949d919c50939a5098505050505050505050565b600061115b6108c7565b6001600160a01b031663bd02d0f56107b661213e565b600061117b6108c7565b6001600160a01b031663bd02d0f56107308461216f565b6000546001600160a01b031690565b60006111ab6108c7565b6001600160a01b031663bd02d0f561083d85856121bf565b6111cb612228565b6001600160a01b03166349616d79336111e2611192565b6001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561121a57600080fd5b505afa15801561122e573d6000803e3d6000fd5b505050506040513d602081101561124457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152516044808301926000929190829003018186803b15801561129457600080fd5b505afa1580156112a8573d6000803e3d6000fd5b5050505080600014156112f9576040805162461bcd60e51b8152602060048201526014602482015273696c6c6567616c206c6f636b75702076616c756560601b604482015290519081900360640190fd5b611301611192565b6001600160a01b031663628f043d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561133957600080fd5b505afa15801561134d573d6000803e3d6000fd5b505050506040513d602081101561136357600080fd5b505160408051638b234cb160e01b81526001600160a01b03858116600483015291519190921691638b234cb1916024808301926020929190829003018186803b1580156113af57600080fd5b505afa1580156113c3573d6000803e3d6000fd5b505050506040513d60208110156113d957600080fd5b50516114165760405162461bcd60e51b815260040180806020018281038252602b815260200180613ab4602b913960400191505060405180910390fd5b61141e612d58565b6114288385612237565b9050611438600185858585612274565b604080516001600160a01b0380871682528516602082015280820184905290517f71601c75cd9722fdbd6d57dbb30980d4a4bd6169ba3d456dc18b7f878629d7bf9181900360600190a150505050565b60008060006114956108c7565b6001600160a01b031663bd02d0f56114ab6122ce565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156114df57600080fd5b505afa1580156114f3573d6000803e3d6000fd5b505050506040513d602081101561150957600080fd5b50519050600061152c826904ee2d6d415b85acef8160201b63ffffffff611a1316565b905060006115506109f5836904ee2d6d415b85acef8160201b63ffffffff611a5516565b91945090925050509091565b600080611567610f9b565b50915050610a3c8184612316565b61157d610da8565b6115bc576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6115c4610a65565b1561160e576040805162461bcd60e51b8152602060048201526015602482015274616c726561647920736574207468652076616c756560581b604482015290519081900360640190fd5b61161781612377565b50565b611622610da8565b611661576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b61161781612395565b6904ee2d6d415b85acef8160201b81565b611686823383612436565b6116d7576040805162461bcd60e51b815260206004820152601a60248201527f696e73756666696369656e7420746f6b656e73207374616b6564000000000000604482015290519081900360640190fd5b6116df612d58565b6116e88361244f565b90508115611757576040805163f3fef3a360e01b81523360048201526024810184905290516001600160a01b0385169163f3fef3a391604480830192600092919082900301818387803b15801561173e57600080fd5b505af1158015611752573d6000803e3d6000fd5b505050505b611765600033858585612274565b505050565b60008061177784846125d6565b50949350505050565b611788610da8565b6117c7576040805162461bcd60e51b81526020600482018190526024820152600080516020613a94833981519152604482015290519081900360640190fd5b6003546001600160a01b031615611816576040805162461bcd60e51b815260206004820152600e60248201526d1cdd1bdc9859d9481a5cc81cd95d60921b604482015290519081900360640190fd5b600060405161182490612d79565b604051809103906000f080158015611840573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b039290921691909117905550565b60006108a082610c83565b60008160405160200180806139b1602d9139602d01826001600160a01b03166001600160a01b031660601b8152601401915050604051602081830303815290604052805190602001209050919050565b60006040516020018080613a2560229139602201905060405160208183030381529060405280519060200120905090565b604080517f5f70656e64696e67496e7465726573745769746864726177616c0000000000006020808301919091526001600160601b0319606086811b8216603a85015285901b16604e830152825160428184030181526062909201909252805191012092915050565b604080517f5f63756d756c61746976654c6f636b6564557056616c7565000000000000000060208083019190915260609390931b6001600160601b03191660388201528151808203602c018152604c909101909152805191012090565b604080517f5f63756d756c61746976654c6f636b65645570556e6974416e64426c6f636b0060208083019190915260609390931b6001600160601b031916603f820152815180820360330181526053909101909152805191012090565b6000610a3c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612746565b600082611a64575060006108a0565b82820282848281611a7157fe5b0414610a3c5760405162461bcd60e51b8152600401808060200182810382526021815260200180613a736021913960400191505060405180910390fd5b6000610a3c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506127e8565b604080516e5f696e746572657374546f74616c7360881b60208083019190915260609390931b6001600160601b031916602f820152815180820360230181526043909101909152805191012090565b604080517f5f6c6173745374616b6564496e746572657374507269636500000000000000006020808301919091526001600160601b0319606095861b8116603884015293851b909316604c82015281518082038301815293019052815191012090565b60408051705f6469703447656e65736973426c6f636b60781b602080830191909152825180830360110181526031909201909252805191012090565b60408051755f6c6173744c617374496e746572657374507269636560501b6020808301919091526001600160601b0319606086811b8216603685015285901b16604a8301528251603e818403018152605e909201909252805191012092915050565b604080517f5f6c61737443756d756c617469766550726f7065727479496e746572657374006020808301919091526001600160601b0319606086811b8216603f85015285901b166053830152825160478184030181526067909201909252805191012092915050565b604080517f306c61737443756d756c6174697665496e7465726573745072696365000000006020808301919091528251808303601c018152603c909201909252805191012090565b604080517f5f6c61737443756d756c61746976654c6f636b65645570416e64426c6f636b006020808301919091526001600160601b0319606086811b8216603f85015285901b166053830152825160478184030181526067909201909252805191012092915050565b604080517f5f63756d756c6174697665476c6f62616c526577617264730000000000000000602080830191909152825180830360180181526038909201909252805191012090565b604080516d5f70726f706572747956616c756560901b60208083019190915260609390931b6001600160601b031916602e820152815180820360220181526042909101909152805191012090565b60408051685f616c6c56616c756560b81b602080830191909152825180830360090181526029909201909252805191012090565b3390565b60408051655f76616c756560d01b6020808301919091526001600160601b0319606086811b8216602685015285901b16603a8301528251602e818403018152604e909201909252805191012092915050565b6000806000611e87611192565b6001600160a01b031663aa5dcecc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505160408051633aa5460b60e01b815290516001600160a01b0390921691633aa5460b91600480820192602092909190829003018186803b158015611f2d57600080fd5b505afa158015611f41573d6000803e3d6000fd5b505050506040513d6020811015611f5757600080fd5b50519050600080611f66611488565b915091506000838314611f795782611f7b565b835b90506000808311611f8d576000611f9d565b611f9d438463ffffffff611aae16565b90506000611fb1838363ffffffff611a5516565b90506000611fc182611131610c63565b98509596505050505050509091565b611fd86108c7565b6001600160a01b031663e2a4853a611fee611d5a565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015610f8057600080fd5b600061204f82611131856904ee2d6d415b85acef8160201b63ffffffff611a5516565b90506120596108c7565b6001600160a01b031663e2a4853a61206f6122ce565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156120ad57600080fd5b505af11580156120c1573d6000803e3d6000fd5b50505050505050565b60006108a082670de0b6b3a764000063ffffffff611a5516565b600082820183811015610a3c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006040516020018080613a0460219139602101905060405160208183030381529060405280519060200120905090565b6000816040516020018080613a47602c9139602c01826001600160a01b03166001600160a01b031660601b8152601401915050604051602081830303815290604052805190602001209050919050565b604080517f5f4c61737443756d756c6174697665476c6f62616c52657761726400000000006020808301919091526001600160601b0319606086811b8216603b85015285901b16604f830152825160438184030181526063909201909252805191012092915050565b6001546001600160a01b031690565b61223f612d58565b6000612249612d58565b61225385856125d6565b91509150612262858584612842565b61226c8585612862565b949350505050565b61227f83858361288a565b84156122a85761228e826128ee565b6122988383612915565b6122a383858461293e565b6122c6565b6122b182612969565b6122bb8383612985565b6122c68385846129b0565b610f94610ec5565b604080517f5f4c61737453616d6552657761726473416d6f756e74416e64426c6f636b00006020808301919091528251808303601e018152603e909201909252805191012090565b60008060006123248461070f565b61232d85611171565b91509150600061235b61233f86610c83565b61234f888563ffffffff611aae16565b9063ffffffff611a5516565b905061236d838263ffffffff6120e416565b9695505050505050565b61237f6108c7565b6001600160a01b031663e2a4853a611fee611ba2565b6001600160a01b0381166123da5760405162461bcd60e51b81526004018080602001828103825260268152602001806139de6026913960400191505060405180910390fd5b6002546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000806124438585610e37565b90921115949350505050565b612457612d58565b6000612461612d58565b61246b84336125d6565b9150915061247b84336000612842565b6000612485611192565b6001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124bd57600080fd5b505afa1580156124d1573d6000803e3d6000fd5b505050506040513d60208110156124e757600080fd5b505160408301519091506124fe90869033906129ce565b6125088533612862565b604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b038316916340c10f199160448083019260209291908290030181600087803b15801561255757600080fd5b505af115801561256b573d6000803e3d6000fd5b505050506040513d602081101561258157600080fd5b50516125c6576040805162461bcd60e51b815260206004820152600f60248201526e19195d881b5a5b9d0819985a5b1959608a1b604482015290519081900360640190fd5b6125ce610ec5565b509392505050565b60006125e0612d58565b6125e8611192565b6001600160a01b031663628f043d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561262057600080fd5b505afa158015612634573d6000803e3d6000fd5b505050506040513d602081101561264a57600080fd5b505160408051638b234cb160e01b81526001600160a01b03878116600483015291519190921691638b234cb1916024808301926020929190829003018186803b15801561269657600080fd5b505afa1580156126aa573d6000803e3d6000fd5b505050506040513d60208110156126c057600080fd5b50516126e957505060408051606081018252600080825260208201819052918101829052610c4d565b60006126f5858561081b565b9050600061270386866129ee565b9050600061270f612d58565b6127198888612a55565b925050915060006127378461113187866120e490919063ffffffff16565b99919850909650505050505050565b600081836127d25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561279757818101518382015260200161277f565b50505050905090810190601f1680156127c45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816127de57fe5b0495945050505050565b6000818484111561283a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561279757818101518382015260200161277f565b505050900390565b61284a6108c7565b6001600160a01b031663e2a4853a61206f85856118f0565b600061286d83610a0f565b90508061287a8484610a85565b1461176557611765838383612ae8565b600061289a826020015185612316565b90506128ab848484604001516129ce565b81516128b690612b08565b6128c38260200151612b26565b6128d08260400151612b44565b6128da8482612b62565b6128e8848360200151612bdb565b50505050565b60006128f8610d0f565b905061290a818363ffffffff6120e416565b9050610ee781612bfa565b600061292083610c83565b9050612932818363ffffffff6120e416565b90506117658382612c5b565b600061294a8484610e37565b905061295c818363ffffffff6120e416565b90506128e8848483612cbd565b6000612973610d0f565b905061290a818363ffffffff611aae16565b600061299083610c83565b905060006129a4828463ffffffff611aae16565b90506128e88482612c5b565b60006129bc8484610e37565b905061295c818363ffffffff611aae16565b6129d66108c7565b6001600160a01b031663e2a4853a61206f8585611b3f565b6000806129fb8484610a85565b90506000612a0885610a0f565b90506000612a1c828463ffffffff611aae16565b90506000612a2a8787610e37565b90506000612a3e838363ffffffff611a5516565b9050612a4981612d3e565b98975050505050505050565b600080612a60612d58565b6000612a6c8686610e37565b90506000612a7a8787610a43565b90506000806000612a89610f9b565b925092509250600084821015612aa0576000612abc565b612abc612ab78761234f858963ffffffff611aae16565b612d3e565b604080516060810182529586526020860194909452928401829052509096509450925050509250925092565b612af06108c7565b6001600160a01b031663e2a4853a61206f8585611bde565b612b106108c7565b6001600160a01b031663e2a4853a611fee6118bf565b612b2e6108c7565b6001600160a01b031663e2a4853a611fee61213e565b612b4c6108c7565b6001600160a01b031663e2a4853a611fee611ca9565b612b6a6108c7565b6001600160a01b031663e2a4853a612b818461186f565b836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612bbf57600080fd5b505af1158015612bd3573d6000803e3d6000fd5b505050505050565b612be36108c7565b6001600160a01b031663e2a4853a612b818461216f565b6000612c04611df0565b9050612c0e6108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612bbf57600080fd5b6000612c6683611da2565b9050612c706108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156120ad57600080fd5b6000612cc98484611e28565b9050612cd36108c7565b6001600160a01b031663e2a4853a82846040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612d2057600080fd5b505af1158015612d34573d6000803e3d6000fd5b5050505050505050565b60006108a082670de0b6b3a764000063ffffffff611a1316565b60405180606001604052806000815260200160008152602001600081525090565b610c2a80612d878339019056fe6080604052600080546001600160a01b0319163317905534801561002257600080fd5b50610bf8806100326000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063a6f9dae1116100ad578063d5d2c56011610071578063d5d2c560146103f5578063dc97d96214610418578063e2a4853a14610435578063e2b202bf14610458578063f6bb3cc41461047557610121565b8063a6f9dae114610332578063abfdcced14610358578063bd02d0f51461037d578063c031a180146103ac578063ca446dd9146103c957610121565b8063616b59f6116100f4578063616b59f6146101be5780636e899550146101db5780637ae1cfca146102525780638c16009514610283578063986e791a146102a057610121565b80630e14a3761461012657806321f8a721146101455780632c62ff2d1461017e5780633e49bed01461019b575b600080fd5b6101436004803603602081101561013c57600080fd5b5035610492565b005b6101626004803603602081101561015b57600080fd5b50356104fd565b604080516001600160a01b039092168252519081900360200190f35b6101436004803603602081101561019457600080fd5b5035610518565b610143600480360360408110156101b157600080fd5b508035906020013561057d565b610143600480360360208110156101d457600080fd5b50356105dc565b610143600480360360408110156101f157600080fd5b8135919081019060408101602082013564010000000081111561021357600080fd5b82018360208201111561022557600080fd5b8035906020019184600183028401116401000000008311171561024757600080fd5b50909250905061063a565b61026f6004803603602081101561026857600080fd5b50356106a6565b604080519115158252519081900360200190f35b6101436004803603602081101561029957600080fd5b50356106bb565b6102bd600480360360208110156102b657600080fd5b5035610719565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102f75781810151838201526020016102df565b50505050905090810190601f1680156103245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101436004803603602081101561034857600080fd5b50356001600160a01b03166107b8565b6101436004803603604081101561036e57600080fd5b50803590602001351515610827565b61039a6004803603602081101561039357600080fd5b5035610894565b60408051918252519081900360200190f35b61039a600480360360208110156103c257600080fd5b50356108a6565b610143600480360360408110156103df57600080fd5b50803590602001356001600160a01b03166108b8565b6101436004803603604081101561040b57600080fd5b5080359060200135610933565b61039a6004803603602081101561042e57600080fd5b5035610992565b6101436004803603604081101561044b57600080fd5b50803590602001356109a4565b6101436004803603602081101561046e57600080fd5b5035610a03565b6101436004803603602081101561048b57600080fd5b5035610a61565b6000546001600160a01b031633146104df576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260036020526040902080546001600160a01b0319169055565b6000908152600360205260409020546001600160a01b031690565b6000546001600160a01b03163314610565576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b6000908152600560205260409020805460ff19169055565b6000546001600160a01b031633146105ca576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526006602052604090912055565b6000546001600160a01b03163314610629576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260046020526040812055565b6000546001600160a01b03163314610687576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60008381526002602052604090206106a0908383610ac8565b50505050565b60009081526005602052604090205460ff1690565b6000546001600160a01b03163314610708576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260066020526040812055565b600081815260026020818152604092839020805484516001821615610100026000190190911693909304601f810183900483028401830190945283835260609390918301828280156107ac5780601f10610781576101008083540402835291602001916107ac565b820191906000526020600020905b81548152906001019060200180831161078f57829003601f168201915b50505050509050919050565b6000546001600160a01b03163314610805576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610874576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600091825260056020526040909120805460ff1916911515919091179055565b60009081526001602052604090205490565b60009081526004602052604090205490565b6000546001600160a01b03163314610905576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526003602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b03163314610980576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526004602052604090912055565b60009081526006602052604090205490565b6000546001600160a01b031633146109f1576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b60009182526001602052604090912055565b6000546001600160a01b03163314610a50576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b600090815260016020526040812055565b6000546001600160a01b03163314610aae576040805162461bcd60e51b81526020600482015260116024820152600080516020610ba4833981519152604482015290519081900360640190fd5b6000818152600260205260408120610ac591610b46565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610b095782800160ff19823516178555610b36565b82800160010185558215610b36579182015b82811115610b36578235825591602001919060010190610b1b565b50610b42929150610b86565b5090565b50805460018160011615610100020316600290046000825580601f10610b6c5750610ac5565b601f016020900490600052602060002090810190610ac591905b610ba091905b80821115610b425760008155600101610b8c565b9056fe6e6f742063757272656e74206f776e6572000000000000000000000000000000a265627a7a7231582057b8f79d63d7401460f294f799b49ede95894ae9e0caba7b38d88fb5d7c66fd364736f6c63430005110032306c61737443756d756c6174697665486f6c64657273526577617264416d6f756e7450657250726f70657274794f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373306c61737443756d756c6174697665486f6c6465727352657761726450726963655f6c6173745374616b65734368616e67656443756d756c6174697665526577617264306c61737443756d756c6174697665486f6c64657273526577617264507269636550657250726f7065727479536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572756e61626c6520746f207374616b6520746f20756e61757468656e746963617465642070726f7065727479a265627a7a723158205d54435503e59cd9260c03e4b2d4887800a0a05ae2aad2e5a34b69acfe9f9b8464736f6c63430005110032

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

0000000000000000000000001d415aa39d647834786eb9b5a333a50e9935b796

-----Decoded View---------------
Arg [0] : _config (address): 0x1D415aa39D647834786EB9B5a333A50e9935b796

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001d415aa39d647834786eb9b5a333a50e9935b796


Deployed Bytecode Sourcemap

59326:17866:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59326:17866:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53524:259;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;53524:259:0;-1:-1:-1;;;;;53524:259:0;;:::i;:::-;;;;;;;;;;;;;;;;51612:202;;;:::i;48698:233::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;48698:233:0;;;;;;;;;;:::i;48049:200::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48049:200:0;-1:-1:-1;;;;;48049:200:0;;:::i;39898:97::-;;;:::i;:::-;;;;-1:-1:-1;;;;;39898:97:0;;;;;;;;;;;;;;47245:362;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47245:362:0;-1:-1:-1;;;;;47245:362:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;42969:173;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42969:173:0;-1:-1:-1;;;;;42969:173:0;;:::i;73211:149::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;73211:149:0;;;;;;;;;;:::i;50915:230::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;50915:230:0;;;;;;;;;;:::i;49333:142::-;;;:::i;43564:218::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;43564:218:0;;;;;;;;;;:::i;46412:243::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;46412:243:0;;;;;;;;;;:::i;52846:190::-;;;:::i;27022:140::-;;;:::i;:::-;;49976:405;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;49976:405:0;;;;;;;;;;:::i;72601:92::-;;;:::i;45034:156::-;;;:::i;42329:195::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42329:195:0;-1:-1:-1;;;;;42329:195:0;;:::i;41229:148::-;;;:::i;26211:79::-;;;:::i;26577:94::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;40491:100;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40491:100:0;-1:-1:-1;;;;;40491:100:0;;:::i;41726:205::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;41726:205:0;;;;;;;;;;:::i;65627:381::-;;;:::i;40720:114::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40720:114:0;-1:-1:-1;;;;;40720:114:0;;:::i;62730:1263::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;52242:200;;;:::i;54349:257::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54349:257:0;-1:-1:-1;;;;;54349:257:0;;:::i;34120:90::-;;;:::i;45630:235::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;45630:235:0;;;;;;;;;;:::i;59887:992::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;59887:992:0;;;;;;;;;;;;;;;;;:::i;44304:350::-;;;:::i;65000:246::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65000:246:0;-1:-1:-1;;;;;65000:246:0;;:::i;76919:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;76919:270:0;;:::i;27317:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27317:109:0;-1:-1:-1;;;;;27317:109:0;;:::i;40998:65::-;;;:::i;61027:654::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;61027:654:0;;;;;;;;:::i;70020:235::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;70020:235:0;;;;;;;;;;:::i;40178:177::-;;;:::i;74305:139::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;74305:139:0;-1:-1:-1;;;;;74305:139:0;;:::i;53524:259::-;53635:7;53660:16;:14;:16::i;:::-;-1:-1:-1;;;;;53660:24:0;;53691:81;53756:9;53691:57;:81::i;:::-;53660:118;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53660:118:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53660:118:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;53660:118:0;;53524:259;-1:-1:-1;;53524:259:0:o;51612:202::-;51697:7;51724:16;:14;:16::i;:::-;-1:-1:-1;;;;;51724:24:0;;51755:48;:46;:48::i;:::-;51724:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51724:85:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;51724:85:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;51724:85:0;;-1:-1:-1;51612:202:0;:::o;48698:233::-;48808:7;48833:16;:14;:16::i;:::-;-1:-1:-1;;;;;48833:24:0;;48864:56;48903:9;48914:5;48864:38;:56::i;:::-;48833:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48833:93:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48833:93:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48833:93:0;;-1:-1:-1;48698:233:0;;;;;:::o;48049:200::-;48137:7;48164:16;:14;:16::i;:::-;-1:-1:-1;;;;;48164:24:0;;48195:43;48232:5;48195:36;:43::i;39898:97::-;39586:8;;39961:7;;-1:-1:-1;;;;;39586:8:0;39578:53;;;;;-1:-1:-1;;;39578:53:0;;;;;;;;;;;;-1:-1:-1;;;39578:53:0;;;;;;;;;;;;;;;-1:-1:-1;39982:8:0;;-1:-1:-1;;;;;39982:8:0;39898:97;:::o;47245:362::-;47340:13;47355:14;47378;47395:16;:14;:16::i;:::-;-1:-1:-1;;;;;47395:24:0;;47425:50;47469:5;47425:43;:50::i;:::-;47395:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;47395:85:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;47395:85:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47395:85:0;;-1:-1:-1;47485:12:0;47500:17;47395:85;-1:-1:-1;;;47500:17:0;:10;:17;:::i;:::-;47485:32;-1:-1:-1;47522:19:0;47544:27;47555:15;47485:32;-1:-1:-1;;;47555:15:0;:8;:15;:::i;:::-;47544:6;;:27;:10;:27;:::i;:::-;47584:4;;-1:-1:-1;47522:49:0;;-1:-1:-1;;;47245:362:0;;;:::o;42969:173::-;43051:7;43074:16;:14;:16::i;:::-;-1:-1:-1;;;;;43074:24:0;;43099:37;43126:9;43099:26;:37::i;73211:149::-;73297:7;73320:35;73336:9;73347:7;73320:15;:35::i;:::-;73313:42;73211:149;-1:-1:-1;;;73211:149:0:o;50915:230::-;51022:7;51049:16;:14;:16::i;:::-;-1:-1:-1;;;;;51049:24:0;;51080:54;51117:9;51128:5;51080:36;:54::i;49333:142::-;49392:7;49413:16;:14;:16::i;:::-;-1:-1:-1;;;;;49413:24:0;;49438:31;:29;:31::i;43564:218::-;43665:7;43692:16;:14;:16::i;:::-;-1:-1:-1;;;;;43692:24:0;;43723:48;43754:9;43765:5;43723:30;:48::i;46412:243::-;46527:7;46552:16;:14;:16::i;:::-;-1:-1:-1;;;;;46552:24:0;;46583:61;46627:9;46638:5;46583:43;:61::i;52846:190::-;52925:7;52952:16;:14;:16::i;:::-;-1:-1:-1;;;;;52952:24:0;;52983:42;:40;:42::i;27022:140::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;27105:6;;27084:40;;27121:1;;-1:-1:-1;;;;;27105:6:0;;27084:40;;27121:1;;27084:40;27135:6;:19;;-1:-1:-1;;;;;;27135:19:0;;;27022:140::o;49976:405::-;50091:16;50109:14;50130;50147:16;:14;:16::i;:::-;-1:-1:-1;;;;;50147:24:0;;50177:61;50221:9;50232:5;50177:43;:61::i;:::-;50147:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50147:96:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50147:96:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;50147:96:0;;-1:-1:-1;50248:15:0;50266:17;50147:96;-1:-1:-1;;;50266:17:0;:10;:17;:::i;:::-;50248:35;-1:-1:-1;50288:19:0;50310:30;50321:18;50248:35;-1:-1:-1;;;50321:18:0;:11;:18;:::i;50310:30::-;50355:7;;-1:-1:-1;50288:52:0;;-1:-1:-1;;;49976:405:0;;;;;;:::o;72601:92::-;72647:7;72668:20;:18;:20::i;:::-;72661:27;;72601:92;:::o;45034:156::-;45100:7;45121:16;:14;:16::i;:::-;-1:-1:-1;;;;;45121:24:0;;45146:38;:36;:38::i;42329:195::-;42411:7;42427:11;42441:37;42468:9;42441:26;:37::i;:::-;42427:51;;42490:16;:14;:16::i;:::-;-1:-1:-1;;;;;42490:24:0;;42515:3;42490:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42490:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42490:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42490:29:0;;42329:195;-1:-1:-1;;;42329:195:0:o;41229:148::-;41280:7;41294:11;41308:23;:21;:23::i;:::-;41294:37;;41343:16;:14;:16::i;:::-;-1:-1:-1;;;;;41343:24:0;;41368:3;41343:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41343:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41343:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41343:29:0;;-1:-1:-1;;41229:148:0;:::o;26211:79::-;26276:6;;-1:-1:-1;;;;;26276:6:0;26211:79;:::o;26577:94::-;26657:6;;26617:4;;-1:-1:-1;;;;;26657:6:0;26641:12;:10;:12::i;:::-;-1:-1:-1;;;;;26641:22:0;;26634:29;;26577:94;:::o;40491:100::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;40560:8;:26;;-1:-1:-1;;;;;;40560:26:0;-1:-1:-1;;;;;40560:26:0;;;;;;;;;;40491:100::o;41726:205::-;41817:7;41833:11;41847:38;41866:9;41877:7;41847:18;:38::i;:::-;41833:52;;41897:16;:14;:16::i;:::-;-1:-1:-1;;;;;41897:24:0;;41922:3;41897:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41897:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41897:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41897:29:0;;41726:205;-1:-1:-1;;;;41726:205:0:o;65627:381::-;65768:20;65790:15;65809:5;:3;:5::i;:::-;65767:47;;;;65889;65923:12;65889:33;:47::i;:::-;65941:62;65981:7;65990:12;65941:39;:62::i;:::-;65627:381;;:::o;40720:114::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;40798:8;;40783:46;;;-1:-1:-1;;;40783:46:0;;-1:-1:-1;;;;;40783:46:0;;;;;;;;;40798:8;;;;;40783:36;;:46;;;;;40798:8;;40783:46;;;;;;;40798:8;;40783:46;;;5:2:-1;;;;30:1;27;20:12;5:2;40783:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40783:46:0;;;;40720:114;:::o;62730:1263::-;62808:15;62829:16;62851:17;62881:18;62902:45;:43;:45::i;:::-;62881:66;;62952:24;62979:44;:42;:44::i;:::-;62952:71;;63028:25;63056:39;:37;:39::i;:::-;63028:67;;63100:17;63120:20;:18;:20::i;:::-;63100:40;;63217:14;63237:5;:3;:5::i;:::-;63216:26;;;63247:15;63265:17;:6;:15;:17::i;:::-;63247:35;;63479:13;63507:1;63495:9;:13;:66;;63560:1;63495:66;;;63515:38;63543:9;63515:23;:7;63527:10;63515:23;:11;:23;:::i;:::-;:27;:38;:27;:38;:::i;:::-;63479:82;;63650:20;63681:8;:6;:8::i;:::-;-1:-1:-1;;;;;63681:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63681:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63681:17:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63681:17:0;63673:70;;;-1:-1:-1;;;63673:70:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63673:39:0;;;;;;:70;;;;;63681:17;;63673:70;;;;;;;;:39;:70;;;5:2:-1;;;;30:1;27;20:12;5:2;63673:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63673:70:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63673:70:0;;-1:-1:-1;63806:20:0;63829:34;63673:70;63846:16;63829:34;:16;:34;:::i;:::-;63806:57;-1:-1:-1;63868:21:0;63892:46;63920:17;63892:23;:5;63902:12;63892:23;:9;:23;:::i;:::-;:27;:46;:27;:46;:::i;:::-;63951:7;;63960:12;;-1:-1:-1;63951:7:0;;-1:-1:-1;62730:1263:0;-1:-1:-1;;;;;;;;;62730:1263:0:o;52242:200::-;52326:7;52353:16;:14;:16::i;:::-;-1:-1:-1;;;;;52353:24:0;;52384:47;:45;:47::i;54349:257::-;54459:7;54484:16;:14;:16::i;:::-;-1:-1:-1;;;;;54484:24:0;;54515:80;54579:9;54515:56;:80::i;34120:90::-;34168:7;34197;-1:-1:-1;;;;;34197:7:0;34120:90;:::o;45630:235::-;45741:7;45766:16;:14;:16::i;:::-;-1:-1:-1;;;;;45766:24:0;;45797:57;45837:9;45848:5;45797:39;:57::i;59887:992::-;60038:18;:16;:18::i;:::-;-1:-1:-1;;;;;60038:34:0;;60073:10;60085:8;:6;:8::i;:::-;-1:-1:-1;;;;;60085:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60085:16:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60085:16:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60085:16:0;60038:64;;;-1:-1:-1;;;;;;60038:64:0;;;;;;;-1:-1:-1;;;;;60038:64:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;60038:64:0;;;;;;;;;;;5:2:-1;;;;30:1;27;20:12;5:2;60038:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60038:64:0;;;;60164:6;60174:1;60164:11;;60156:44;;;;;-1:-1:-1;;;60156:44:0;;;;;;;;;;;;-1:-1:-1;;;60156:44:0;;;;;;;;;;;;;;;60310:8;:6;:8::i;:::-;-1:-1:-1;;;;;60310:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60310:23:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60310:23:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60310:23:0;60296:59;;;-1:-1:-1;;;60296:59:0;;-1:-1:-1;;;;;60296:59:0;;;;;;;;;:48;;;;;;;:59;;;;;60310:23;;60296:59;;;;;;;:48;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;60296:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60296:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60296:59:0;60283:128;;;;-1:-1:-1;;;60283:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60593:26;;:::i;:::-;60622:62;60659:9;60674:5;60622:31;:62::i;:::-;60593:91;;60778:52;60791:4;60797:5;60804:9;60815:6;60823;60778:12;:52::i;:::-;60840:34;;;-1:-1:-1;;;;;60840:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59887:992;;;;:::o;44304:350::-;44385:15;44402:14;44425;44442:16;:14;:16::i;:::-;-1:-1:-1;;;;;44442:24:0;;44472:44;:42;:44::i;:::-;44442:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;44442:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44442:79:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44442:79:0;;-1:-1:-1;44526:14:0;44543:17;44442:79;-1:-1:-1;;;44543:17:0;:10;:17;:::i;:::-;44526:34;-1:-1:-1;44565:19:0;44587:29;44598:17;44526:34;-1:-1:-1;;;44598:17:0;:10;:17;:::i;44587:29::-;44629:6;;-1:-1:-1;44565:51:0;;-1:-1:-1;;;44304:350:0;;:::o;65000:246::-;65097:7;65116:15;65137:33;:31;:33::i;:::-;65113:57;;;;65182:59;65222:7;65231:9;65182:39;:59::i;76919:270::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;77048:28;:26;:28::i;:::-;:33;77040:67;;;;;-1:-1:-1;;;77040:67:0;;;;;;;;;;;;-1:-1:-1;;;77040:67:0;;;;;;;;;;;;;;;77150:34;77177:6;77150:26;:34::i;:::-;76919:270;:::o;27317:109::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;27390:28;27409:8;27390:18;:28::i;40998:65::-;-1:-1:-1;;;40998:65:0;:::o;61027:654::-;61184:40;61193:9;61204:10;61216:7;61184:8;:40::i;:::-;61171:92;;;;;-1:-1:-1;;;61171:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61319:26;;:::i;:::-;61348:28;61366:9;61348:17;:28::i;:::-;61319:57;-1:-1:-1;61449:12:0;;61445:80;;61469:50;;;-1:-1:-1;;;61469:50:0;;61499:10;61469:50;;;;;;;;;;;;-1:-1:-1;;;;;61469:29:0;;;;;:50;;;;;-1:-1:-1;;61469:50:0;;;;;;;-1:-1:-1;61469:29:0;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;61469:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61469:50:0;;;;61445:80;61617:59;61630:5;61637:10;61649:9;61660:7;61669:6;61617:12;:59::i;:::-;61027:654;;;:::o;70020:235::-;70130:7;70145:14;70165:67;70207:9;70222:5;70165:36;:67::i;:::-;-1:-1:-1;70144:88:0;70020:235;-1:-1:-1;;;;70020:235:0:o;40178:177::-;26423:9;:7;:9::i;:::-;26415:54;;;;;-1:-1:-1;;;26415:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;26415:54:0;;;;;;;;;;;;;;;40235:8;;-1:-1:-1;;;;;40235:8:0;:22;40227:49;;;;;-1:-1:-1;;;40227:49:0;;;;;;;;;;;;-1:-1:-1;;;40227:49:0;;;;;;;;;;;;;;;40281:18;40302:20;;;;;:::i;:::-;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;40327:8:0;:23;;-1:-1:-1;;;;;;40327:23:0;-1:-1:-1;;;;;40327:23:0;;;;;;;;;;-1:-1:-1;40178:177:0:o;74305:139::-;74382:7;74405:34;74429:9;74405:23;:34::i;53788:262::-;53903:7;54023:9;53944:95;;;;;;;;;;;;;-1:-1:-1;;;;;53944:95:0;-1:-1:-1;;;;;53944:95:0;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;53944:95:0;;;53928:117;;;;;;53917:128;;53788:262;;;:::o;51819:186::-;51908:7;51945:54;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;51945:54:0;;;51935:65;;;;;;51924:76;;51819:186;:::o;48936:230::-;49091:64;;;;;;;;;;;;-1:-1:-1;;;;;;49091:64:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;49091:64:0;;;;;;;49075:86;;;;;48936:230;;;;:::o;48254:182::-;48379:51;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;48379:51:0;;;;;;;26:21:-1;;;22:32;;6:49;;48379:51:0;;;;;;;48369:62;;;;;;48254:182::o;47612:211::-;47754:58;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;47754:58:0;;;;;;;26:21:-1;;;22:32;;6:49;;47754:58:0;;;;;;;47738:80;;;;;;47612:211::o;7300:132::-;7358:7;7385:39;7389:1;7392;7385:39;;;;;;;;;;;;;;;;;:3;:39::i;6361:471::-;6419:7;6664:6;6660:47;;-1:-1:-1;6694:1:0;6687:8;;6660:47;6731:5;;;6735:1;6731;:5;:1;6755:5;;;;;:10;6747:56;;;;-1:-1:-1;;;6747:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5445:136;5503:7;5530:43;5534:1;5537;5530:43;;;;;;;;;;;;;;;;;:3;:43::i;43147:171::-;43266:46;;;-1:-1:-1;;;43266:46:0;;;;;;;;;;;;;-1:-1:-1;;;;;;43266:46:0;;;;;;;26:21:-1;;;22:32;;6:49;;43266:46:0;;;;;;;43256:57;;;;;;43147:171::o;51150:226::-;51303:62;;;;;;;;;;;;-1:-1:-1;;;;;;51303:62:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;51303:62:0;;;;51287:84;;;;;;51150:226::o;49480:137::-;49574:37;;;-1:-1:-1;;;49574:37:0;;;;;;;;;;26:21:-1;;;49574:37:0;22:32:-1;6:49;;49574:37:0;;;;;;;49564:48;;;;;49480:137;:::o;43787:219::-;43935:60;;;-1:-1:-1;;;43935:60:0;;;;;;;;-1:-1:-1;;;;;;43935:60:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;43935:60:0;;;;;;;43919:82;;;;;43787:219;;;;:::o;46660:265::-;46820:94;;;;;;;;;;;;-1:-1:-1;;;;;;46820:94:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;46820:94:0;;;;;;;46804:116;;;;;46660:265;;;;:::o;53041:170::-;53157:48;;;;;;;;;;;;;;26:21:-1;;;53157:48:0;22:32:-1;6:49;;53157:48:0;;;;;;;53147:59;;;;;53041:170;:::o;50386:265::-;50546:94;;;;;;;;;;;;-1:-1:-1;;;;;;50546:94:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;50546:94:0;;;;;;;50530:116;;;;;50386:265;;;;:::o;45195:162::-;45307:44;;;;;;;;;;;;;;26:21:-1;;;45307:44:0;22:32:-1;6:49;;45307:44:0;;;;;;;45297:55;;;;;45195:162;:::o;42529:170::-;42648:45;;;-1:-1:-1;;;42648:45:0;;;;;;;;;;;;;-1:-1:-1;;;;;;42648:45:0;;;;;;;26:21:-1;;;22:32;;6:49;;42648:45:0;;;;;;;42638:56;;;;;;42529:170::o;41382:121::-;41468:29;;;-1:-1:-1;;;41468:29:0;;;;;;;;;;26:21:-1;;;41468:29:0;22:32:-1;6:49;;41468:29:0;;;;;;;41458:40;;;;;41382:121;:::o;858:98::-;938:10;858:98;:::o;41936:180::-;42064:46;;;-1:-1:-1;;;42064:46:0;;;;;;;;-1:-1:-1;;;;;;42064:46:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;42064:46:0;;;;;;;42054:57;;;;;41936:180;;;;:::o;66189:1458::-;66235:20;66257:15;66364:21;66399:8;:6;:8::i;:::-;-1:-1:-1;;;;;66399:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66399:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66399:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66399:20:0;66388:67;;;-1:-1:-1;;;66388:67:0;;;;-1:-1:-1;;;;;66388:65:0;;;;;;:67;;;;;66399:20;;66388:67;;;;;;;;:65;:67;;;5:2:-1;;;;30:1;27;20:12;5:2;66388:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66388:67:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66388:67:0;;-1:-1:-1;66609:18:0;;66658:41;:39;:41::i;:::-;66603:96;;;;66924:22;66963:13;66949:10;:27;:64;;67003:10;66949:64;;;66983:13;66949:64;66924:89;;67134:14;67163:1;67151:9;:13;:47;;67197:1;67151:47;;;67167:27;:12;67184:9;67167:27;:16;:27;:::i;:::-;67134:64;-1:-1:-1;67328:25:0;67356:26;:14;67134:64;67356:26;:18;:26;:::i;:::-;67328:54;;67387:19;67409:67;67454:17;67409:35;:33;:35::i;:67::-;67387:89;-1:-1:-1;67628:13:0;;-1:-1:-1;;;;;;;66189:1458:0;;:::o;44866:163::-;44939:16;:14;:16::i;:::-;-1:-1:-1;;;;;44939:24:0;;44969:38;:36;:38::i;:::-;45013:6;44939:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;44045:254:0;44151:14;44168:30;44191:6;44168:18;:7;-1:-1:-1;;;44168:18:0;:11;:18;:::i;:30::-;44151:47;;44203:16;:14;:16::i;:::-;-1:-1:-1;;;;;44203:24:0;;44233:44;:42;:44::i;:::-;44283:6;44203:91;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;44203:91:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44203:91:0;;;;44045:254;;;:::o;21463:97::-;21516:7;21537:18;:2;20958:19;21537:18;:6;:18;:::i;4989:181::-;5047:7;5079:5;;;5103:6;;;;5095:46;;;;;-1:-1:-1;;;5095:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;52447:180;52535:7;52568:53;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;52568:53:0;;;52558:64;;;;;;52551:71;;52447:180;:::o;54611:260::-;54725:7;54844:9;54766:94;;;;;;;;;;;;;-1:-1:-1;;;;;54766:94:0;-1:-1:-1;;;;;54766:94:0;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;54766:94:0;;;54750:116;;;;;;54739:127;;54611:260;;;:::o;45870:257::-;46026:90;;;;;;;;;;;;-1:-1:-1;;;;;;46026:90:0;;;;;;;;;;;;;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;46026:90:0;;;;;;;46010:112;;;;;45870:257;;;;:::o;24396:96::-;24477:10;;-1:-1:-1;;;;;24477:10:0;24396:96;:::o;75076:668::-;75174:27;;:::i;:::-;75267:26;75299;;:::i;:::-;75333:54;75370:9;75381:5;75333:36;:54::i;:::-;75261:126;;;;75471:90;75512:9;75527:5;75538:18;75471:35;:90::i;:::-;75661:58;75702:9;75713:5;75661:40;:58::i;:::-;75733:6;75076:668;-1:-1:-1;;;;75076:668:0:o;71393:1136::-;71545:49;71565:9;71576:8;71586:7;71545:19;:49::i;:::-;71641:9;71637:774;;;71739:19;71751:6;71739:11;:19::i;:::-;71841:35;71858:9;71869:6;71841:16;:35::i;:::-;71966:37;71975:9;71986:8;71996:6;71966:8;:37::i;:::-;71637:774;;;72148:19;72160:6;72148:11;:19::i;:::-;72250:35;72267:9;72278:6;72250:16;:35::i;:::-;72368:37;72377:9;72388:8;72398:6;72368:8;:37::i;:::-;72516:8;:6;:8::i;44659:174::-;44777:50;;;;;;;;;;;;;;26:21:-1;;;44777:50:0;22:32:-1;6:49;;44777:50:0;;;;;;;44767:61;;;;;44659:174;:::o;64164:752::-;64281:7;64296:22;64320:18;64348:65;64403:9;64348:54;:65::i;:::-;64419:64;64473:9;64419:53;:64::i;:::-;64295:193;;;;64595:31;64629:72;64662:34;64686:9;64662:23;:34::i;:::-;64629:23;:7;64641:10;64629:23;:11;:23;:::i;:::-;:27;:72;:27;:72;:::i;:::-;64595:106;-1:-1:-1;64868:43:0;:14;64595:106;64868:43;:18;:43;:::i;:::-;64861:50;64164:752;-1:-1:-1;;;;;;64164:752:0:o;49192:136::-;49258:16;:14;:16::i;:::-;-1:-1:-1;;;;;49258:24:0;;49283:31;:29;:31::i;27532:229::-;-1:-1:-1;;;;;27606:22:0;;27598:73;;;;-1:-1:-1;;;27598:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27708:6;;27687:38;;-1:-1:-1;;;;;27687:38:0;;;;27708:6;;27687:38;;27708:6;;27687:38;27736:6;:17;;-1:-1:-1;;;;;;27736:17:0;-1:-1:-1;;;;;27736:17:0;;;;;;;;;;27532:229::o;74038:201::-;74144:4;74155:13;74171:35;74187:9;74198:7;74171:15;:35::i;:::-;-1:-1:-1;;;74218:16:0;;74038:201;-1:-1:-1;;;;74038:201:0:o;70318:997::-;70387:27;;:::i;:::-;70479:13;70498:26;;:::i;:::-;70532:59;70569:9;70580:10;70532:36;:59::i;:::-;70473:118;;;;70659:61;70695:9;70706:10;70718:1;70659:35;:61::i;:::-;70777:19;70813:8;:6;:8::i;:::-;-1:-1:-1;;;;;70813:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;70813:16:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;70813:16:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70813:16:0;70979:15;;;;70813:16;;-1:-1:-1;70909:90:0;;70948:9;;70963:10;;70909:33;:90::i;:::-;71004:63;71045:9;71056:10;71004:40;:63::i;:::-;71120:29;;;-1:-1:-1;;;71120:29:0;;71131:10;71120:29;;;;;;;;;;;;-1:-1:-1;;;;;71120:10:0;;;;;:29;;;;;;;;;;;;;;-1:-1:-1;71120:10:0;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;71120:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;71120:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71120:29:0;71112:57;;;;;-1:-1:-1;;;71112:57:0;;;;;;;;;;;;-1:-1:-1;;;71112:57:0;;;;;;;;;;;;;;;71282:8;:6;:8::i;:::-;-1:-1:-1;71304:6:0;70318:997;-1:-1:-1;;;70318:997:0:o;68843:1049::-;68955:15;68972:27;;:::i;:::-;69113:8;:6;:8::i;:::-;-1:-1:-1;;;;;69113:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;69113:23:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;69113:23:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;69113:23:0;69099:59;;;-1:-1:-1;;;69099:59:0;;-1:-1:-1;;;;;69099:59:0;;;;;;;;;:48;;;;;;;:59;;;;;69113:23;;69099:59;;;;;;;:48;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;69099:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;69099:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;69099:59:0;69090:128;;-1:-1:-1;;69190:21:0;;;;;;;;69187:1;69190:21;;;;;;;;;;;;;;;69179:33;;69090:128;69296:15;69314:53;69350:9;69361:5;69314:35;:53::i;:::-;69296:71;;69433:14;69450:52;69485:9;69496:5;69450:34;:52::i;:::-;69433:69;;69577:14;69603:26;;:::i;:::-;69637:42;69662:9;69673:5;69637:24;:42::i;:::-;69571:108;;;;;69737:26;69766:81;69840:6;69766:24;69782:7;69766:6;:15;;:24;;;;:::i;:81::-;69737:110;69880:6;;-1:-1:-1;68843:1049:0;;-1:-1:-1;;;;;;;68843:1049:0:o;7962:345::-;8048:7;8150:12;8143:5;8135:28;;;;-1:-1:-1;;;8135:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;8135:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8174:9;8190:1;8186;:5;;;;;;;7962:345;-1:-1:-1;;;;;7962:345:0:o;5918:192::-;6004:7;6040:12;6032:6;;;;6024:29;;;;-1:-1:-1;;;6024:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6024:29:0;-1:-1:-1;;;6076:5:0;;;5918:192::o;48463:230::-;48585:16;:14;:16::i;:::-;-1:-1:-1;;;;;48585:24:0;;48615:56;48654:9;48665:5;48615:38;:56::i;76529:314::-;76636:21;76660:34;76684:9;76660:23;:34::i;:::-;76636:58;;76752:13;76703:45;76731:9;76742:5;76703:27;:45::i;:::-;:62;76699:140;;76773:60;76801:9;76812:5;76819:13;76773:27;:60::i;61739:811::-;61940:22;61965:80;62010:7;:15;;;62031:9;61965:39;:80::i;:::-;61940:105;;62090:69;62124:9;62135:5;62142:7;:16;;;62090:33;:69::i;:::-;62208:14;;62164:59;;:43;:59::i;:::-;62228;62271:7;:15;;;62228:42;:59::i;:::-;62292:55;62330:7;:16;;;62292:37;:55::i;:::-;62352:94;62412:9;62427:14;62352:54;:94::i;:::-;62451;62510:9;62525:7;:15;;;62451:53;:94::i;:::-;61739:811;;;;:::o;72762:151::-;72812:13;72828:20;:18;:20::i;:::-;72812:36;-1:-1:-1;72861:17:0;72812:36;72871:6;72861:17;:9;:17;:::i;:::-;72853:25;;72883;72902:5;72883:18;:25::i;74507:205::-;74581:13;74597:34;74621:9;74597:23;:34::i;:::-;74581:50;-1:-1:-1;74644:17:0;74581:50;74654:6;74644:17;:9;:17;:::i;:::-;74636:25;;74666:41;74690:9;74701:5;74666:23;:41::i;73430:229::-;73526:13;73542:35;73558:9;73569:7;73542:15;:35::i;:::-;73526:51;-1:-1:-1;73590:17:0;73526:51;73600:6;73590:17;:9;:17;:::i;:::-;73582:25;;73612:42;73628:9;73639:7;73648:5;73612:15;:42::i;72987:151::-;73037:13;73053:20;:18;:20::i;:::-;73037:36;-1:-1:-1;73086:17:0;73037:36;73096:6;73086:17;:9;:17;:::i;74780:221::-;74854:13;74870:34;74894:9;74870:23;:34::i;:::-;74854:50;-1:-1:-1;74909:17:0;74929;74854:50;74939:6;74929:17;:9;:17;:::i;:::-;74909:37;;74951:45;74975:9;74986;74951:23;:45::i;73734:229::-;73830:13;73846:35;73862:9;73873:7;73846:15;:35::i;:::-;73830:51;-1:-1:-1;73894:17:0;73830:51;73904:6;73894:17;:9;:17;:::i;50684:226::-;50804:16;:14;:16::i;:::-;-1:-1:-1;;;;;50804:24:0;;50834:54;50871:9;50882:5;50834:36;:54::i;76018:423::-;76128:7;76142:13;76158:45;76186:9;76197:5;76158:27;:45::i;:::-;76142:61;;76208:13;76224:34;76248:9;76224:23;:34::i;:::-;76208:50;-1:-1:-1;76263:16:0;76282;76208:50;76292:5;76282:16;:9;:16;:::i;:::-;76263:35;;76303:21;76327:33;76343:9;76354:5;76327:15;:33::i;:::-;76303:57;-1:-1:-1;76365:13:0;76381:27;:8;76303:57;76381:27;:12;:27;:::i;:::-;76365:43;;76420:16;:5;:14;:16::i;:::-;76413:23;76018:423;-1:-1:-1;;;;;;;;76018:423:0:o;67708:1012::-;67812:15;67833:22;67861:27;;:::i;:::-;67974:26;68003:33;68019:9;68030:5;68003:15;:33::i;:::-;67974:62;;68146:20;68169:64;68208:9;68223:5;68169:33;:64::i;:::-;68146:87;;68320:14;68340:15;68361:16;68385:33;:31;:33::i;:::-;68314:104;;;;;;68527:14;68556:12;68544:8;:24;;:100;;68643:1;68544:100;;;68575:61;:50;68606:18;68575:26;:8;68588:12;68575:26;:12;:26;:::i;:50::-;:59;:61::i;:::-;68675:39;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68527:117:0;;-1:-1:-1;68665:8:0;-1:-1:-1;68675:39:0;-1:-1:-1;;;67708:1012:0;;;;;:::o;43345:214::-;43459:16;:14;:16::i;:::-;-1:-1:-1;;;;;43459:24:0;;43489:48;43520:9;43531:5;43489:30;:48::i;51419:188::-;51507:16;:14;:16::i;:::-;-1:-1:-1;;;;;51507:24:0;;51537:48;:46;:48::i;52047:190::-;52136:16;:14;:16::i;:::-;-1:-1:-1;;;;;52136:24:0;;52166:47;:45;:47::i;52664:177::-;52744:16;:14;:16::i;:::-;-1:-1:-1;;;;;52744:24:0;;52774:42;:40;:42::i;53265:254::-;53388:16;:14;:16::i;:::-;-1:-1:-1;;;;;53388:24:0;;53418:79;53482:9;53418:57;:79::i;:::-;53503:6;53388:126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53388:126:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53388:126:0;;;;53265:254;;:::o;54103:241::-;54225:16;:14;:16::i;:::-;-1:-1:-1;;;;;54225:24:0;;54255:67;54312:9;54255:56;:67::i;41082:142::-;41140:11;41154:23;:21;:23::i;:::-;41140:37;;41182:16;:14;:16::i;:::-;-1:-1:-1;;;;;41182:24:0;;41207:3;41212:6;41182:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;42139:185:0;42226:11;42240:37;42267:9;42240:26;:37::i;:::-;42226:51;;42282:16;:14;:16::i;:::-;-1:-1:-1;;;;;42282:24:0;;42307:3;42312:6;42282:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;41518:203:0;41622:11;41636:38;41655:9;41666:7;41636:18;:38::i;:::-;41622:52;;41679:16;:14;:16::i;:::-;-1:-1:-1;;;;;41679:24:0;;41704:3;41709:6;41679:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41679:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41679:37:0;;;;41518:203;;;;:::o;21671:97::-;21724:7;21745:18;:2;20958:19;21745:18;:6;:18;:::i;59326:17866::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::o

Swarm Source

bzzr://3f56f68666d8539eb2b32e34ee2367d8fa1c02fcfd94cf25d12f11de94b1dfc4

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.