ETH Price: $2,548.55 (+1.10%)

Contract

0xc0b19570370478EDE5F2e922c5D31FAf1D5f90EA
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Settle Expired206197822024-08-27 12:00:1124 days ago1724760011IN
0xc0b19570...f1D5f90EA
0 ETH0.000199221.53654172
Settle Expired206197802024-08-27 11:59:4724 days ago1724759987IN
0xc0b19570...f1D5f90EA
0 ETH0.00027461.61556998
Settle Expired176757072023-07-12 6:28:47436 days ago1689143327IN
0xc0b19570...f1D5f90EA
0 ETH0.0028183716.78616309
Settle Expired143645802022-03-11 8:51:15924 days ago1646988675IN
0xc0b19570...f1D5f90EA
0 ETH0.0024246715
Settle Expired140742632022-01-25 10:37:10969 days ago1643107030IN
0xc0b19570...f1D5f90EA
0 ETH0.0116107768.30953083
Settle Expired130700942021-08-21 17:49:511126 days ago1629568191IN
0xc0b19570...f1D5f90EA
0 ETH0.0038801425.159946
Settle Expired129260432021-07-30 8:59:261148 days ago1627635566IN
0xc0b19570...f1D5f90EA
0 ETH0.0051354642
Settle Expired120637862021-03-18 16:35:171282 days ago1616085317IN
0xc0b19570...f1D5f90EA
0 ETH0.02287803169
Settle Expired120311802021-03-13 15:58:021287 days ago1615651082IN
0xc0b19570...f1D5f90EA
0 ETH0.0235549174
Settle Expired120309542021-03-13 15:09:421287 days ago1615648182IN
0xc0b19570...f1D5f90EA
0 ETH0.0177792150.00000145
Settle Expired119374062021-02-27 5:14:051301 days ago1614402845IN
0xc0b19570...f1D5f90EA
0 ETH0.009372480
Settle Expired119367352021-02-27 2:44:491302 days ago1614393889IN
0xc0b19570...f1D5f90EA
0 ETH0.0113872986.50000072
Settle Expired117363682021-01-27 7:06:311332 days ago1611731191IN
0xc0b19570...f1D5f90EA
0 ETH0.0074455155
Settle Expired116749492021-01-17 20:43:141342 days ago1610916194IN
0xc0b19570...f1D5f90EA
0 ETH0.005265840
Settle Expired116748022021-01-17 20:12:431342 days ago1610914363IN
0xc0b19570...f1D5f90EA
0 ETH0.0076354158
Settle Expired116677642021-01-16 18:09:581343 days ago1610820598IN
0xc0b19570...f1D5f90EA
0 ETH0.008798760
Settle Expired116616452021-01-15 19:32:021344 days ago1610739122IN
0xc0b19570...f1D5f90EA
0 ETH0.0079446166
Settle Expired116152892021-01-08 16:54:591351 days ago1610124899IN
0xc0b19570...f1D5f90EA
0 ETH0.0080303461
Settle Expired115940392021-01-05 10:40:281354 days ago1609843228IN
0xc0b19570...f1D5f90EA
0 ETH0.0112916677
Settle Expired115603122020-12-31 6:38:541359 days ago1609396734IN
0xc0b19570...f1D5f90EA
0 ETH0.0089781868.2
Settle Expired114827412020-12-19 9:10:541371 days ago1608369054IN
0xc0b19570...f1D5f90EA
0 ETH0.0045459931
Settle Expired114198862020-12-09 16:53:451381 days ago1607532825IN
0xc0b19570...f1D5f90EA
0 ETH0.0048734236
Settle Expired113988932020-12-06 11:29:281384 days ago1607254168IN
0xc0b19570...f1D5f90EA
0 ETH0.0020318519.8
Settle Expired113988932020-12-06 11:29:281384 days ago1607254168IN
0xc0b19570...f1D5f90EA
0 ETH0.0026803819.8
Settle Expired113739842020-12-02 15:48:181388 days ago1606924098IN
0xc0b19570...f1D5f90EA
0 ETH0.0051325735
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
107998292020-09-05 6:46:041476 days ago1599288364  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x39450EB4...32cFB8759
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
ExpiringMultiParty

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

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

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

pragma solidity ^0.6.0;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // 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.
     */
    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/IERC20.sol

pragma solidity ^0.6.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.6.2;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

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

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

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

pragma solidity ^0.6.0;




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

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

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

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

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

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

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

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

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

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

// File: contracts/common/implementation/FixedPoint.sol

pragma solidity ^0.6.0;



/**
 * @title Library for fixed point arithmetic on uints
 */
library FixedPoint {
    using SafeMath for uint256;

    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // Can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.
    uint256 private constant FP_SCALING_FACTOR = 10**18;

    struct Unsigned {
        uint256 rawValue;
    }

    /**
     * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5**18`.
     * @param a uint to convert into a FixedPoint.
     * @return the converted FixedPoint.
     */
    function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {
        return Unsigned(a.mul(FP_SCALING_FACTOR));
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue == fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue == b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue > fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue >= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue < fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue <= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue <= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue <= b.rawValue;
    }

    /**
     * @notice The minimum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the minimum of `a` and `b`.
     */
    function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue < b.rawValue ? a : b;
    }

    /**
     * @notice The maximum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the maximum of `a` and `b`.
     */
    function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue > b.rawValue ? a : b;
    }

    /**
     * @notice Adds two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.add(b.rawValue));
    }

    /**
     * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return add(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.sub(b.rawValue));
    }

    /**
     * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return sub(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return sub(fromUnscaledUint(a), b);
    }

    /**
     * @notice Multiplies two `Unsigned`s, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
        // stored internally as a uint256 ~10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
        // would round to 3, but this computation produces the result 2.
        // No need to use SafeMath because FP_SCALING_FACTOR != 0.
        return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Multiplies two `Unsigned`s and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 mulRaw = a.rawValue.mul(b.rawValue);
        uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;
        uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);
        if (mod != 0) {
            return Unsigned(mulFloor.add(1));
        } else {
            return Unsigned(mulFloor);
        }
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256 and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Since b is an int, there is no risk of truncation and we can just mul it normally
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
        // 10^41 is stored internally as a uint256 10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
        // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
        return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.div(b));
    }

    /**
     * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a uint256 numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return div(fromUnscaledUint(a), b);
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned` and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);
        uint256 divFloor = aScaled.div(b.rawValue);
        uint256 mod = aScaled.mod(b.rawValue);
        if (mod != 0) {
            return Unsigned(divFloor.add(1));
        } else {
            return Unsigned(divFloor);
        }
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256 and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Because it is possible that a quotient gets truncated, we can't just call "Unsigned(a.rawValue.div(b))"
        // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.
        // This creates the possibility of overflow if b is very large.
        return divCeil(a, fromUnscaledUint(b));
    }

    /**
     * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
     * @dev This will "floor" the result.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return output is `a` to the power of `b`.
     */
    function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {
        output = fromUnscaledUint(1);
        for (uint256 i = 0; i < b; i = i.add(1)) {
            output = mul(output, a);
        }
    }
}

// File: contracts/common/interfaces/ExpandedIERC20.sol

pragma solidity ^0.6.0;



/**
 * @title ERC20 interface that includes burn and mint methods.
 */
abstract contract ExpandedIERC20 is IERC20 {
    /**
     * @notice Burns a specific amount of the caller's tokens.
     * @dev Only burns the caller's tokens, so it is safe to leave this method permissionless.
     */
    function burn(uint256 value) external virtual;

    /**
     * @notice Mints tokens and adds them to the balance of the `to` address.
     * @dev This method should be permissioned to only allow designated parties to mint tokens.
     */
    function mint(address to, uint256 value) external virtual returns (bool);
}

// File: contracts/oracle/interfaces/OracleInterface.sol

pragma solidity ^0.6.0;


/**
 * @title Financial contract facing Oracle interface.
 * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
 */
interface OracleInterface {
    /**
     * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     */
    function requestPrice(bytes32 identifier, uint256 time) external;

    /**
     * @notice Whether the price for `identifier` and `time` is available.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
     */
    function hasPrice(bytes32 identifier, uint256 time) external view returns (bool);

    /**
     * @notice Gets the price for `identifier` and `time` if it has already been requested and resolved.
     * @dev If the price is not available, the method reverts.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     * @return int256 representing the resolved price for the given identifier and timestamp.
     */
    function getPrice(bytes32 identifier, uint256 time) external view returns (int256);
}

// File: contracts/oracle/interfaces/IdentifierWhitelistInterface.sol

pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;


/**
 * @title Interface for whitelists of supported identifiers that the oracle can provide prices for.
 */
interface IdentifierWhitelistInterface {
    /**
     * @notice Adds the provided identifier as a supported identifier.
     * @dev Price requests using this identifier will succeed after this call.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     */
    function addSupportedIdentifier(bytes32 identifier) external;

    /**
     * @notice Removes the identifier from the whitelist.
     * @dev Price requests using this identifier will no longer succeed after this call.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     */
    function removeSupportedIdentifier(bytes32 identifier) external;

    /**
     * @notice Checks whether an identifier is on the whitelist.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     * @return bool if the identifier is supported (or not).
     */
    function isIdentifierSupported(bytes32 identifier) external view returns (bool);
}

// File: contracts/oracle/interfaces/AdministrateeInterface.sol

pragma solidity ^0.6.0;


/**
 * @title Interface that all financial contracts expose to the admin.
 */
interface AdministrateeInterface {
    /**
     * @notice Initiates the shutdown process, in case of an emergency.
     */
    function emergencyShutdown() external;

    /**
     * @notice A core contract method called independently or as a part of other financial contract transactions.
     * @dev It pays fees and moves money between margin accounts to make sure they reflect the NAV of the contract.
     */
    function remargin() external;
}

// File: contracts/oracle/implementation/Constants.sol

pragma solidity ^0.6.0;


/**
 * @title Stores common interface names used throughout the DVM by registration in the Finder.
 */
library OracleInterfaces {
    bytes32 public constant Oracle = "Oracle";
    bytes32 public constant IdentifierWhitelist = "IdentifierWhitelist";
    bytes32 public constant Store = "Store";
    bytes32 public constant FinancialContractsAdmin = "FinancialContractsAdmin";
    bytes32 public constant Registry = "Registry";
    bytes32 public constant CollateralWhitelist = "CollateralWhitelist";
}

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

pragma solidity ^0.6.0;

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

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

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

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

pragma solidity ^0.6.0;





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

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(sender, recipient, amount);

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

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

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

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

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

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

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

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

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

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

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

// File: contracts/common/implementation/MultiRole.sol

pragma solidity ^0.6.0;


library Exclusive {
    struct RoleMembership {
        address member;
    }

    function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
        return roleMembership.member == memberToCheck;
    }

    function resetMember(RoleMembership storage roleMembership, address newMember) internal {
        require(newMember != address(0x0), "Cannot set an exclusive role to 0x0");
        roleMembership.member = newMember;
    }

    function getMember(RoleMembership storage roleMembership) internal view returns (address) {
        return roleMembership.member;
    }

    function init(RoleMembership storage roleMembership, address initialMember) internal {
        resetMember(roleMembership, initialMember);
    }
}


library Shared {
    struct RoleMembership {
        mapping(address => bool) members;
    }

    function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
        return roleMembership.members[memberToCheck];
    }

    function addMember(RoleMembership storage roleMembership, address memberToAdd) internal {
        require(memberToAdd != address(0x0), "Cannot add 0x0 to a shared role");
        roleMembership.members[memberToAdd] = true;
    }

    function removeMember(RoleMembership storage roleMembership, address memberToRemove) internal {
        roleMembership.members[memberToRemove] = false;
    }

    function init(RoleMembership storage roleMembership, address[] memory initialMembers) internal {
        for (uint256 i = 0; i < initialMembers.length; i++) {
            addMember(roleMembership, initialMembers[i]);
        }
    }
}


/**
 * @title Base class to manage permissions for the derived class.
 */
abstract contract MultiRole {
    using Exclusive for Exclusive.RoleMembership;
    using Shared for Shared.RoleMembership;

    enum RoleType { Invalid, Exclusive, Shared }

    struct Role {
        uint256 managingRole;
        RoleType roleType;
        Exclusive.RoleMembership exclusiveRoleMembership;
        Shared.RoleMembership sharedRoleMembership;
    }

    mapping(uint256 => Role) private roles;

    event ResetExclusiveMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
    event AddedSharedMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
    event RemovedSharedMember(uint256 indexed roleId, address indexed oldMember, address indexed manager);

    /**
     * @notice Reverts unless the caller is a member of the specified roleId.
     */
    modifier onlyRoleHolder(uint256 roleId) {
        require(holdsRole(roleId, msg.sender), "Sender does not hold required role");
        _;
    }

    /**
     * @notice Reverts unless the caller is a member of the manager role for the specified roleId.
     */
    modifier onlyRoleManager(uint256 roleId) {
        require(holdsRole(roles[roleId].managingRole, msg.sender), "Can only be called by a role manager");
        _;
    }

    /**
     * @notice Reverts unless the roleId represents an initialized, exclusive roleId.
     */
    modifier onlyExclusive(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Exclusive, "Must be called on an initialized Exclusive role");
        _;
    }

    /**
     * @notice Reverts unless the roleId represents an initialized, shared roleId.
     */
    modifier onlyShared(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Shared, "Must be called on an initialized Shared role");
        _;
    }

    /**
     * @notice Whether `memberToCheck` is a member of roleId.
     * @dev Reverts if roleId does not correspond to an initialized role.
     * @param roleId the Role to check.
     * @param memberToCheck the address to check.
     * @return True if `memberToCheck` is a member of `roleId`.
     */
    function holdsRole(uint256 roleId, address memberToCheck) public view returns (bool) {
        Role storage role = roles[roleId];
        if (role.roleType == RoleType.Exclusive) {
            return role.exclusiveRoleMembership.isMember(memberToCheck);
        } else if (role.roleType == RoleType.Shared) {
            return role.sharedRoleMembership.isMember(memberToCheck);
        }
        revert("Invalid roleId");
    }

    /**
     * @notice Changes the exclusive role holder of `roleId` to `newMember`.
     * @dev Reverts if the caller is not a member of the managing role for `roleId` or if `roleId` is not an
     * initialized, ExclusiveRole.
     * @param roleId the ExclusiveRole membership to modify.
     * @param newMember the new ExclusiveRole member.
     */
    function resetMember(uint256 roleId, address newMember) public onlyExclusive(roleId) onlyRoleManager(roleId) {
        roles[roleId].exclusiveRoleMembership.resetMember(newMember);
        emit ResetExclusiveMember(roleId, newMember, msg.sender);
    }

    /**
     * @notice Gets the current holder of the exclusive role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, exclusive role.
     * @param roleId the ExclusiveRole membership to check.
     * @return the address of the current ExclusiveRole member.
     */
    function getMember(uint256 roleId) public view onlyExclusive(roleId) returns (address) {
        return roles[roleId].exclusiveRoleMembership.getMember();
    }

    /**
     * @notice Adds `newMember` to the shared role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
     * managing role for `roleId`.
     * @param roleId the SharedRole membership to modify.
     * @param newMember the new SharedRole member.
     */
    function addMember(uint256 roleId, address newMember) public onlyShared(roleId) onlyRoleManager(roleId) {
        roles[roleId].sharedRoleMembership.addMember(newMember);
        emit AddedSharedMember(roleId, newMember, msg.sender);
    }

    /**
     * @notice Removes `memberToRemove` from the shared role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
     * managing role for `roleId`.
     * @param roleId the SharedRole membership to modify.
     * @param memberToRemove the current SharedRole member to remove.
     */
    function removeMember(uint256 roleId, address memberToRemove) public onlyShared(roleId) onlyRoleManager(roleId) {
        roles[roleId].sharedRoleMembership.removeMember(memberToRemove);
        emit RemovedSharedMember(roleId, memberToRemove, msg.sender);
    }

    /**
     * @notice Removes caller from the role, `roleId`.
     * @dev Reverts if the caller is not a member of the role for `roleId` or if `roleId` is not an
     * initialized, SharedRole.
     * @param roleId the SharedRole membership to modify.
     */
    function renounceMembership(uint256 roleId) public onlyShared(roleId) onlyRoleHolder(roleId) {
        roles[roleId].sharedRoleMembership.removeMember(msg.sender);
        emit RemovedSharedMember(roleId, msg.sender, msg.sender);
    }

    /**
     * @notice Reverts if `roleId` is not initialized.
     */
    modifier onlyValidRole(uint256 roleId) {
        require(roles[roleId].roleType != RoleType.Invalid, "Attempted to use an invalid roleId");
        _;
    }

    /**
     * @notice Reverts if `roleId` is initialized.
     */
    modifier onlyInvalidRole(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Invalid, "Cannot use a pre-existing role");
        _;
    }

    /**
     * @notice Internal method to initialize a shared role, `roleId`, which will be managed by `managingRoleId`.
     * `initialMembers` will be immediately added to the role.
     * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
     * initialized.
     */
    function _createSharedRole(
        uint256 roleId,
        uint256 managingRoleId,
        address[] memory initialMembers
    ) internal onlyInvalidRole(roleId) {
        Role storage role = roles[roleId];
        role.roleType = RoleType.Shared;
        role.managingRole = managingRoleId;
        role.sharedRoleMembership.init(initialMembers);
        require(
            roles[managingRoleId].roleType != RoleType.Invalid,
            "Attempted to use an invalid role to manage a shared role"
        );
    }

    /**
     * @notice Internal method to initialize an exclusive role, `roleId`, which will be managed by `managingRoleId`.
     * `initialMember` will be immediately added to the role.
     * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
     * initialized.
     */
    function _createExclusiveRole(
        uint256 roleId,
        uint256 managingRoleId,
        address initialMember
    ) internal onlyInvalidRole(roleId) {
        Role storage role = roles[roleId];
        role.roleType = RoleType.Exclusive;
        role.managingRole = managingRoleId;
        role.exclusiveRoleMembership.init(initialMember);
        require(
            roles[managingRoleId].roleType != RoleType.Invalid,
            "Attempted to use an invalid role to manage an exclusive role"
        );
    }
}

// File: contracts/common/implementation/ExpandedERC20.sol

pragma solidity ^0.6.0;





/**
 * @title An ERC20 with permissioned burning and minting. The contract deployer will initially
 * be the owner who is capable of adding new roles.
 */
contract ExpandedERC20 is ExpandedIERC20, ERC20, MultiRole {
    enum Roles {
        // Can set the minter and burner.
        Owner,
        // Addresses that can mint new tokens.
        Minter,
        // Addresses that can burn tokens that address owns.
        Burner
    }

    /**
     * @notice Constructs the ExpandedERC20.
     * @param _tokenName The name which describes the new token.
     * @param _tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.
     * @param _tokenDecimals The number of decimals to define token precision.
     */
    constructor(
        string memory _tokenName,
        string memory _tokenSymbol,
        uint8 _tokenDecimals
    ) public ERC20(_tokenName, _tokenSymbol) {
        _setupDecimals(_tokenDecimals);
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
        _createSharedRole(uint256(Roles.Minter), uint256(Roles.Owner), new address[](0));
        _createSharedRole(uint256(Roles.Burner), uint256(Roles.Owner), new address[](0));
    }

    /**
     * @dev Mints `value` tokens to `recipient`, returning true on success.
     * @param recipient address to mint to.
     * @param value amount of tokens to mint.
     * @return True if the mint succeeded, or False.
     */
    function mint(address recipient, uint256 value)
        external
        override
        onlyRoleHolder(uint256(Roles.Minter))
        returns (bool)
    {
        _mint(recipient, value);
        return true;
    }

    /**
     * @dev Burns `value` tokens owned by `msg.sender`.
     * @param value amount of tokens to burn.
     */
    function burn(uint256 value) external override onlyRoleHolder(uint256(Roles.Burner)) {
        _burn(msg.sender, value);
    }
}

// File: contracts/common/implementation/Lockable.sol

pragma solidity ^0.6.0;


/**
 * @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract
 * is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol
 * and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.
 */
contract Lockable {
    bool private _notEntered;

    constructor() internal {
        // Storing an initial non-zero value makes deployment a bit more
        // expensive, but in exchange the refund on every call to nonReentrant
        // will be lower in amount. Since refunds are capped to a percetange of
        // the total transaction's gas, it is best to keep them low in cases
        // like this one, to increase the likelihood of the full refund coming
        // into effect.
        _notEntered = true;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _preEntranceCheck();
        _preEntranceSet();
        _;
        _postEntranceReset();
    }

    /**
     * @dev Designed to prevent a view-only method from being re-entered during a call to a `nonReentrant()` state-changing method.
     */
    modifier nonReentrantView() {
        _preEntranceCheck();
        _;
    }

    // Internal methods are used to avoid copying the require statement's bytecode to every `nonReentrant()` method.
    // On entry into a function, `_preEntranceCheck()` should always be called to check if the function is being re-entered.
    // Then, if the function modifies state, it should call `_postEntranceSet()`, perform its logic, and then call `_postEntranceReset()`.
    // View-only methods can simply call `_preEntranceCheck()` to make sure that it is not being re-entered.
    function _preEntranceCheck() internal view {
        // On the first call to nonReentrant, _notEntered will be true
        require(_notEntered, "ReentrancyGuard: reentrant call");
    }

    function _preEntranceSet() internal {
        // Any calls to nonReentrant after this point will fail
        _notEntered = false;
    }

    function _postEntranceReset() internal {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _notEntered = true;
    }
}

// File: contracts/financial-templates/common/SyntheticToken.sol

pragma solidity ^0.6.0;




/**
 * @title Burnable and mintable ERC20.
 * @dev The contract deployer will initially be the only minter, burner and owner capable of adding new roles.
 */

contract SyntheticToken is ExpandedERC20, Lockable {
    /**
     * @notice Constructs the SyntheticToken.
     * @param tokenName The name which describes the new token.
     * @param tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.
     * @param tokenDecimals The number of decimals to define token precision.
     */
    constructor(
        string memory tokenName,
        string memory tokenSymbol,
        uint8 tokenDecimals
    ) public ExpandedERC20(tokenName, tokenSymbol, tokenDecimals) nonReentrant() {}

    /**
     * @notice Add Minter role to account.
     * @dev The caller must have the Owner role.
     * @param account The address to which the Minter role is added.
     */
    function addMinter(address account) external nonReentrant() {
        addMember(uint256(Roles.Minter), account);
    }

    /**
     * @notice Remove Minter role from account.
     * @dev The caller must have the Owner role.
     * @param account The address from which the Minter role is removed.
     */
    function removeMinter(address account) external nonReentrant() {
        removeMember(uint256(Roles.Minter), account);
    }

    /**
     * @notice Add Burner role to account.
     * @dev The caller must have the Owner role.
     * @param account The address to which the Burner role is added.
     */
    function addBurner(address account) external nonReentrant() {
        addMember(uint256(Roles.Burner), account);
    }

    /**
     * @notice Removes Burner role from account.
     * @dev The caller must have the Owner role.
     * @param account The address from which the Burner role is removed.
     */
    function removeBurner(address account) external nonReentrant() {
        removeMember(uint256(Roles.Burner), account);
    }

    /**
     * @notice Reset Owner role to account.
     * @dev The caller must have the Owner role.
     * @param account The new holder of the Owner role.
     */
    function resetOwner(address account) external nonReentrant() {
        resetMember(uint256(Roles.Owner), account);
    }

    /**
     * @notice Checks if a given account holds the Minter role.
     * @param account The address which is checked for the Minter role.
     * @return bool True if the provided account is a Minter.
     */
    function isMinter(address account) public view nonReentrantView() returns (bool) {
        return holdsRole(uint256(Roles.Minter), account);
    }

    /**
     * @notice Checks if a given account holds the Burner role.
     * @param account The address which is checked for the Burner role.
     * @return bool True if the provided account is a Burner.
     */
    function isBurner(address account) public view nonReentrantView() returns (bool) {
        return holdsRole(uint256(Roles.Burner), account);
    }
}

// File: contracts/financial-templates/common/TokenFactory.sol

pragma solidity ^0.6.0;





/**
 * @title Factory for creating new mintable and burnable tokens.
 */

contract TokenFactory is Lockable {
    /**
     * @notice Create a new token and return it to the caller.
     * @dev The caller will become the only minter and burner and the new owner capable of assigning the roles.
     * @param tokenName used to describe the new token.
     * @param tokenSymbol short ticker abbreviation of the name. Ideally < 5 chars.
     * @param tokenDecimals used to define the precision used in the token's numerical representation.
     * @return newToken an instance of the newly created token interface.
     */
    function createToken(
        string calldata tokenName,
        string calldata tokenSymbol,
        uint8 tokenDecimals
    ) external nonReentrant() returns (ExpandedIERC20 newToken) {
        SyntheticToken mintableToken = new SyntheticToken(tokenName, tokenSymbol, tokenDecimals);
        mintableToken.addMinter(msg.sender);
        mintableToken.addBurner(msg.sender);
        mintableToken.resetOwner(msg.sender);
        newToken = ExpandedIERC20(address(mintableToken));
    }
}

// File: contracts/common/implementation/Timer.sol

pragma solidity ^0.6.0;


/**
 * @title Universal store of current contract time for testing environments.
 */
contract Timer {
    uint256 private currentTime;

    constructor() public {
        currentTime = now; // solhint-disable-line not-rely-on-time
    }

    /**
     * @notice Sets the current time.
     * @dev Will revert if not running in test mode.
     * @param time timestamp to set `currentTime` to.
     */
    function setCurrentTime(uint256 time) external {
        currentTime = time;
    }

    /**
     * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.
     * Otherwise, it will return the block timestamp.
     * @return uint256 for the current Testable timestamp.
     */
    function getCurrentTime() public view returns (uint256) {
        return currentTime;
    }
}

// File: contracts/common/implementation/Testable.sol

pragma solidity ^0.6.0;



/**
 * @title Base class that provides time overrides, but only if being run in test mode.
 */
abstract contract Testable {
    // If the contract is being run on the test network, then `timerAddress` will be the 0x0 address.
    // Note: this variable should be set on construction and never modified.
    address public timerAddress;

    /**
     * @notice Constructs the Testable contract. Called by child contracts.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(address _timerAddress) internal {
        timerAddress = _timerAddress;
    }

    /**
     * @notice Reverts if not running in test mode.
     */
    modifier onlyIfTest {
        require(timerAddress != address(0x0));
        _;
    }

    /**
     * @notice Sets the current time.
     * @dev Will revert if not running in test mode.
     * @param time timestamp to set current Testable time to.
     */
    function setCurrentTime(uint256 time) external onlyIfTest {
        Timer(timerAddress).setCurrentTime(time);
    }

    /**
     * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.
     * Otherwise, it will return the block timestamp.
     * @return uint for the current Testable timestamp.
     */
    function getCurrentTime() public view returns (uint256) {
        if (timerAddress != address(0x0)) {
            return Timer(timerAddress).getCurrentTime();
        } else {
            return now; // solhint-disable-line not-rely-on-time
        }
    }
}

// File: contracts/oracle/interfaces/StoreInterface.sol

pragma solidity ^0.6.0;




/**
 * @title Interface that allows financial contracts to pay oracle fees for their use of the system.
 */
interface StoreInterface {
    /**
     * @notice Pays Oracle fees in ETH to the store.
     * @dev To be used by contracts whose margin currency is ETH.
     */
    function payOracleFees() external payable;

    /**
     * @notice Pays oracle fees in the margin currency, erc20Address, to the store.
     * @dev To be used if the margin currency is an ERC20 token rather than ETH.
     * @param erc20Address address of the ERC20 token used to pay the fee.
     * @param amount number of tokens to transfer. An approval for at least this amount must exist.
     */
    function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external;

    /**
     * @notice Computes the regular oracle fees that a contract should pay for a period.
     * @param startTime defines the beginning time from which the fee is paid.
     * @param endTime end time until which the fee is paid.
     * @param pfc "profit from corruption", or the maximum amount of margin currency that a
     * token sponsor could extract from the contract through corrupting the price feed in their favor.
     * @return regularFee amount owed for the duration from start to end time for the given pfc.
     * @return latePenalty for paying the fee after the deadline.
     */
    function computeRegularFee(
        uint256 startTime,
        uint256 endTime,
        FixedPoint.Unsigned calldata pfc
    ) external view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty);

    /**
     * @notice Computes the final oracle fees that a contract should pay at settlement.
     * @param currency token used to pay the final fee.
     * @return finalFee amount due.
     */
    function computeFinalFee(address currency) external view returns (FixedPoint.Unsigned memory);
}

// File: contracts/oracle/interfaces/FinderInterface.sol

pragma solidity ^0.6.0;


/**
 * @title Provides addresses of the live contracts implementing certain interfaces.
 * @dev Examples are the Oracle or Store interfaces.
 */
interface FinderInterface {
    /**
     * @notice Updates the address of the contract that implements `interfaceName`.
     * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
     * @param implementationAddress address of the deployed contract that implements the interface.
     */
    function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;

    /**
     * @notice Gets the address of the contract that implements the given `interfaceName`.
     * @param interfaceName queried interface.
     * @return implementationAddress address of the deployed contract that implements the interface.
     */
    function getImplementationAddress(bytes32 interfaceName) external view returns (address);
}

// File: contracts/financial-templates/common/FeePayer.sol

pragma solidity ^0.6.0;










/**
 * @title FeePayer contract.
 * @notice Provides fee payment functionality for the ExpiringMultiParty contract.
 * contract is abstract as each derived contract that inherits `FeePayer` must implement `pfc()`.
 */

abstract contract FeePayer is Testable, Lockable {
    using SafeMath for uint256;
    using FixedPoint for FixedPoint.Unsigned;
    using SafeERC20 for IERC20;

    /****************************************
     *      FEE PAYER DATA STRUCTURES       *
     ****************************************/

    // The collateral currency used to back the positions in this contract.
    IERC20 public collateralCurrency;

    // Finder contract used to look up addresses for UMA system contracts.
    FinderInterface public finder;

    // Tracks the last block time when the fees were paid.
    uint256 private lastPaymentTime;

    // Tracks the cumulative fees that have been paid by the contract for use by derived contracts.
    // The multiplier starts at 1, and is updated by computing cumulativeFeeMultiplier * (1 - effectiveFee).
    // Put another way, the cumulativeFeeMultiplier is (1 - effectiveFee1) * (1 - effectiveFee2) ...
    // For example:
    // The cumulativeFeeMultiplier should start at 1.
    // If a 1% fee is charged, the multiplier should update to .99.
    // If another 1% fee is charged, the multiplier should be 0.99^2 (0.9801).
    FixedPoint.Unsigned public cumulativeFeeMultiplier;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event RegularFeesPaid(uint256 indexed regularFee, uint256 indexed lateFee);
    event FinalFeesPaid(uint256 indexed amount);

    /****************************************
     *              MODIFIERS               *
     ****************************************/

    // modifier that calls payRegularFees().
    modifier fees {
        payRegularFees();
        _;
    }

    /**
     * @notice Constructs the FeePayer contract. Called by child contracts.
     * @param _collateralAddress ERC20 token that is used as the underlying collateral for the synthetic.
     * @param _finderAddress UMA protocol Finder used to discover other protocol contracts.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        address _collateralAddress,
        address _finderAddress,
        address _timerAddress
    ) public Testable(_timerAddress) nonReentrant() {
        collateralCurrency = IERC20(_collateralAddress);
        finder = FinderInterface(_finderAddress);
        lastPaymentTime = getCurrentTime();
        cumulativeFeeMultiplier = FixedPoint.fromUnscaledUint(1);
    }

    /****************************************
     *        FEE PAYMENT FUNCTIONS         *
     ****************************************/

    /**
     * @notice Pays UMA DVM regular fees (as a % of the collateral pool) to the Store contract.
     * @dev These must be paid periodically for the life of the contract. If the contract has not paid its regular fee
     * in a week or more then a late penalty is applied which is sent to the caller. If the amount of
     * fees owed are greater than the pfc, then this will pay as much as possible from the available collateral.
     * An event is only fired if the fees charged are greater than 0.
     * @return totalPaid Amount of collateral that the contract paid (sum of the amount paid to the Store and caller).
     * This returns 0 and exit early if there is no pfc, fees were already paid during the current block, or the fee rate is 0.
     */
    function payRegularFees() public nonReentrant() returns (FixedPoint.Unsigned memory totalPaid) {
        StoreInterface store = _getStore();
        uint256 time = getCurrentTime();
        FixedPoint.Unsigned memory collateralPool = _pfc();

        // Exit early if there is no collateral from which to pay fees.
        if (collateralPool.isEqual(0)) {
            return totalPaid;
        }

        // Exit early if fees were already paid during this block.
        if (lastPaymentTime == time) {
            return totalPaid;
        }

        (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty) = store.computeRegularFee(
            lastPaymentTime,
            time,
            collateralPool
        );
        lastPaymentTime = time;

        totalPaid = regularFee.add(latePenalty);
        if (totalPaid.isEqual(0)) {
            return totalPaid;
        }
        // If the effective fees paid as a % of the pfc is > 100%, then we need to reduce it and make the contract pay
        // as much of the fee that it can (up to 100% of its pfc). We'll reduce the late penalty first and then the
        // regular fee, which has the effect of paying the store first, followed by the caller if there is any fee remaining.
        if (totalPaid.isGreaterThan(collateralPool)) {
            FixedPoint.Unsigned memory deficit = totalPaid.sub(collateralPool);
            FixedPoint.Unsigned memory latePenaltyReduction = FixedPoint.min(latePenalty, deficit);
            latePenalty = latePenalty.sub(latePenaltyReduction);
            deficit = deficit.sub(latePenaltyReduction);
            regularFee = regularFee.sub(FixedPoint.min(regularFee, deficit));
            totalPaid = collateralPool;
        }

        emit RegularFeesPaid(regularFee.rawValue, latePenalty.rawValue);

        _adjustCumulativeFeeMultiplier(totalPaid, collateralPool);

        if (regularFee.isGreaterThan(0)) {
            collateralCurrency.safeIncreaseAllowance(address(store), regularFee.rawValue);
            store.payOracleFeesErc20(address(collateralCurrency), regularFee);
        }

        if (latePenalty.isGreaterThan(0)) {
            collateralCurrency.safeTransfer(msg.sender, latePenalty.rawValue);
        }
        return totalPaid;
    }

    /**
     * @notice Gets the current profit from corruption for this contract in terms of the collateral currency.
     * @dev This is equivalent to the collateral pool available from which to pay fees. Therefore, derived contracts are
     * expected to implement this so that pay-fee methods can correctly compute the owed fees as a % of PfC.
     * @return pfc value for equal to the current profit from corrution denominated in collateral currency.
     */
    function pfc() public view nonReentrantView() returns (FixedPoint.Unsigned memory) {
        return _pfc();
    }

    /****************************************
     *         INTERNAL FUNCTIONS           *
     ****************************************/

    // Pays UMA Oracle final fees of `amount` in `collateralCurrency` to the Store contract. Final fee is a flat fee
    // charged for each price request. If payer is the contract, adjusts internal bookkeeping variables. If payer is not
    // the contract, pulls in `amount` of collateral currency.
    function _payFinalFees(address payer, FixedPoint.Unsigned memory amount) internal {
        if (amount.isEqual(0)) {
            return;
        }

        if (payer != address(this)) {
            // If the payer is not the contract pull the collateral from the payer.
            collateralCurrency.safeTransferFrom(payer, address(this), amount.rawValue);
        } else {
            // If the payer is the contract, adjust the cumulativeFeeMultiplier to compensate.
            FixedPoint.Unsigned memory collateralPool = _pfc();

            // The final fee must be < available collateral or the fee will be larger than 100%.
            require(collateralPool.isGreaterThan(amount), "Final fee is more than PfC");

            _adjustCumulativeFeeMultiplier(amount, collateralPool);
        }

        emit FinalFeesPaid(amount.rawValue);

        StoreInterface store = _getStore();
        collateralCurrency.safeIncreaseAllowance(address(store), amount.rawValue);
        store.payOracleFeesErc20(address(collateralCurrency), amount);
    }

    function _pfc() internal virtual view returns (FixedPoint.Unsigned memory);

    function _getStore() internal view returns (StoreInterface) {
        return StoreInterface(finder.getImplementationAddress(OracleInterfaces.Store));
    }

    function _computeFinalFees() internal view returns (FixedPoint.Unsigned memory finalFees) {
        StoreInterface store = _getStore();
        return store.computeFinalFee(address(collateralCurrency));
    }

    // Returns the user's collateral minus any fees that have been subtracted since it was originally
    // deposited into the contract. Note: if the contract has paid fees since it was deployed, the raw
    // value should be larger than the returned value.
    function _getFeeAdjustedCollateral(FixedPoint.Unsigned memory rawCollateral)
        internal
        view
        returns (FixedPoint.Unsigned memory collateral)
    {
        return rawCollateral.mul(cumulativeFeeMultiplier);
    }

    // Converts a user-readable collateral value into a raw value that accounts for already-assessed fees. If any fees
    // have been taken from this contract in the past, then the raw value will be larger than the user-readable value.
    function _convertToRawCollateral(FixedPoint.Unsigned memory collateral)
        internal
        view
        returns (FixedPoint.Unsigned memory rawCollateral)
    {
        return collateral.div(cumulativeFeeMultiplier);
    }

    // Decrease rawCollateral by a fee-adjusted collateralToRemove amount. Fee adjustment scales up collateralToRemove
    // by dividing it by cumulativeFeeMultiplier. There is potential for this quotient to be floored, therefore
    // rawCollateral is decreased by less than expected. Because this method is usually called in conjunction with an
    // actual removal of collateral from this contract, return the fee-adjusted amount that the rawCollateral is
    // decreased by so that the caller can minimize error between collateral removed and rawCollateral debited.
    function _removeCollateral(FixedPoint.Unsigned storage rawCollateral, FixedPoint.Unsigned memory collateralToRemove)
        internal
        returns (FixedPoint.Unsigned memory removedCollateral)
    {
        FixedPoint.Unsigned memory initialBalance = _getFeeAdjustedCollateral(rawCollateral);
        FixedPoint.Unsigned memory adjustedCollateral = _convertToRawCollateral(collateralToRemove);
        rawCollateral.rawValue = rawCollateral.sub(adjustedCollateral).rawValue;
        removedCollateral = initialBalance.sub(_getFeeAdjustedCollateral(rawCollateral));
    }

    // Increase rawCollateral by a fee-adjusted collateralToAdd amount. Fee adjustment scales up collateralToAdd
    // by dividing it by cumulativeFeeMultiplier. There is potential for this quotient to be floored, therefore
    // rawCollateral is increased by less than expected. Because this method is usually called in conjunction with an
    // actual addition of collateral to this contract, return the fee-adjusted amount that the rawCollateral is
    // increased by so that the caller can minimize error between collateral added and rawCollateral credited.
    // NOTE: This return value exists only for the sake of symmetry with _removeCollateral. We don't actually use it
    // because we are OK if more collateral is stored in the contract than is represented by rawTotalPositionCollateral.
    function _addCollateral(FixedPoint.Unsigned storage rawCollateral, FixedPoint.Unsigned memory collateralToAdd)
        internal
        returns (FixedPoint.Unsigned memory addedCollateral)
    {
        FixedPoint.Unsigned memory initialBalance = _getFeeAdjustedCollateral(rawCollateral);
        FixedPoint.Unsigned memory adjustedCollateral = _convertToRawCollateral(collateralToAdd);
        rawCollateral.rawValue = rawCollateral.add(adjustedCollateral).rawValue;
        addedCollateral = _getFeeAdjustedCollateral(rawCollateral).sub(initialBalance);
    }

    // Scale the cumulativeFeeMultiplier by the ratio of fees paid to the current available collateral.
    function _adjustCumulativeFeeMultiplier(FixedPoint.Unsigned memory amount, FixedPoint.Unsigned memory currentPfc)
        internal
    {
        FixedPoint.Unsigned memory effectiveFee = amount.divCeil(currentPfc);
        cumulativeFeeMultiplier = cumulativeFeeMultiplier.mul(FixedPoint.fromUnscaledUint(1).sub(effectiveFee));
    }
}

// File: contracts/financial-templates/expiring-multiparty/PricelessPositionManager.sol

pragma solidity ^0.6.0;













/**
 * @title Financial contract with priceless position management.
 * @notice Handles positions for multiple sponsors in an optimistic (i.e., priceless) way without relying
 * on a price feed. On construction, deploys a new ERC20, managed by this contract, that is the synthetic token.
 */

contract PricelessPositionManager is FeePayer, AdministrateeInterface {
    using SafeMath for uint256;
    using FixedPoint for FixedPoint.Unsigned;
    using SafeERC20 for IERC20;
    using SafeERC20 for ExpandedIERC20;

    /****************************************
     *  PRICELESS POSITION DATA STRUCTURES  *
     ****************************************/

    // Stores the state of the PricelessPositionManager. Set on expiration, emergency shutdown, or settlement.
    enum ContractState { Open, ExpiredPriceRequested, ExpiredPriceReceived }
    ContractState public contractState;

    // Represents a single sponsor's position. All collateral is held by this contract.
    // This struct acts as bookkeeping for how much of that collateral is allocated to each sponsor.
    struct PositionData {
        FixedPoint.Unsigned tokensOutstanding;
        // Tracks pending withdrawal requests. A withdrawal request is pending if `withdrawalRequestPassTimestamp != 0`.
        uint256 withdrawalRequestPassTimestamp;
        FixedPoint.Unsigned withdrawalRequestAmount;
        // Raw collateral value. This value should never be accessed directly -- always use _getFeeAdjustedCollateral().
        // To add or remove collateral, use _addCollateral() and _removeCollateral().
        FixedPoint.Unsigned rawCollateral;
        // Tracks pending transfer position requests. A transfer position request is pending if `transferPositionRequestPassTimestamp != 0`.
        uint256 transferPositionRequestPassTimestamp;
    }

    // Maps sponsor addresses to their positions. Each sponsor can have only one position.
    mapping(address => PositionData) public positions;

    // Keep track of the total collateral and tokens across all positions to enable calculating the
    // global collateralization ratio without iterating over all positions.
    FixedPoint.Unsigned public totalTokensOutstanding;

    // Similar to the rawCollateral in PositionData, this value should not be used directly.
    // _getFeeAdjustedCollateral(), _addCollateral() and _removeCollateral() must be used to access and adjust.
    FixedPoint.Unsigned public rawTotalPositionCollateral;

    // Synthetic token created by this contract.
    ExpandedIERC20 public tokenCurrency;

    // Unique identifier for DVM price feed ticker.
    bytes32 public priceIdentifier;
    // Time that this contract expires. Should not change post-construction unless an emergency shutdown occurs.
    uint256 public expirationTimestamp;
    // Time that has to elapse for a withdrawal request to be considered passed, if no liquidations occur.
    uint256 public withdrawalLiveness;

    // Minimum number of tokens in a sponsor's position.
    FixedPoint.Unsigned public minSponsorTokens;

    // The expiry price pulled from the DVM.
    FixedPoint.Unsigned public expiryPrice;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event RequestTransferPosition(address indexed oldSponsor);
    event RequestTransferPositionExecuted(address indexed oldSponsor, address indexed newSponsor);
    event RequestTransferPositionCanceled(address indexed oldSponsor);
    event Deposit(address indexed sponsor, uint256 indexed collateralAmount);
    event Withdrawal(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawal(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawalExecuted(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawalCanceled(address indexed sponsor, uint256 indexed collateralAmount);
    event PositionCreated(address indexed sponsor, uint256 indexed collateralAmount, uint256 indexed tokenAmount);
    event NewSponsor(address indexed sponsor);
    event EndedSponsorPosition(address indexed sponsor);
    event Redeem(address indexed sponsor, uint256 indexed collateralAmount, uint256 indexed tokenAmount);
    event ContractExpired(address indexed caller);
    event SettleExpiredPosition(
        address indexed caller,
        uint256 indexed collateralReturned,
        uint256 indexed tokensBurned
    );
    event EmergencyShutdown(address indexed caller, uint256 originalExpirationTimestamp, uint256 shutdownTimestamp);

    /****************************************
     *               MODIFIERS              *
     ****************************************/

    modifier onlyPreExpiration() {
        _onlyPreExpiration();
        _;
    }

    modifier onlyPostExpiration() {
        _onlyPostExpiration();
        _;
    }

    modifier onlyCollateralizedPosition(address sponsor) {
        _onlyCollateralizedPosition(sponsor);
        _;
    }

    // Check that the current state of the pricelessPositionManager is Open.
    // This prevents multiple calls to `expire` and `EmergencyShutdown` post expiration.
    modifier onlyOpenState() {
        _onlyOpenState();
        _;
    }

    modifier noPendingWithdrawal(address sponsor) {
        _positionHasNoPendingWithdrawal(sponsor);
        _;
    }

    /**
     * @notice Construct the PricelessPositionManager
     * @param _expirationTimestamp unix timestamp of when the contract will expire.
     * @param _withdrawalLiveness liveness delay, in seconds, for pending withdrawals.
     * @param _collateralAddress ERC20 token used as collateral for all positions.
     * @param _finderAddress UMA protocol Finder used to discover other protocol contracts.
     * @param _priceIdentifier registered in the DVM for the synthetic.
     * @param _syntheticName name for the token contract that will be deployed.
     * @param _syntheticSymbol symbol for the token contract that will be deployed.
     * @param _tokenFactoryAddress deployed UMA token factory to create the synthetic token.
     * @param _minSponsorTokens minimum amount of collateral that must exist at any time in a position.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        uint256 _expirationTimestamp,
        uint256 _withdrawalLiveness,
        address _collateralAddress,
        address _finderAddress,
        bytes32 _priceIdentifier,
        string memory _syntheticName,
        string memory _syntheticSymbol,
        address _tokenFactoryAddress,
        FixedPoint.Unsigned memory _minSponsorTokens,
        address _timerAddress
    ) public FeePayer(_collateralAddress, _finderAddress, _timerAddress) nonReentrant() {
        require(_expirationTimestamp > getCurrentTime(), "Invalid expiration in future");
        require(_getIdentifierWhitelist().isIdentifierSupported(_priceIdentifier), "Unsupported price identifier");

        expirationTimestamp = _expirationTimestamp;
        withdrawalLiveness = _withdrawalLiveness;
        TokenFactory tf = TokenFactory(_tokenFactoryAddress);
        tokenCurrency = tf.createToken(_syntheticName, _syntheticSymbol, 18);
        minSponsorTokens = _minSponsorTokens;
        priceIdentifier = _priceIdentifier;
    }

    /****************************************
     *          POSITION FUNCTIONS          *
     ****************************************/

    /**
     * @notice Requests to transfer ownership of the caller's current position to a new sponsor address.
     * Once the request liveness is passed, the sponsor can execute the transfer and specify the new sponsor.
     * @dev The liveness length is the same as the withdrawal liveness.
     */
    function requestTransferPosition() public onlyPreExpiration() nonReentrant() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.transferPositionRequestPassTimestamp == 0, "Pending transfer");

        // Make sure the proposed expiration of this request is not post-expiry.
        uint256 requestPassTime = getCurrentTime().add(withdrawalLiveness);
        require(requestPassTime < expirationTimestamp, "Request expires post-expiry");

        // Update the position object for the user.
        positionData.transferPositionRequestPassTimestamp = requestPassTime;

        emit RequestTransferPosition(msg.sender);
    }

    /**
     * @notice After a passed transfer position request (i.e., by a call to `requestTransferPosition` and waiting
     * `withdrawalLiveness`), transfers ownership of the caller's current position to `newSponsorAddress`.
     * @dev Transferring positions can only occur if the recipient does not already have a position.
     * @param newSponsorAddress is the address to which the position will be transferred.
     */
    function transferPositionPassedRequest(address newSponsorAddress)
        public
        onlyPreExpiration()
        noPendingWithdrawal(msg.sender)
        nonReentrant()
    {
        require(
            _getFeeAdjustedCollateral(positions[newSponsorAddress].rawCollateral).isEqual(
                FixedPoint.fromUnscaledUint(0)
            ),
            "Sponsor already has position"
        );
        PositionData storage positionData = _getPositionData(msg.sender);
        require(
            positionData.transferPositionRequestPassTimestamp != 0 &&
                positionData.transferPositionRequestPassTimestamp <= getCurrentTime(),
            "Invalid transfer request"
        );

        // Reset transfer request.
        positionData.transferPositionRequestPassTimestamp = 0;

        positions[newSponsorAddress] = positionData;
        delete positions[msg.sender];

        emit RequestTransferPositionExecuted(msg.sender, newSponsorAddress);
        emit NewSponsor(newSponsorAddress);
        emit EndedSponsorPosition(msg.sender);
    }

    /**
     * @notice Cancels a pending transfer position request.
     */
    function cancelTransferPosition() external onlyPreExpiration() nonReentrant() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.transferPositionRequestPassTimestamp != 0, "No pending transfer");

        emit RequestTransferPositionCanceled(msg.sender);

        // Reset withdrawal request.
        positionData.transferPositionRequestPassTimestamp = 0;
    }

    /**
     * @notice Transfers `collateralAmount` of `collateralCurrency` into the specified sponsor's position.
     * @dev Increases the collateralization level of a position after creation. This contract must be approved to spend
     * at least `collateralAmount` of `collateralCurrency`.
     * @param sponsor the sponsor to credit the deposit to.
     * @param collateralAmount total amount of collateral tokens to be sent to the sponsor's position.
     */
    function depositTo(address sponsor, FixedPoint.Unsigned memory collateralAmount)
        public
        onlyPreExpiration()
        noPendingWithdrawal(sponsor)
        fees()
        nonReentrant()
    {
        require(collateralAmount.isGreaterThan(0), "Invalid collateral amount");
        PositionData storage positionData = _getPositionData(sponsor);

        // Increase the position and global collateral balance by collateral amount.
        _incrementCollateralBalances(positionData, collateralAmount);

        emit Deposit(sponsor, collateralAmount.rawValue);

        // Move collateral currency from sender to contract.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), collateralAmount.rawValue);
    }

    /**
     * @notice Transfers `collateralAmount` of `collateralCurrency` into the caller's position.
     * @dev Increases the collateralization level of a position after creation. This contract must be approved to spend
     * at least `collateralAmount` of `collateralCurrency`.
     * @param collateralAmount total amount of collateral tokens to be sent to the sponsor's position.
     */
    function deposit(FixedPoint.Unsigned memory collateralAmount) public {
        // This is just a thin wrapper over depositTo that specified the sender as the sponsor.
        depositTo(msg.sender, collateralAmount);
    }

    /**
     * @notice Transfers `collateralAmount` of `collateralCurrency` from the sponsor's position to the sponsor.
     * @dev Reverts if the withdrawal puts this position's collateralization ratio below the global collateralization
     * ratio. In that case, use `requestWithdrawal`. Might not withdraw the full requested amount to account for precision loss.
     * @param collateralAmount is the amount of collateral to withdraw.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function withdraw(FixedPoint.Unsigned memory collateralAmount)
        public
        onlyPreExpiration()
        noPendingWithdrawal(msg.sender)
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(collateralAmount.isGreaterThan(0), "Invalid collateral amount");

        // Decrement the sponsor's collateral and global collateral amounts. Check the GCR between decrement to ensure
        // position remains above the GCR within the witdrawl. If this is not the case the caller must submit a request.
        amountWithdrawn = _decrementCollateralBalancesCheckGCR(positionData, collateralAmount);

        emit Withdrawal(msg.sender, amountWithdrawn.rawValue);

        // Move collateral currency from contract to sender.
        // Note: that we move the amount of collateral that is decreased from rawCollateral (inclusive of fees)
        // instead of the user requested amount. This eliminates precision loss that could occur
        // where the user withdraws more collateral than rawCollateral is decremented by.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);
    }

    /**
     * @notice Starts a withdrawal request that, if passed, allows the sponsor to withdraw` from their position.
     * @dev The request will be pending for `withdrawalLiveness`, during which the position can be liquidated.
     * @param collateralAmount the amount of collateral requested to withdraw
     */
    function requestWithdrawal(FixedPoint.Unsigned memory collateralAmount)
        public
        onlyPreExpiration()
        noPendingWithdrawal(msg.sender)
        nonReentrant()
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(
            collateralAmount.isGreaterThan(0) &&
                collateralAmount.isLessThanOrEqual(_getFeeAdjustedCollateral(positionData.rawCollateral)),
            "Invalid collateral amount"
        );

        // Make sure the proposed expiration of this request is not post-expiry.
        uint256 requestPassTime = getCurrentTime().add(withdrawalLiveness);
        require(requestPassTime < expirationTimestamp, "Request expires post-expiry");

        // Update the position object for the user.
        positionData.withdrawalRequestPassTimestamp = requestPassTime;
        positionData.withdrawalRequestAmount = collateralAmount;

        emit RequestWithdrawal(msg.sender, collateralAmount.rawValue);
    }

    /**
     * @notice After a passed withdrawal request (i.e., by a call to `requestWithdrawal` and waiting
     * `withdrawalLiveness`), withdraws `positionData.withdrawalRequestAmount` of collateral currency.
     * @dev Might not withdraw the full requested amount in order to account for precision loss or if the full requested
     * amount exceeds the collateral in the position (due to paying fees).
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function withdrawPassedRequest()
        external
        onlyPreExpiration()
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(
            positionData.withdrawalRequestPassTimestamp != 0 &&
                positionData.withdrawalRequestPassTimestamp <= getCurrentTime(),
            "Invalid withdraw request"
        );

        // If withdrawal request amount is > position collateral, then withdraw the full collateral amount.
        // This situation is possible due to fees charged since the withdrawal was originally requested.
        FixedPoint.Unsigned memory amountToWithdraw = positionData.withdrawalRequestAmount;
        if (positionData.withdrawalRequestAmount.isGreaterThan(_getFeeAdjustedCollateral(positionData.rawCollateral))) {
            amountToWithdraw = _getFeeAdjustedCollateral(positionData.rawCollateral);
        }

        // Decrement the sponsor's collateral and global collateral amounts.
        amountWithdrawn = _decrementCollateralBalances(positionData, amountToWithdraw);

        // Reset withdrawal request by setting withdrawal amount and withdrawal timestamp to 0.
        _resetWithdrawalRequest(positionData);

        // Transfer approved withdrawal amount from the contract to the caller.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);

        emit RequestWithdrawalExecuted(msg.sender, amountWithdrawn.rawValue);
    }

    /**
     * @notice Cancels a pending withdrawal request.
     */
    function cancelWithdrawal() external onlyPreExpiration() nonReentrant() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.withdrawalRequestPassTimestamp != 0, "No pending withdrawal");

        emit RequestWithdrawalCanceled(msg.sender, positionData.withdrawalRequestAmount.rawValue);

        // Reset withdrawal request by setting withdrawal amount and withdrawal timestamp to 0.
        _resetWithdrawalRequest(positionData);
    }

    /**
     * @notice Creates tokens by creating a new position or by augmenting an existing position. Pulls `collateralAmount` into the sponsor's position and mints `numTokens` of `tokenCurrency`.
     * @dev Reverts if minting these tokens would put the position's collateralization ratio below the
     * global collateralization ratio. This contract must be approved to spend at least `collateralAmount` of
     * `collateralCurrency`.
     * @param collateralAmount is the number of collateral tokens to collateralize the position with
     * @param numTokens is the number of tokens to mint from the position.
     */
    function create(FixedPoint.Unsigned memory collateralAmount, FixedPoint.Unsigned memory numTokens)
        public
        onlyPreExpiration()
        fees()
        nonReentrant()
    {
        require(_checkCollateralization(collateralAmount, numTokens), "CR below GCR");

        PositionData storage positionData = positions[msg.sender];
        require(positionData.withdrawalRequestPassTimestamp == 0, "Pending withdrawal");
        if (positionData.tokensOutstanding.isEqual(0)) {
            require(numTokens.isGreaterThanOrEqual(minSponsorTokens), "Below minimum sponsor position");
            emit NewSponsor(msg.sender);
        }

        // Increase the position and global collateral balance by collateral amount.
        _incrementCollateralBalances(positionData, collateralAmount);

        // Add the number of tokens created to the position's outstanding tokens.
        positionData.tokensOutstanding = positionData.tokensOutstanding.add(numTokens);

        totalTokensOutstanding = totalTokensOutstanding.add(numTokens);

        emit PositionCreated(msg.sender, collateralAmount.rawValue, numTokens.rawValue);

        // Transfer tokens into the contract from caller and mint corresponding synthetic tokens to the caller's address.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), collateralAmount.rawValue);
        require(tokenCurrency.mint(msg.sender, numTokens.rawValue), "Minting synthetic tokens failed");
    }

    /**
     * @notice Burns `numTokens` of `tokenCurrency` and sends back the proportional amount of `collateralCurrency`.
     * @dev Can only be called by a token sponsor. Might not redeem the full proportional amount of collateral
     * in order to account for precision loss. This contract must be approved to spend at least `numTokens` of
     * `tokenCurrency`.
     * @param numTokens is the number of tokens to be burnt for a commensurate amount of collateral.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function redeem(FixedPoint.Unsigned memory numTokens)
        public
        onlyPreExpiration()
        noPendingWithdrawal(msg.sender)
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(!numTokens.isGreaterThan(positionData.tokensOutstanding), "Invalid token amount");

        FixedPoint.Unsigned memory fractionRedeemed = numTokens.div(positionData.tokensOutstanding);
        FixedPoint.Unsigned memory collateralRedeemed = fractionRedeemed.mul(
            _getFeeAdjustedCollateral(positionData.rawCollateral)
        );

        // If redemption returns all tokens the sponsor has then we can delete their position. Else, downsize.
        if (positionData.tokensOutstanding.isEqual(numTokens)) {
            amountWithdrawn = _deleteSponsorPosition(msg.sender);
        } else {
            // Decrement the sponsor's collateral and global collateral amounts.
            amountWithdrawn = _decrementCollateralBalances(positionData, collateralRedeemed);

            // Decrease the sponsors position tokens size. Ensure it is above the min sponsor size.
            FixedPoint.Unsigned memory newTokenCount = positionData.tokensOutstanding.sub(numTokens);
            require(newTokenCount.isGreaterThanOrEqual(minSponsorTokens), "Below minimum sponsor position");
            positionData.tokensOutstanding = newTokenCount;

            // Update the totalTokensOutstanding after redemption.
            totalTokensOutstanding = totalTokensOutstanding.sub(numTokens);
        }

        emit Redeem(msg.sender, amountWithdrawn.rawValue, numTokens.rawValue);

        // Transfer collateral from contract to caller and burn callers synthetic tokens.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);
        tokenCurrency.safeTransferFrom(msg.sender, address(this), numTokens.rawValue);
        tokenCurrency.burn(numTokens.rawValue);
    }

    /**
     * @notice After a contract has passed expiry all token holders can redeem their tokens for underlying at the
     * prevailing price defined by the DVM from the `expire` function.
     * @dev This burns all tokens from the caller of `tokenCurrency` and sends back the proportional amount of
     * `collateralCurrency`. Might not redeem the full proportional amount of collateral in order to account for
     * precision loss. This contract must be approved to spend `tokenCurrency` at least up to the caller's full balance.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function settleExpired()
        external
        onlyPostExpiration()
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        // If the contract state is open and onlyPostExpiration passed then `expire()` has not yet been called.
        require(contractState != ContractState.Open, "Unexpired position");

        // Get the current settlement price and store it. If it is not resolved will revert.
        if (contractState != ContractState.ExpiredPriceReceived) {
            expiryPrice = _getOraclePrice(expirationTimestamp);
            contractState = ContractState.ExpiredPriceReceived;
        }

        // Get caller's tokens balance and calculate amount of underlying entitled to them.
        FixedPoint.Unsigned memory tokensToRedeem = FixedPoint.Unsigned(tokenCurrency.balanceOf(msg.sender));
        FixedPoint.Unsigned memory totalRedeemableCollateral = tokensToRedeem.mul(expiryPrice);

        // If the caller is a sponsor with outstanding collateral they are also entitled to their excess collateral after their debt.
        PositionData storage positionData = positions[msg.sender];
        if (_getFeeAdjustedCollateral(positionData.rawCollateral).isGreaterThan(0)) {
            // Calculate the underlying entitled to a token sponsor. This is collateral - debt in underlying.
            FixedPoint.Unsigned memory tokenDebtValueInCollateral = positionData.tokensOutstanding.mul(expiryPrice);
            FixedPoint.Unsigned memory positionCollateral = _getFeeAdjustedCollateral(positionData.rawCollateral);

            // If the debt is greater than the remaining collateral, they cannot redeem anything.
            FixedPoint.Unsigned memory positionRedeemableCollateral = tokenDebtValueInCollateral.isLessThan(
                positionCollateral
            )
                ? positionCollateral.sub(tokenDebtValueInCollateral)
                : FixedPoint.Unsigned(0);

            // Add the number of redeemable tokens for the sponsor to their total redeemable collateral.
            totalRedeemableCollateral = totalRedeemableCollateral.add(positionRedeemableCollateral);

            // Reset the position state as all the value has been removed after settlement.
            delete positions[msg.sender];
            emit EndedSponsorPosition(msg.sender);
        }

        // Take the min of the remaining collateral and the collateral "owed". If the contract is undercapitalized,
        // the caller will get as much collateral as the contract can pay out.
        FixedPoint.Unsigned memory payout = FixedPoint.min(
            _getFeeAdjustedCollateral(rawTotalPositionCollateral),
            totalRedeemableCollateral
        );

        // Decrement total contract collateral and outstanding debt.
        amountWithdrawn = _removeCollateral(rawTotalPositionCollateral, payout);
        totalTokensOutstanding = totalTokensOutstanding.sub(tokensToRedeem);

        emit SettleExpiredPosition(msg.sender, amountWithdrawn.rawValue, tokensToRedeem.rawValue);

        // Transfer tokens & collateral and burn the redeemed tokens.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);
        tokenCurrency.safeTransferFrom(msg.sender, address(this), tokensToRedeem.rawValue);
        tokenCurrency.burn(tokensToRedeem.rawValue);
    }

    /****************************************
     *        GLOBAL STATE FUNCTIONS        *
     ****************************************/

    /**
     * @notice Locks contract state in expired and requests oracle price.
     * @dev this function can only be called once the contract is expired and can't be re-called.
     */
    function expire() external onlyPostExpiration() onlyOpenState() fees() nonReentrant() {
        contractState = ContractState.ExpiredPriceRequested;

        // The final fee for this request is paid out of the contract rather than by the caller.
        _payFinalFees(address(this), _computeFinalFees());
        _requestOraclePrice(expirationTimestamp);

        emit ContractExpired(msg.sender);
    }

    /**
     * @notice Premature contract settlement under emergency circumstances.
     * @dev Only the governor can call this function as they are permissioned within the `FinancialContractAdmin`.
     * Upon emergency shutdown, the contract settlement time is set to the shutdown time. This enables withdrawal
     * to occur via the standard `settleExpired` function. Contract state is set to `ExpiredPriceRequested`
     * which prevents re-entry into this function or the `expire` function. No fees are paid when calling
     * `emergencyShutdown` as the governor who would call the function would also receive the fees.
     */
    function emergencyShutdown() external override onlyPreExpiration() onlyOpenState() nonReentrant() {
        require(msg.sender == _getFinancialContractsAdminAddress(), "Caller not Governor");

        contractState = ContractState.ExpiredPriceRequested;
        // Expiratory time now becomes the current time (emergency shutdown time).
        // Price requested at this time stamp. `settleExpired` can now withdraw at this timestamp.
        uint256 oldExpirationTimestamp = expirationTimestamp;
        expirationTimestamp = getCurrentTime();
        _requestOraclePrice(expirationTimestamp);

        emit EmergencyShutdown(msg.sender, oldExpirationTimestamp, expirationTimestamp);
    }

    /**
     * @notice Theoretically supposed to pay fees and move money between margin accounts to make sure they
     * reflect the NAV of the contract. However, this functionality doesn't apply to this contract.
     * @dev This is supposed to be implemented by any contract that inherits `AdministrateeInterface` and callable
     * only by the Governor contract. This method is therefore minimally implemented in this contract and does nothing.
     */
    function remargin() external override onlyPreExpiration() nonReentrant() {
        return;
    }

    /**
     * @notice Accessor method for a sponsor's collateral.
     * @dev This is necessary because the struct returned by the positions() method shows
     * rawCollateral, which isn't a user-readable value.
     * @param sponsor address whose collateral amount is retrieved.
     * @return collateralAmount amount of collateral within a sponsors position.
     */
    function getCollateral(address sponsor)
        external
        view
        nonReentrantView()
        returns (FixedPoint.Unsigned memory collateralAmount)
    {
        // Note: do a direct access to avoid the validity check.
        return _getFeeAdjustedCollateral(positions[sponsor].rawCollateral);
    }

    /**
     * @notice Accessor method for the total collateral stored within the PricelessPositionManager.
     * @return totalCollateral amount of all collateral within the Expiring Multi Party Contract.
     */
    function totalPositionCollateral()
        external
        view
        nonReentrantView()
        returns (FixedPoint.Unsigned memory totalCollateral)
    {
        return _getFeeAdjustedCollateral(rawTotalPositionCollateral);
    }

    /****************************************
     *          INTERNAL FUNCTIONS          *
     ****************************************/

    // Reduces a sponsor's position and global counters by the specified parameters. Handles deleting the entire
    // position if the entire position is being removed. Does not make any external transfers.
    function _reduceSponsorPosition(
        address sponsor,
        FixedPoint.Unsigned memory tokensToRemove,
        FixedPoint.Unsigned memory collateralToRemove,
        FixedPoint.Unsigned memory withdrawalAmountToRemove
    ) internal {
        PositionData storage positionData = _getPositionData(sponsor);

        // If the entire position is being removed, delete it instead.
        if (
            tokensToRemove.isEqual(positionData.tokensOutstanding) &&
            _getFeeAdjustedCollateral(positionData.rawCollateral).isEqual(collateralToRemove)
        ) {
            _deleteSponsorPosition(sponsor);
            return;
        }

        // Decrement the sponsor's collateral and global collateral amounts.
        _decrementCollateralBalances(positionData, collateralToRemove);

        // Ensure that the sponsor will meet the min position size after the reduction.
        FixedPoint.Unsigned memory newTokenCount = positionData.tokensOutstanding.sub(tokensToRemove);
        require(newTokenCount.isGreaterThanOrEqual(minSponsorTokens), "Below minimum sponsor position");
        positionData.tokensOutstanding = newTokenCount;

        // Decrement the position's withdrawal amount.
        positionData.withdrawalRequestAmount = positionData.withdrawalRequestAmount.sub(withdrawalAmountToRemove);

        // Decrement the total outstanding tokens in the overall contract.
        totalTokensOutstanding = totalTokensOutstanding.sub(tokensToRemove);
    }

    // Deletes a sponsor's position and updates global counters. Does not make any external transfers.
    function _deleteSponsorPosition(address sponsor) internal returns (FixedPoint.Unsigned memory) {
        PositionData storage positionToLiquidate = _getPositionData(sponsor);

        FixedPoint.Unsigned memory startingGlobalCollateral = _getFeeAdjustedCollateral(rawTotalPositionCollateral);

        // Remove the collateral and outstanding from the overall total position.
        FixedPoint.Unsigned memory remainingRawCollateral = positionToLiquidate.rawCollateral;
        rawTotalPositionCollateral = rawTotalPositionCollateral.sub(remainingRawCollateral);
        totalTokensOutstanding = totalTokensOutstanding.sub(positionToLiquidate.tokensOutstanding);

        // Reset the sponsors position to have zero outstanding and collateral.
        delete positions[sponsor];

        emit EndedSponsorPosition(sponsor);

        // Return fee-adjusted amount of collateral deleted from position.
        return startingGlobalCollateral.sub(_getFeeAdjustedCollateral(rawTotalPositionCollateral));
    }

    function _pfc() internal virtual override view returns (FixedPoint.Unsigned memory) {
        return _getFeeAdjustedCollateral(rawTotalPositionCollateral);
    }

    function _getPositionData(address sponsor)
        internal
        view
        onlyCollateralizedPosition(sponsor)
        returns (PositionData storage)
    {
        return positions[sponsor];
    }

    function _getIdentifierWhitelist() internal view returns (IdentifierWhitelistInterface) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }

    function _getOracle() internal view returns (OracleInterface) {
        return OracleInterface(finder.getImplementationAddress(OracleInterfaces.Oracle));
    }

    function _getFinancialContractsAdminAddress() internal view returns (address) {
        return finder.getImplementationAddress(OracleInterfaces.FinancialContractsAdmin);
    }

    // Requests a price for `priceIdentifier` at `requestedTime` from the Oracle.
    function _requestOraclePrice(uint256 requestedTime) internal {
        OracleInterface oracle = _getOracle();
        oracle.requestPrice(priceIdentifier, requestedTime);
    }

    // Fetches a resolved Oracle price from the Oracle. Reverts if the Oracle hasn't resolved for this request.
    function _getOraclePrice(uint256 requestedTime) internal view returns (FixedPoint.Unsigned memory) {
        // Create an instance of the oracle and get the price. If the price is not resolved revert.
        OracleInterface oracle = _getOracle();
        require(oracle.hasPrice(priceIdentifier, requestedTime), "Unresolved oracle price");
        int256 oraclePrice = oracle.getPrice(priceIdentifier, requestedTime);

        // For now we don't want to deal with negative prices in positions.
        if (oraclePrice < 0) {
            oraclePrice = 0;
        }
        return FixedPoint.Unsigned(uint256(oraclePrice));
    }

    // Reset withdrawal request by setting the withdrawal request and withdrawal timestamp to 0.
    function _resetWithdrawalRequest(PositionData storage positionData) internal {
        positionData.withdrawalRequestAmount = FixedPoint.fromUnscaledUint(0);
        positionData.withdrawalRequestPassTimestamp = 0;
    }

    // Ensure individual and global consistency when increasing collateral balances. Returns the change to the position.
    function _incrementCollateralBalances(
        PositionData storage positionData,
        FixedPoint.Unsigned memory collateralAmount
    ) internal returns (FixedPoint.Unsigned memory) {
        _addCollateral(positionData.rawCollateral, collateralAmount);
        return _addCollateral(rawTotalPositionCollateral, collateralAmount);
    }

    // Ensure individual and global consistency when decrementing collateral balances. Returns the change to the
    // position. We elect to return the amount that the global collateral is decreased by, rather than the individual
    // position's collateral, because we need to maintain the invariant that the global collateral is always
    // <= the collateral owned by the contract to avoid reverts on withdrawals. The amount returned = amount withdrawn.
    function _decrementCollateralBalances(
        PositionData storage positionData,
        FixedPoint.Unsigned memory collateralAmount
    ) internal returns (FixedPoint.Unsigned memory) {
        _removeCollateral(positionData.rawCollateral, collateralAmount);
        return _removeCollateral(rawTotalPositionCollateral, collateralAmount);
    }

    // Ensure individual and global consistency when decrementing collateral balances. Returns the change to the position.
    // This function is similar to the _decrementCollateralBalances function except this function checks position GCR
    // between the decrements. This ensures that collateral removal will not leave the position undercollateralized.
    function _decrementCollateralBalancesCheckGCR(
        PositionData storage positionData,
        FixedPoint.Unsigned memory collateralAmount
    ) internal returns (FixedPoint.Unsigned memory) {
        _removeCollateral(positionData.rawCollateral, collateralAmount);
        require(_checkPositionCollateralization(positionData), "CR below GCR");
        return _removeCollateral(rawTotalPositionCollateral, collateralAmount);
    }

    // These internal functions are supposed to act identically to modifiers, but re-used modifiers
    // unnecessarily increase contract bytecode size.
    // source: https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6
    function _onlyOpenState() internal view {
        require(contractState == ContractState.Open, "Contract state is not OPEN");
    }

    function _onlyPreExpiration() internal view {
        require(getCurrentTime() < expirationTimestamp, "Only callable pre-expiry");
    }

    function _onlyPostExpiration() internal view {
        require(getCurrentTime() >= expirationTimestamp, "Only callable post-expiry");
    }

    function _onlyCollateralizedPosition(address sponsor) internal view {
        require(
            _getFeeAdjustedCollateral(positions[sponsor].rawCollateral).isGreaterThan(0),
            "Position has no collateral"
        );
    }

    // Note: This checks whether an already existing position has a pending withdrawal. This cannot be used on the
    // `create` method because it is possible that `create` is called on a new position (i.e. one without any collateral
    // or tokens outstanding) which would fail the `onlyCollateralizedPosition` modifier on `_getPositionData`.
    function _positionHasNoPendingWithdrawal(address sponsor) internal view {
        require(_getPositionData(sponsor).withdrawalRequestPassTimestamp == 0, "Pending withdrawal");
    }

    /****************************************
     *          PRIVATE FUNCTIONS          *
     ****************************************/

    function _checkPositionCollateralization(PositionData storage positionData) private view returns (bool) {
        return
            _checkCollateralization(
                _getFeeAdjustedCollateral(positionData.rawCollateral),
                positionData.tokensOutstanding
            );
    }

    // Checks whether the provided `collateral` and `numTokens` have a collateralization ratio above the global
    // collateralization ratio.
    function _checkCollateralization(FixedPoint.Unsigned memory collateral, FixedPoint.Unsigned memory numTokens)
        private
        view
        returns (bool)
    {
        FixedPoint.Unsigned memory global = _getCollateralizationRatio(
            _getFeeAdjustedCollateral(rawTotalPositionCollateral),
            totalTokensOutstanding
        );
        FixedPoint.Unsigned memory thisChange = _getCollateralizationRatio(collateral, numTokens);
        return !global.isGreaterThan(thisChange);
    }

    function _getCollateralizationRatio(FixedPoint.Unsigned memory collateral, FixedPoint.Unsigned memory numTokens)
        private
        pure
        returns (FixedPoint.Unsigned memory ratio)
    {
        if (!numTokens.isGreaterThan(0)) {
            return FixedPoint.fromUnscaledUint(0);
        } else {
            return collateral.div(numTokens);
        }
    }
}

// File: contracts/financial-templates/expiring-multiparty/Liquidatable.sol

pragma solidity ^0.6.0;






/**
 * @title Liquidatable
 * @notice Adds logic to a position-managing contract that enables callers to liquidate an undercollateralized position.
 * @dev The liquidation has a liveness period before expiring successfully, during which someone can "dispute" the
 * liquidation, which sends a price request to the relevant Oracle to settle the final collateralization ratio based on
 * a DVM price. The contract enforces dispute rewards in order to incentivize disputers to correctly dispute false
 * liquidations and compensate position sponsors who had their position incorrectly liquidated. Importantly, a
 * prospective disputer must deposit a dispute bond that they can lose in the case of an unsuccessful dispute.
 */
contract Liquidatable is PricelessPositionManager {
    using FixedPoint for FixedPoint.Unsigned;
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /****************************************
     *     LIQUIDATION DATA STRUCTURES      *
     ****************************************/

    // Because of the check in withdrawable(), the order of these enum values should not change.
    enum Status { Uninitialized, PreDispute, PendingDispute, DisputeSucceeded, DisputeFailed }

    struct LiquidationData {
        // Following variables set upon creation of liquidation:
        address sponsor; // Address of the liquidated position's sponsor
        address liquidator; // Address who created this liquidation
        Status state; // Liquidated (and expired or not), Pending a Dispute, or Dispute has resolved
        uint256 liquidationTime; // Time when liquidation is initiated, needed to get price from Oracle
        // Following variables determined by the position that is being liquidated:
        FixedPoint.Unsigned tokensOutstanding; // Synthetic tokens required to be burned by liquidator to initiate dispute
        FixedPoint.Unsigned lockedCollateral; // Collateral locked by contract and released upon expiry or post-dispute
        // Amount of collateral being liquidated, which could be different from
        // lockedCollateral if there were pending withdrawals at the time of liquidation
        FixedPoint.Unsigned liquidatedCollateral;
        // Unit value (starts at 1) that is used to track the fees per unit of collateral over the course of the liquidation.
        FixedPoint.Unsigned rawUnitCollateral;
        // Following variable set upon initiation of a dispute:
        address disputer; // Person who is disputing a liquidation
        // Following variable set upon a resolution of a dispute:
        FixedPoint.Unsigned settlementPrice; // Final price as determined by an Oracle following a dispute
        FixedPoint.Unsigned finalFee;
    }

    // Define the contract's constructor parameters as a struct to enable more variables to be specified.
    // This is required to enable more params, over and above Solidity's limits.
    struct ConstructorParams {
        // Params for PricelessPositionManager only.
        uint256 expirationTimestamp;
        uint256 withdrawalLiveness;
        address collateralAddress;
        address finderAddress;
        address tokenFactoryAddress;
        address timerAddress;
        bytes32 priceFeedIdentifier;
        string syntheticName;
        string syntheticSymbol;
        FixedPoint.Unsigned minSponsorTokens;
        // Params specifically for Liquidatable.
        uint256 liquidationLiveness;
        FixedPoint.Unsigned collateralRequirement;
        FixedPoint.Unsigned disputeBondPct;
        FixedPoint.Unsigned sponsorDisputeRewardPct;
        FixedPoint.Unsigned disputerDisputeRewardPct;
    }

    // Liquidations are unique by ID per sponsor
    mapping(address => LiquidationData[]) public liquidations;

    // Total collateral in liquidation.
    FixedPoint.Unsigned public rawLiquidationCollateral;

    // Immutable contract parameters:
    // Amount of time for pending liquidation before expiry.
    uint256 public liquidationLiveness;
    // Required collateral:TRV ratio for a position to be considered sufficiently collateralized.
    FixedPoint.Unsigned public collateralRequirement;
    // Percent of a Liquidation/Position's lockedCollateral to be deposited by a potential disputer
    // Represented as a multiplier, for example 1.5e18 = "150%" and 0.05e18 = "5%"
    FixedPoint.Unsigned public disputeBondPct;
    // Percent of oraclePrice paid to sponsor in the Disputed state (i.e. following a successful dispute)
    // Represented as a multiplier, see above.
    FixedPoint.Unsigned public sponsorDisputeRewardPct;
    // Percent of oraclePrice paid to disputer in the Disputed state (i.e. following a successful dispute)
    // Represented as a multiplier, see above.
    FixedPoint.Unsigned public disputerDisputeRewardPct;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event LiquidationCreated(
        address indexed sponsor,
        address indexed liquidator,
        uint256 indexed liquidationId,
        uint256 tokensOutstanding,
        uint256 lockedCollateral,
        uint256 liquidatedCollateral,
        uint256 liquidationTime
    );
    event LiquidationDisputed(
        address indexed sponsor,
        address indexed liquidator,
        address indexed disputer,
        uint256 liquidationId,
        uint256 disputeBondAmount
    );
    event DisputeSettled(
        address indexed caller,
        address indexed sponsor,
        address indexed liquidator,
        address disputer,
        uint256 liquidationId,
        bool disputeSucceeded
    );
    event LiquidationWithdrawn(
        address indexed caller,
        uint256 withdrawalAmount,
        Status indexed liquidationStatus,
        uint256 settlementPrice
    );

    /****************************************
     *              MODIFIERS               *
     ****************************************/

    modifier disputable(uint256 liquidationId, address sponsor) {
        _disputable(liquidationId, sponsor);
        _;
    }

    modifier withdrawable(uint256 liquidationId, address sponsor) {
        _withdrawable(liquidationId, sponsor);
        _;
    }

    /**
     * @notice Constructs the liquidatable contract.
     * @param params struct to define input parameters for construction of Liquidatable. Some params
     * are fed directly into the PricelessPositionManager's constructor within the inheritance tree.
     */
    constructor(ConstructorParams memory params)
        public
        PricelessPositionManager(
            params.expirationTimestamp,
            params.withdrawalLiveness,
            params.collateralAddress,
            params.finderAddress,
            params.priceFeedIdentifier,
            params.syntheticName,
            params.syntheticSymbol,
            params.tokenFactoryAddress,
            params.minSponsorTokens,
            params.timerAddress
        )
        nonReentrant()
    {
        require(params.collateralRequirement.isGreaterThan(1), "CR is more than 100%");
        require(
            params.sponsorDisputeRewardPct.add(params.disputerDisputeRewardPct).isLessThan(1),
            "Rewards are more than 100%"
        );

        // Set liquidatable specific variables.
        liquidationLiveness = params.liquidationLiveness;
        collateralRequirement = params.collateralRequirement;
        disputeBondPct = params.disputeBondPct;
        sponsorDisputeRewardPct = params.sponsorDisputeRewardPct;
        disputerDisputeRewardPct = params.disputerDisputeRewardPct;
    }

    /****************************************
     *        LIQUIDATION FUNCTIONS         *
     ****************************************/

    /**
     * @notice Liquidates the sponsor's position if the caller has enough
     * synthetic tokens to retire the position's outstanding tokens.
     * @dev This method generates an ID that will uniquely identify liquidation for the sponsor. This contract must be
     * approved to spend at least `tokensLiquidated` of `tokenCurrency` and at least `finalFeeBond` of `collateralCurrency`.
     * @param sponsor address of the sponsor to liquidate.
     * @param minCollateralPerToken abort the liquidation if the position's collateral per token is below this value.
     * @param maxCollateralPerToken abort the liquidation if the position's collateral per token exceeds this value.
     * @param maxTokensToLiquidate max number of tokens to liquidate.
     * @param deadline abort the liquidation if the transaction is mined after this timestamp.
     * @return liquidationId ID of the newly created liquidation.
     * @return tokensLiquidated amount of synthetic tokens removed and liquidated from the `sponsor`'s position.
     * @return finalFeeBond amount of collateral to be posted by liquidator and returned if not disputed successfully.
     */
    function createLiquidation(
        address sponsor,
        FixedPoint.Unsigned calldata minCollateralPerToken,
        FixedPoint.Unsigned calldata maxCollateralPerToken,
        FixedPoint.Unsigned calldata maxTokensToLiquidate,
        uint256 deadline
    )
        external
        fees()
        onlyPreExpiration()
        nonReentrant()
        returns (
            uint256 liquidationId,
            FixedPoint.Unsigned memory tokensLiquidated,
            FixedPoint.Unsigned memory finalFeeBond
        )
    {
        // Check that this transaction was mined pre-deadline.
        require(getCurrentTime() <= deadline, "Mined after deadline");

        // Retrieve Position data for sponsor
        PositionData storage positionToLiquidate = _getPositionData(sponsor);

        tokensLiquidated = FixedPoint.min(maxTokensToLiquidate, positionToLiquidate.tokensOutstanding);

        // Starting values for the Position being liquidated. If withdrawal request amount is > position's collateral,
        // then set this to 0, otherwise set it to (startCollateral - withdrawal request amount).
        FixedPoint.Unsigned memory startCollateral = _getFeeAdjustedCollateral(positionToLiquidate.rawCollateral);
        FixedPoint.Unsigned memory startCollateralNetOfWithdrawal = FixedPoint.fromUnscaledUint(0);
        if (positionToLiquidate.withdrawalRequestAmount.isLessThanOrEqual(startCollateral)) {
            startCollateralNetOfWithdrawal = startCollateral.sub(positionToLiquidate.withdrawalRequestAmount);
        }

        // Scoping to get rid of a stack too deep error.
        {
            FixedPoint.Unsigned memory startTokens = positionToLiquidate.tokensOutstanding;

            // The Position's collateralization ratio must be between [minCollateralPerToken, maxCollateralPerToken].
            // maxCollateralPerToken >= startCollateralNetOfWithdrawal / startTokens.
            require(
                maxCollateralPerToken.mul(startTokens).isGreaterThanOrEqual(startCollateralNetOfWithdrawal),
                "CR is more than max liq. price"
            );
            // minCollateralPerToken >= startCollateralNetOfWithdrawal / startTokens.
            require(
                minCollateralPerToken.mul(startTokens).isLessThanOrEqual(startCollateralNetOfWithdrawal),
                "CR is less than min liq. price"
            );
        }

        // Compute final fee at time of liquidation.
        finalFeeBond = _computeFinalFees();

        // These will be populated within the scope below.
        FixedPoint.Unsigned memory lockedCollateral;
        FixedPoint.Unsigned memory liquidatedCollateral;

        // Scoping to get rid of a stack too deep error.
        {
            FixedPoint.Unsigned memory ratio = tokensLiquidated.div(positionToLiquidate.tokensOutstanding);

            // The actual amount of collateral that gets moved to the liquidation.
            lockedCollateral = startCollateral.mul(ratio);

            // For purposes of disputes, it's actually this liquidatedCollateral value that's used. This value is net of
            // withdrawal requests.
            liquidatedCollateral = startCollateralNetOfWithdrawal.mul(ratio);

            // Part of the withdrawal request is also removed. Ideally:
            // liquidatedCollateral + withdrawalAmountToRemove = lockedCollateral.
            FixedPoint.Unsigned memory withdrawalAmountToRemove = positionToLiquidate.withdrawalRequestAmount.mul(
                ratio
            );
            _reduceSponsorPosition(sponsor, tokensLiquidated, lockedCollateral, withdrawalAmountToRemove);
        }

        // Add to the global liquidation collateral count.
        _addCollateral(rawLiquidationCollateral, lockedCollateral.add(finalFeeBond));

        // Construct liquidation object.
        // Note: All dispute-related values are zeroed out until a dispute occurs. liquidationId is the index of the new
        // LiquidationData that is pushed into the array, which is equal to the current length of the array pre-push.
        liquidationId = liquidations[sponsor].length;
        liquidations[sponsor].push(
            LiquidationData({
                sponsor: sponsor,
                liquidator: msg.sender,
                state: Status.PreDispute,
                liquidationTime: getCurrentTime(),
                tokensOutstanding: tokensLiquidated,
                lockedCollateral: lockedCollateral,
                liquidatedCollateral: liquidatedCollateral,
                rawUnitCollateral: _convertToRawCollateral(FixedPoint.fromUnscaledUint(1)),
                disputer: address(0),
                settlementPrice: FixedPoint.fromUnscaledUint(0),
                finalFee: finalFeeBond
            })
        );

        emit LiquidationCreated(
            sponsor,
            msg.sender,
            liquidationId,
            tokensLiquidated.rawValue,
            lockedCollateral.rawValue,
            liquidatedCollateral.rawValue,
            getCurrentTime()
        );

        // Destroy tokens
        tokenCurrency.safeTransferFrom(msg.sender, address(this), tokensLiquidated.rawValue);
        tokenCurrency.burn(tokensLiquidated.rawValue);

        // Pull final fee from liquidator.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), finalFeeBond.rawValue);
    }

    /**
     * @notice Disputes a liquidation, if the caller has enough collateral to post a dispute bond
     * and pay a fixed final fee charged on each price request.
     * @dev Can only dispute a liquidation before the liquidation expires and if there are no other pending disputes.
     * This contract must be approved to spend at least the dispute bond amount of `collateralCurrency`. This dispute
     * bond amount is calculated from `disputeBondPct` times the collateral in the liquidation.
     * @param liquidationId of the disputed liquidation.
     * @param sponsor the address of the sponsor whose liquidation is being disputed.
     * @return totalPaid amount of collateral charged to disputer (i.e. final fee bond + dispute bond).
     */
    function dispute(uint256 liquidationId, address sponsor)
        external
        disputable(liquidationId, sponsor)
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory totalPaid)
    {
        LiquidationData storage disputedLiquidation = _getLiquidationData(sponsor, liquidationId);

        // Multiply by the unit collateral so the dispute bond is a percentage of the locked collateral after fees.
        FixedPoint.Unsigned memory disputeBondAmount = disputedLiquidation.lockedCollateral.mul(disputeBondPct).mul(
            _getFeeAdjustedCollateral(disputedLiquidation.rawUnitCollateral)
        );
        _addCollateral(rawLiquidationCollateral, disputeBondAmount);

        // Request a price from DVM. Liquidation is pending dispute until DVM returns a price.
        disputedLiquidation.state = Status.PendingDispute;
        disputedLiquidation.disputer = msg.sender;

        // Enqueue a request with the DVM.
        _requestOraclePrice(disputedLiquidation.liquidationTime);

        emit LiquidationDisputed(
            sponsor,
            disputedLiquidation.liquidator,
            msg.sender,
            liquidationId,
            disputeBondAmount.rawValue
        );
        totalPaid = disputeBondAmount.add(disputedLiquidation.finalFee);

        // Pay the final fee for requesting price from the DVM.
        _payFinalFees(msg.sender, disputedLiquidation.finalFee);

        // Transfer the dispute bond amount from the caller to this contract.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), disputeBondAmount.rawValue);
    }

    /**
     * @notice After a dispute has settled or after a non-disputed liquidation has expired,
     * the sponsor, liquidator, and/or disputer can call this method to receive payments.
     * @dev If the dispute SUCCEEDED: the sponsor, liquidator, and disputer are eligible for payment.
     * If the dispute FAILED: only the liquidator can receive payment.
     * Once all collateral is withdrawn, delete the liquidation data.
     * @param liquidationId uniquely identifies the sponsor's liquidation.
     * @param sponsor address of the sponsor associated with the liquidation.
     * @return amountWithdrawn the total amount of underlying returned from the liquidation.
     */
    function withdrawLiquidation(uint256 liquidationId, address sponsor)
        public
        withdrawable(liquidationId, sponsor)
        fees()
        nonReentrant()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        require(
            (msg.sender == liquidation.disputer) ||
                (msg.sender == liquidation.liquidator) ||
                (msg.sender == liquidation.sponsor),
            "Caller cannot withdraw rewards"
        );

        // Settles the liquidation if necessary. This call will revert if the price has not resolved yet.
        _settle(liquidationId, sponsor);

        // Calculate rewards as a function of the TRV.
        // Note: all payouts are scaled by the unit collateral value so all payouts are charged the fees pro rata.
        FixedPoint.Unsigned memory feeAttenuation = _getFeeAdjustedCollateral(liquidation.rawUnitCollateral);
        FixedPoint.Unsigned memory tokenRedemptionValue = liquidation
            .tokensOutstanding
            .mul(liquidation.settlementPrice)
            .mul(feeAttenuation);
        FixedPoint.Unsigned memory collateral = liquidation.lockedCollateral.mul(feeAttenuation);
        FixedPoint.Unsigned memory disputerDisputeReward = disputerDisputeRewardPct.mul(tokenRedemptionValue);
        FixedPoint.Unsigned memory sponsorDisputeReward = sponsorDisputeRewardPct.mul(tokenRedemptionValue);
        FixedPoint.Unsigned memory disputeBondAmount = collateral.mul(disputeBondPct);
        FixedPoint.Unsigned memory finalFee = liquidation.finalFee.mul(feeAttenuation);

        // There are three main outcome states: either the dispute succeeded, failed or was not updated.
        // Based on the state, different parties of a liquidation can withdraw different amounts.
        // Once a caller has been paid their address deleted from the struct.
        // This prevents them from being paid multiple from times the same liquidation.
        FixedPoint.Unsigned memory withdrawalAmount = FixedPoint.fromUnscaledUint(0);
        if (liquidation.state == Status.DisputeSucceeded) {
            // If the dispute is successful then all three users can withdraw from the contract.
            if (msg.sender == liquidation.disputer) {
                // Pay DISPUTER: disputer reward + dispute bond + returned final fee
                FixedPoint.Unsigned memory payToDisputer = disputerDisputeReward.add(disputeBondAmount).add(finalFee);
                withdrawalAmount = withdrawalAmount.add(payToDisputer);
                delete liquidation.disputer;
            }

            if (msg.sender == liquidation.sponsor) {
                // Pay SPONSOR: remaining collateral (collateral - TRV) + sponsor reward
                FixedPoint.Unsigned memory remainingCollateral = collateral.sub(tokenRedemptionValue);
                FixedPoint.Unsigned memory payToSponsor = sponsorDisputeReward.add(remainingCollateral);
                withdrawalAmount = withdrawalAmount.add(payToSponsor);
                delete liquidation.sponsor;
            }

            if (msg.sender == liquidation.liquidator) {
                // Pay LIQUIDATOR: TRV - dispute reward - sponsor reward
                // If TRV > Collateral, then subtract rewards from collateral
                // NOTE: This should never be below zero since we prevent (sponsorDisputePct+disputerDisputePct) >= 0 in
                // the constructor when these params are set.
                FixedPoint.Unsigned memory payToLiquidator = tokenRedemptionValue.sub(sponsorDisputeReward).sub(
                    disputerDisputeReward
                );
                withdrawalAmount = withdrawalAmount.add(payToLiquidator);
                delete liquidation.liquidator;
            }

            // Free up space once all collateral is withdrawn by removing the liquidation object from the array.
            if (
                liquidation.disputer == address(0) &&
                liquidation.sponsor == address(0) &&
                liquidation.liquidator == address(0)
            ) {
                delete liquidations[sponsor][liquidationId];
            }
            // In the case of a failed dispute only the liquidator can withdraw.
        } else if (liquidation.state == Status.DisputeFailed && msg.sender == liquidation.liquidator) {
            // Pay LIQUIDATOR: collateral + dispute bond + returned final fee
            withdrawalAmount = collateral.add(disputeBondAmount).add(finalFee);
            delete liquidations[sponsor][liquidationId];
            // If the state is pre-dispute but time has passed liveness then there was no dispute. We represent this
            // state as a dispute failed and the liquidator can withdraw.
        } else if (liquidation.state == Status.PreDispute && msg.sender == liquidation.liquidator) {
            // Pay LIQUIDATOR: collateral + returned final fee
            withdrawalAmount = collateral.add(finalFee);
            delete liquidations[sponsor][liquidationId];
        }
        require(withdrawalAmount.isGreaterThan(0), "Invalid withdrawal amount");

        // Decrease the total collateral held in liquidatable by the amount withdrawn.
        amountWithdrawn = _removeCollateral(rawLiquidationCollateral, withdrawalAmount);

        emit LiquidationWithdrawn(
            msg.sender,
            amountWithdrawn.rawValue,
            liquidation.state,
            liquidation.settlementPrice.rawValue
        );

        // Transfer amount withdrawn from this contract to the caller.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);

        return amountWithdrawn;
    }

    /**
     * @notice Gets all liquidation information for a given sponsor address.
     * @param sponsor address of the position sponsor.
     * @return liquidationData array of all liquidation information for the given sponsor address.
     */
    function getLiquidations(address sponsor)
        external
        view
        nonReentrantView()
        returns (LiquidationData[] memory liquidationData)
    {
        return liquidations[sponsor];
    }

    /****************************************
     *          INTERNAL FUNCTIONS          *
     ****************************************/

    // This settles a liquidation if it is in the PendingDispute state. If not, it will immediately return.
    // If the liquidation is in the PendingDispute state, but a price is not available, this will revert.
    function _settle(uint256 liquidationId, address sponsor) internal {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);

        // Settlement only happens when state == PendingDispute and will only happen once per liquidation.
        // If this liquidation is not ready to be settled, this method should return immediately.
        if (liquidation.state != Status.PendingDispute) {
            return;
        }

        // Get the returned price from the oracle. If this has not yet resolved will revert.
        liquidation.settlementPrice = _getOraclePrice(liquidation.liquidationTime);

        // Find the value of the tokens in the underlying collateral.
        FixedPoint.Unsigned memory tokenRedemptionValue = liquidation.tokensOutstanding.mul(
            liquidation.settlementPrice
        );

        // The required collateral is the value of the tokens in underlying * required collateral ratio.
        FixedPoint.Unsigned memory requiredCollateral = tokenRedemptionValue.mul(collateralRequirement);

        // If the position has more than the required collateral it is solvent and the dispute is valid(liquidation is invalid)
        // Note that this check uses the liquidatedCollateral not the lockedCollateral as this considers withdrawals.
        bool disputeSucceeded = liquidation.liquidatedCollateral.isGreaterThanOrEqual(requiredCollateral);
        liquidation.state = disputeSucceeded ? Status.DisputeSucceeded : Status.DisputeFailed;

        emit DisputeSettled(
            msg.sender,
            sponsor,
            liquidation.liquidator,
            liquidation.disputer,
            liquidationId,
            disputeSucceeded
        );
    }

    function _pfc() internal override view returns (FixedPoint.Unsigned memory) {
        return super._pfc().add(_getFeeAdjustedCollateral(rawLiquidationCollateral));
    }

    function _getLiquidationData(address sponsor, uint256 liquidationId)
        internal
        view
        returns (LiquidationData storage liquidation)
    {
        LiquidationData[] storage liquidationArray = liquidations[sponsor];

        // Revert if the caller is attempting to access an invalid liquidation
        // (one that has never been created or one has never been initialized).
        require(
            liquidationId < liquidationArray.length && liquidationArray[liquidationId].state != Status.Uninitialized,
            "Invalid liquidation ID"
        );
        return liquidationArray[liquidationId];
    }

    function _getLiquidationExpiry(LiquidationData storage liquidation) internal view returns (uint256) {
        return liquidation.liquidationTime.add(liquidationLiveness);
    }

    // These internal functions are supposed to act identically to modifiers, but re-used modifiers
    // unnecessarily increase contract bytecode size.
    // source: https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6
    function _disputable(uint256 liquidationId, address sponsor) internal view {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        require(
            (getCurrentTime() < _getLiquidationExpiry(liquidation)) && (liquidation.state == Status.PreDispute),
            "Liquidation not disputable"
        );
    }

    function _withdrawable(uint256 liquidationId, address sponsor) internal view {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        Status state = liquidation.state;

        // Must be disputed or the liquidation has passed expiry.
        require(
            (state > Status.PreDispute) ||
                ((_getLiquidationExpiry(liquidation) <= getCurrentTime()) && (state == Status.PreDispute)),
            "Liquidation not withdrawable"
        );
    }
}

// File: contracts/financial-templates/expiring-multiparty/ExpiringMultiParty.sol

pragma solidity ^0.6.0;



/**
 * @title Expiring Multi Party.
 * @notice Convenient wrapper for Liquidatable.
 */
contract ExpiringMultiParty is Liquidatable {
    /**
     * @notice Constructs the ExpiringMultiParty contract.
     * @param params struct to define input parameters for construction of Liquidatable. Some params
     * are fed directly into the PricelessPositionManager's constructor within the inheritance tree.
     */
    constructor(ConstructorParams memory params)
        public
        Liquidatable(params)
    // Note: since there is no logic here, there is no need to add a re-entrancy guard.
    {

    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"components":[{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"},{"internalType":"uint256","name":"withdrawalLiveness","type":"uint256"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"finderAddress","type":"address"},{"internalType":"address","name":"tokenFactoryAddress","type":"address"},{"internalType":"address","name":"timerAddress","type":"address"},{"internalType":"bytes32","name":"priceFeedIdentifier","type":"bytes32"},{"internalType":"string","name":"syntheticName","type":"string"},{"internalType":"string","name":"syntheticSymbol","type":"string"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"minSponsorTokens","type":"tuple"},{"internalType":"uint256","name":"liquidationLiveness","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralRequirement","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"disputeBondPct","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"sponsorDisputeRewardPct","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"disputerDisputeRewardPct","type":"tuple"}],"internalType":"struct Liquidatable.ConstructorParams","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"ContractExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"address","name":"disputer","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidationId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"disputeSucceeded","type":"bool"}],"name":"DisputeSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"originalExpirationTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shutdownTimestamp","type":"uint256"}],"name":"EmergencyShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"}],"name":"EndedSponsorPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FinalFeesPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidationId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensOutstanding","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidatedCollateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationTime","type":"uint256"}],"name":"LiquidationCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidationId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"disputeBondAmount","type":"uint256"}],"name":"LiquidationDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawalAmount","type":"uint256"},{"indexed":true,"internalType":"enum Liquidatable.Status","name":"liquidationStatus","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"settlementPrice","type":"uint256"}],"name":"LiquidationWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"}],"name":"NewSponsor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"PositionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"regularFee","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"lateFee","type":"uint256"}],"name":"RegularFeesPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSponsor","type":"address"}],"name":"RequestTransferPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSponsor","type":"address"}],"name":"RequestTransferPositionCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSponsor","type":"address"},{"indexed":true,"internalType":"address","name":"newSponsor","type":"address"}],"name":"RequestTransferPositionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"RequestWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"RequestWithdrawalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"RequestWithdrawalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralReturned","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokensBurned","type":"uint256"}],"name":"SettleExpiredPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sponsor","type":"address"},{"indexed":true,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"cancelTransferPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralCurrency","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralRequirement","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractState","outputs":[{"internalType":"enum PricelessPositionManager.ContractState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"numTokens","type":"tuple"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sponsor","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"minCollateralPerToken","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"maxCollateralPerToken","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"maxTokensToLiquidate","type":"tuple"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"createLiquidation","outputs":[{"internalType":"uint256","name":"liquidationId","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"tokensLiquidated","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"finalFeeBond","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cumulativeFeeMultiplier","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sponsor","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"}],"name":"depositTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationId","type":"uint256"},{"internalType":"address","name":"sponsor","type":"address"}],"name":"dispute","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"totalPaid","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disputeBondPct","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disputerDisputeRewardPct","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expirationTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expiryPrice","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finder","outputs":[{"internalType":"contract FinderInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sponsor","type":"address"}],"name":"getCollateral","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sponsor","type":"address"}],"name":"getLiquidations","outputs":[{"components":[{"internalType":"address","name":"sponsor","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"enum Liquidatable.Status","name":"state","type":"uint8"},{"internalType":"uint256","name":"liquidationTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"tokensOutstanding","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"lockedCollateral","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"liquidatedCollateral","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"rawUnitCollateral","type":"tuple"},{"internalType":"address","name":"disputer","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"settlementPrice","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"finalFee","type":"tuple"}],"internalType":"struct Liquidatable.LiquidationData[]","name":"liquidationData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidationLiveness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"liquidations","outputs":[{"internalType":"address","name":"sponsor","type":"address"},{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"enum Liquidatable.Status","name":"state","type":"uint8"},{"internalType":"uint256","name":"liquidationTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"tokensOutstanding","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"lockedCollateral","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"liquidatedCollateral","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"rawUnitCollateral","type":"tuple"},{"internalType":"address","name":"disputer","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"settlementPrice","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"finalFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSponsorTokens","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payRegularFees","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"totalPaid","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pfc","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"positions","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"tokensOutstanding","type":"tuple"},{"internalType":"uint256","name":"withdrawalRequestPassTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"withdrawalRequestAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"rawCollateral","type":"tuple"},{"internalType":"uint256","name":"transferPositionRequestPassTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rawLiquidationCollateral","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rawTotalPositionCollateral","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"numTokens","type":"tuple"}],"name":"redeem","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amountWithdrawn","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"remargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestTransferPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"}],"name":"requestWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleExpired","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amountWithdrawn","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sponsorDisputeRewardPct","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCurrency","outputs":[{"internalType":"contract ExpandedIERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPositionCollateral","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"totalCollateral","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensOutstanding","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSponsorAddress","type":"address"}],"name":"transferPositionPassedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"collateralAmount","type":"tuple"}],"name":"withdraw","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amountWithdrawn","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationId","type":"uint256"},{"internalType":"address","name":"sponsor","type":"address"}],"name":"withdrawLiquidation","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amountWithdrawn","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawPassedRequest","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amountWithdrawn","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalLiveness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80635f1af1ca1161015c5780639ff4dea8116100ce578063bda02e7711610087578063bda02e77146104ec578063c13f62e1146104f4578063d1e92c11146104fc578063dd0eef3d1461050f578063edfa9a9b14610517578063fcccedc71461051f5761028a565b80639ff4dea81461048e578063a1c4d1e714610496578063a765fbea146104b6578063b795f0d4146104c9578063b9a3c84c146104d1578063bc121630146104d95761028a565b806385209ee01161012057806385209ee0146104465780638c382eb21461045b57806392120aec14610463578063975236611461046b5780639b56d6c9146104735780639f43ddd2146104865761028a565b80635f1af1ca146104085780636ba2f9921461041b5780637048594b1461042e57806379599f961461043657806381a10ae11461043e5761028a565b8063360598e11161020057806348e30c3f116101b957806348e30c3f1461038f5780634f8c48471461039757806350f49846146103c157806355f57510146103c95780635617151c146103ed5780635ee0fe32146104005761028a565b8063360598e11461034957806336980f581461035c578063391fe4e2146103645780633cb6ce831461036c5780633ee7a5ce1461037457806343e4771b146103875761028a565b806322f8e5661161025257806322f8e566146102e757806325ed4dd8146102fa57806329cb924d1461031c5780632d5436cf1461032457806333a46ca21461032c5780633403c2fc146103415761028a565b80630c9229ca1461028f5780630de15fd9146102ad57806318928a0c146102c25780631c39c38d146102d757806322611280146102df575b600080fd5b610297610527565b6040516102a491906145ec565b60405180910390f35b6102b561052d565b6040516102a491906143c2565b6102d56102d036600461422b565b61053c565b005b6102b561061d565b6102d561062c565b6102d56102f5366004614340565b6106ba565b61030d6103083660046141cb565b610734565b6040516102a493929190614daf565b610297610c9a565b610297610d3e565b610334610d44565b6040516102a49190614d81565b6102d5610e9d565b610334610357366004614358565b610f61565b6102d5611598565b61029761165c565b610334611662565b6103346103823660046142c3565b611949565b610334611a22565b610297611a50565b6103aa6103a5366004614260565b611a56565b6040516102a49b9a99989796959493929190614409565b610297611b1a565b6103dc6103d7366004614193565b611b20565b6040516102a4959493929190614d8b565b6102d56103fb366004614193565b611b6d565b610297611d47565b6103346104163660046142c3565b611d4d565b6102d56104293660046142f9565b611fdf565b6102b5612233565b6102d5612242565b6103346122c7565b61044e6122df565b6040516102a49190614603565b6102976122e8565b6102976122ee565b6102976122f4565b610334610481366004614193565b6122fa565b610297612345565b61029761234b565b6104a96104a4366004614193565b612351565b6040516102a491906144dd565b6103346104c4366004614358565b6124af565b6102d5612648565b6102b56126cd565b6102d56104e73660046142c3565b6126dc565b6102d56127e3565b610297612803565b6102d561050a3660046142c3565b612809565b610297612816565b61029761281c565b610334612822565b60075481565b6001546001600160a01b031681565b610544612bfd565b8161054e81612c25565b610556611662565b5061055f612c4f565b610567612c78565b61057882600063ffffffff612c8716565b61059d5760405162461bcd60e51b8152600401610594906148b9565b60405180910390fd5b60006105a884612c9e565b90506105b48184612cc6565b5082516040516001600160a01b038616907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90600090a3825160015461060f916001600160a01b03909116903390309063ffffffff612cee16565b50610618612d4c565b505050565b6000546001600160a01b031681565b610634612bfd565b61063c612c4f565b610644612c78565b600061064f33612c9e565b90508060010154600014156106765760405162461bcd60e51b815260040161059490614d52565b600281015460405133907f74d8a3658feb89d1a5c335229bbbfc3bbcfaf492769feb7aa4cd2d92efeaf69190600090a36106af81612d61565b506106b8612d4c565b565b6000546001600160a01b03166106cf57600080fd5b60005460405163117c72b360e11b81526001600160a01b03909116906322f8e566906106ff9084906004016145ec565b600060405180830381600087803b15801561071957600080fd5b505af115801561072d573d6000803e3d6000fd5b5050505050565b600061073e614125565b610746614125565b61074e611662565b50610757612bfd565b61075f612c4f565b610767612c78565b83610770610c9a565b111561078e5760405162461bcd60e51b815260040161059490614753565b600061079989612c9e565b90506107c16107ad368890038801886142c3565b604080516020810190915283548152612d7b565b92506107cb614125565b6040805160208101909152600383015481526107e690612d99565b90506107f0614125565b6107fa6000612dc2565b60408051602081019091526002850154815290915061081f908363ffffffff612df616565b1561084a5760408051602081019091526002840154815261084790839063ffffffff612dfe16565b90505b610852614125565b506040805160208101909152835481526108918261088583610879368f90038f018f6142c3565b9063ffffffff612e3016565b9063ffffffff612e7316565b6108ad5760405162461bcd60e51b815260040161059490614a9d565b6108d2826108c6838e80360381019061087991906142c3565b9063ffffffff612df616565b6108ee5760405162461bcd60e51b815260040161059490614bd6565b506108f7612e7b565b9350610901614125565b610909614125565b610911614125565b60408051602081019091528654815261093190899063ffffffff612f1616565b9050610943858263ffffffff612e3016565b9250610955848263ffffffff612e3016565b915061095f614125565b604080516020810190915260028801548152610981908363ffffffff612e3016565b905061098f8f8a8684612f57565b506109ac905060106109a7848963ffffffff61308c16565b6130b5565b506001600160a01b038d166000818152600f602090815260409182902080548351610160810185529485523392850192909252909a5091908101600181526020016109f5610c9a565b8152602001898152602001848152602001838152602001610a1e610a196001612dc2565b61313c565b815260200160006001600160a01b03168152602001610a3d6000612dc2565b815260209081018990528254600180820185556000948552938290208351600a9092020180546001600160a01b03199081166001600160a01b0393841617825592840151948101805490931694909116939093178082556040830151929392919060ff60a01b1916600160a01b836004811115610ab657fe5b02179055506060820151816002015560808201518160030160008201518160000155505060a08201518160040160008201518160000155505060c08201518160050160008201518160000155505060e0820151816006016000820151816000015550506101008201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101208201518160080160008201518160000155505061014082015181600901600082015181600001555050505087336001600160a01b03168e6001600160a01b03167f39b4371645b4132767fd76a1aad3108ff95c20d7b687b24d171555f5459a75978a6000015186600001518660000151610bc2610c9a565b604051610bd29493929190614ddc565b60405180910390a48651600954610bfe916001600160a01b03909116903390309063ffffffff612cee16565b6009548751604051630852cd8d60e31b81526001600160a01b03909216916342966c6891610c2e916004016145ec565b600060405180830381600087803b158015610c4857600080fd5b505af1158015610c5c573d6000803e3d6000fd5b50508751600154610c8293506001600160a01b031691503390309063ffffffff612cee16565b5050505050610c8f612d4c565b955095509592505050565b600080546001600160a01b031615610d38576000809054906101000a90046001600160a01b03166001600160a01b03166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cf957600080fd5b505afa158015610d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3191906142ab565b9050610d3b565b50425b90565b60115481565b610d4c614125565b610d54612bfd565b610d5c611662565b50610d65612c4f565b610d6d612c78565b6000610d7833612c9e565b90508060010154600014158015610d9a5750610d92610c9a565b816001015411155b610db65760405162461bcd60e51b8152600401610594906149cb565b610dbe614125565b5060408051602080820183526002840154825282519081019092526003830154825290610e0c90610dee90612d99565b6040805160208101909152600285015481529063ffffffff61316516565b15610e2f57604080516020810190915260038301548152610e2c90612d99565b90505b610e39828261316c565b9250610e4482612d61565b8251600154610e66916001600160a01b0390911690339063ffffffff61318d16565b825160405133907fc86c3298cb79f486674dca87d9247e88b76146160e7d412cc59b26b14c358a6890600090a35050610d3b612d4c565b610ea5612bfd565b610ead6131ac565b610eb5612c4f565b610ebd612c78565b610ec56131dc565b6001600160a01b0316336001600160a01b031614610ef55760405162461bcd60e51b815260040161059490614a39565b6005805460ff19166001179055600b54610f0d610c9a565b600b819055610f1b9061327d565b600b5460405133917fd39eeb7157d9c446579a0893ecf9ecd87d1f466cdb270c6a189cf38ca1e30f4891610f509185916145f5565b60405180910390a2506106b8612d4c565b610f69614125565b8282610f7582826132ef565b610f7d611662565b50610f86612c4f565b610f8e612c78565b6000610f9a8587613369565b60078101549091506001600160a01b0316331480610fc4575060018101546001600160a01b031633145b80610fd8575080546001600160a01b031633145b610ff45760405162461bcd60e51b8152600401610594906146b8565b610ffe8686613406565b611006614125565b60408051602081019091526006830154815261102190612d99565b905061102b614125565b604080516020808201835260088601548252825190810190925260038501548252611062918491610879919063ffffffff612e3016565b905061106c614125565b60408051602081019091526004850154815261108e908463ffffffff612e3016565b9050611098614125565b604080516020810190915260155481526110b8908463ffffffff612e3016565b90506110c2614125565b604080516020810190915260145481526110e2908563ffffffff612e3016565b90506110ec614125565b6040805160208101909152601354815261110d90859063ffffffff612e3016565b9050611117614125565b604080516020810190915260098901548152611139908863ffffffff612e3016565b9050611143614125565b61114d6000612dc2565b9050600360018a0154600160a01b900460ff16600481111561116b57fe5b14156113775760078901546001600160a01b03163314156111d65761118e614125565b6111ae836111a2888763ffffffff61308c16565b9063ffffffff61308c16565b90506111c0828263ffffffff61308c16565b60078b0180546001600160a01b03191690559150505b88546001600160a01b031633141561123f576111f0614125565b611200878963ffffffff612dfe16565b905061120a614125565b61121a868363ffffffff61308c16565b905061122c838263ffffffff61308c16565b8b546001600160a01b0319168c55925050505b60018901546001600160a01b03163314156112a45761125c614125565b61127c866112708a8863ffffffff612dfe16565b9063ffffffff612dfe16565b905061128e828263ffffffff61308c16565b60018b0180546001600160a01b03191690559150505b60078901546001600160a01b03161580156112c7575088546001600160a01b0316155b80156112de575060018901546001600160a01b0316155b15611372576001600160a01b038d166000908152600f6020526040902080548f90811061130757fe5b600091825260208220600a9091020180546001600160a01b031990811682556001820180546001600160a81b03191690556002820183905560038201839055600482018390556005820183905560068201839055600782018054909116905560088101829055600901555b6114c9565b600460018a0154600160a01b900460ff16600481111561139357fe5b1480156113ac575060018901546001600160a01b031633145b156113ed576113c5826111a2888663ffffffff61308c16565b6001600160a01b038e166000908152600f602052604090208054919250908f90811061130757fe5b6001808a0154600160a01b900460ff16600481111561140857fe5b148015611421575060018901546001600160a01b031633145b156114c957611436868363ffffffff61308c16565b6001600160a01b038e166000908152600f602052604090208054919250908f90811061145e57fe5b600091825260208220600a9091020180546001600160a01b031990811682556001820180546001600160a81b03191690556002820183905560038201839055600482018390556005820183905560068201839055600782018054909116905560088101829055600901555b6114da81600063ffffffff612c8716565b6114f65760405162461bcd60e51b81526004016105949061464a565b61150160108261356e565b60018a0154909c50600160a01b900460ff16600481111561151e57fe5b8c5160088b015460405133927f342d1375efc923bbfe4f5b6575b7d47f40247499113546f8689206d3fd1cf82f92611555926145f5565b60405180910390a38b5160015461157f916001600160a01b0390911690339063ffffffff61318d16565b505050505050505050611590612d4c565b505092915050565b6115a0612bfd565b6115a8612c4f565b6115b0612c78565b60006115bb33612c9e565b905080600401546000146115e15760405162461bcd60e51b815260040161059490614cba565b60006115fd600c546115f1610c9a565b9063ffffffff6135f716565b9050600b5481106116205760405162461bcd60e51b815260040161059490614b9f565b6004820181905560405133907fbf457c80c8bf299d5c48272c4c1168bf87b33d83b13f0ab9aac332ce1161ed1e90600090a250506106b8612d4c565b60135481565b61166a614125565b611672612c4f565b61167a612c78565b600061168461361c565b90506000611690610c9a565b905061169a614125565b6116a2613655565b90506116b581600063ffffffff61368216565b156116c35750611941915050565b8160035414156116d65750611941915050565b6116de614125565b6116e6614125565b6003546040516374201feb60e01b81526001600160a01b038716916374201feb91611718919088908890600401614dc5565b604080518083038186803b15801561172f57600080fd5b505afa158015611743573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117679190614315565b60038690559092509050611781828263ffffffff61308c16565b955061179486600063ffffffff61368216565b156117a457506119419350505050565b6117b4868463ffffffff61316516565b1561182d576117c1614125565b6117d1878563ffffffff612dfe16565b90506117db614125565b6117e58383612d7b565b90506117f7838263ffffffff612dfe16565b9250611809828263ffffffff612dfe16565b91506118256118188584612d7b565b859063ffffffff612dfe16565b935084975050505b805182516040517f19b92e73d08d517d71ec46136266e4f5d526a8cd4f8501d73713cebfe4f335ef90600090a36118648684613699565b61187582600063ffffffff612c8716565b1561190357815160015461189c916001600160a01b0390911690879063ffffffff6136e916565b60015460405163432ce91960e11b81526001600160a01b0387811692638659d232926118d0929091169086906004016144a0565b600060405180830381600087803b1580156118ea57600080fd5b505af11580156118fe573d6000803e3d6000fd5b505050505b61191481600063ffffffff612c8716565b1561193b57805160015461193b916001600160a01b0390911690339063ffffffff61318d16565b50505050505b610d3b612d4c565b611951614125565b611959612bfd565b3361196381612c25565b61196b611662565b50611974612c4f565b61197c612c78565b600061198733612c9e565b905061199a84600063ffffffff612c8716565b6119b65760405162461bcd60e51b8152600401610594906148b9565b6119c0818561378e565b80516040519194509033907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b6590600090a38251600154611a13916001600160a01b0390911690339063ffffffff61318d16565b50611a1c612d4c565b50919050565b611a2a614125565b611a32612c4f565b60408051602081019091526008548152611a4b90612d99565b905090565b60125481565b600f6020528160005260406000208181548110611a6f57fe5b6000918252602091829020600a919091020180546001820154600283015460408051808701825260038601548152815180880183526004870154815282518089018452600588015481528351808a0185526006890154815260078901548551808c01875260088b0154815286519b8c019096526009909901548a526001600160a01b039788169b508787169a50600160a01b90960460ff16989497929691959094909391909216918b565b60105481565b600660209081526000918252604091829020825180830184528154815260018201548451808501865260028401548152855194850190955260038301548452600490920154909391929085565b611b75612bfd565b33611b7f81612c25565b611b87612c4f565b611b8f612c78565b611bdd611b9c6000612dc2565b6001600160a01b03841660009081526006602090815260409182902082519182019092526003909101548152611bd190612d99565b9063ffffffff6137d416565b611bf95760405162461bcd60e51b815260040161059490614afa565b6000611c0433612c9e565b90508060040154600014158015611c265750611c1e610c9a565b816004015411155b611c425760405162461bcd60e51b815260040161059490614a02565b600060048083018281556001600160a01b038616808452600660205260408085208654815560018088015481830155600280890154818401556003808a01548185015595549287019290925533808852838820888155918201889055918101879055938401869055929093018490559151919290917ff1a2dcf23621f1a96185c79d39a5776b5ba3dadbea70c5aa86d84c17c7e9418e9190a36040516001600160a01b038416907ff60993fa76f94c9e0a803526ee6e1314814ed4d2b0d223febf1436b36897fb3790600090a260405133907fcad20625296d189a6fc6e5b39d0d544e5bd99dbda0c8f2f0ecffef3e0fbcc28290600090a250611d43612d4c565b5050565b60155481565b611d55614125565b611d5d612bfd565b33611d6781612c25565b611d6f611662565b50611d78612c4f565b611d80612c78565b6000611d8b33612c9e565b604080516020810190915281548152909150611dae90859063ffffffff61316516565b15611dcb5760405162461bcd60e51b8152600401610594906147b6565b611dd3614125565b604080516020810190915282548152611df390869063ffffffff612f1616565b9050611dfd614125565b604080516020810190915260038401548152611e2990611e1c90612d99565b839063ffffffff612e3016565b604080516020810190915284548152909150611e4b908763ffffffff6137d416565b15611e6057611e59336137db565b9450611efd565b611e6a838261316c565b9450611e74614125565b604080516020810190915284548152611e93908863ffffffff612dfe16565b6040805160208101909152600d548152909150611eb790829063ffffffff612e7316565b611ed35760405162461bcd60e51b815260040161059490614852565b8051845560408051602081019091526007548152611ef7908863ffffffff612dfe16565b51600755505b8551855160405133907fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a92990600090a48451600154611f4e916001600160a01b0390911690339063ffffffff61318d16565b8551600954611f72916001600160a01b03909116903390309063ffffffff612cee16565b6009548651604051630852cd8d60e31b81526001600160a01b03909216916342966c6891611fa2916004016145ec565b600060405180830381600087803b158015611fbc57600080fd5b505af1158015611fd0573d6000803e3d6000fd5b50505050505050611a1c612d4c565b611fe7612bfd565b611fef611662565b50611ff8612c4f565b612000612c78565b61200a82826138f9565b6120265760405162461bcd60e51b815260040161059490614ad4565b3360009081526006602052604090206001810154156120575760405162461bcd60e51b81526004016105949061499f565b60408051602081019091528154815261207790600063ffffffff61368216565b156120e5576040805160208101909152600d54815261209d90839063ffffffff612e7316565b6120b95760405162461bcd60e51b815260040161059490614852565b60405133907ff60993fa76f94c9e0a803526ee6e1314814ed4d2b0d223febf1436b36897fb3790600090a25b6120ef8184612cc6565b5060408051602081019091528154815261210f908363ffffffff61308c16565b51815560408051602081019091526007548152612132908363ffffffff61308c16565b516007558151835160405133907f4b82aa16e071a61de1a6b9aeec9edab0356331f8122c78683b469ac8e685dabc90600090a48251600154612189916001600160a01b03909116903390309063ffffffff612cee16565b60095482516040516340c10f1960e01b81526001600160a01b03909216916340c10f19916121bc913391906004016143d6565b602060405180830381600087803b1580156121d657600080fd5b505af11580156121ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220e919061428b565b61222a5760405162461bcd60e51b815260040161059490614a66565b50611d43612d4c565b6009546001600160a01b031681565b61224a613965565b6122526131ac565b61225a611662565b50612263612c4f565b61226b612c78565b6005805460ff1916600117905561228930612284612e7b565b61398e565b612294600b5461327d565b60405133907f18600820405d6cf356e3556301762ca32395e72d8c81494fa344835c9da3633d90600090a26106b8612d4c565b6122cf614125565b6122d7612c4f565b611a4b613655565b60055460ff1681565b60085481565b600d5481565b600a5481565b612302614125565b61230a612c4f565b6001600160a01b0382166000908152600660209081526040918290208251918201909252600390910154815261233f90612d99565b92915050565b600b5481565b600c5481565b606061235b612c4f565b6001600160a01b0382166000908152600f6020908152604080832080548251818502810185019093528083529193909284015b828210156124a45760008481526020908190206040805161016081018252600a860290920180546001600160a01b039081168452600182015490811694840194909452919290830190600160a01b900460ff1660048111156123ec57fe5b60048111156123f757fe5b8152600282015460208083019190915260408051808301825260038501548152818401528051808301825260048501548152606084015280518083018252600585015481526080840152805180830182526006850154815260a084015260078401546001600160a01b031660c0840152805180830182526008850154815260e08401528051808301909152600990930154835261010090910191909152908252600192909201910161238e565b505050509050919050565b6124b7614125565b82826124c38282613aef565b6124cb611662565b506124d4612c4f565b6124dc612c78565b60006124e88587613369565b90506124f2614125565b6040805160208101909152600683015481526125409061251190612d99565b60408051602080820183526013548252825190810190925260048601548252610879919063ffffffff612e3016565b905061254d6010826130b5565b5060018201805460ff60a01b1916600160a11b1790556007820180546001600160a01b0319163317905560028201546125859061327d565b6001820154815160405133926001600160a01b0390811692908a16917fcaca181ccad7979cf36ed4fc921e496001ab5264608f0fac7007ae1b43d36102916125cf918d91906145f5565b60405180910390a46040805160208101909152600983015481526125fa90829063ffffffff61308c16565b60408051602081019091526009840154815290955061261a90339061398e565b805160015461263e916001600160a01b03909116903390309063ffffffff612cee16565b5050611590612d4c565b612650612bfd565b612658612c4f565b612660612c78565b600061266b33612c9e565b90508060040154600014156126925760405162461bcd60e51b815260040161059490614726565b60405133907f2e5702420c76e041698ad7ba57a9ff5cadccf647ea8d96e6007a40b5b2662f5690600090a260006004909101556106b8612d4c565b6002546001600160a01b031681565b6126e4612bfd565b336126ee81612c25565b6126f6612c4f565b6126fe612c78565b600061270933612c9e565b905061271c83600063ffffffff612c8716565b801561274f575060408051602081019091526003820154815261274f9061274290612d99565b849063ffffffff612df616565b61276b5760405162461bcd60e51b8152600401610594906148b9565b600061277b600c546115f1610c9a565b9050600b54811061279e5760405162461bcd60e51b815260040161059490614b9f565b6001820181905583516002830181905560405133907fd33b726e11d2c5d38e6702b16613df0160a07f7ba5185455ee3c45d0494fab1190600090a35050611d43612d4c565b6127eb612bfd565b6127f3612c4f565b6127fb612c78565b6106b8612d4c565b60145481565b612813338261053c565b50565b60045481565b600e5481565b61282a614125565b612832613965565b61283a611662565b50612843612c4f565b61284b612c78565b600060055460ff16600281111561285e57fe5b141561287c5760405162461bcd60e51b815260040161059490614c8e565b600260055460ff16600281111561288f57fe5b146128b15761289f600b54613b4f565b51600e556005805460ff191660021790555b6128b9614125565b6040805160208101918290526009546370a0823160e01b9092529081906001600160a01b03166370a082316128f133602485016143c2565b60206040518083038186803b15801561290957600080fd5b505afa15801561291d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294191906142ab565b9052905061294d614125565b6040805160208101909152600e54815261296e90839063ffffffff612e3016565b3360009081526006602090815260408083208151928301909152600381015482529293506129ac91906129a090612d99565b9063ffffffff612c8716565b15612abb576129b9614125565b6040805160208082018352600e5482528251908101909252835482526129e5919063ffffffff612e3016565b90506129ef614125565b604080516020810190915260038401548152612a0a90612d99565b9050612a14614125565b612a24838363ffffffff613ca516565b612a3d5760405180602001604052806000815250612a4d565b612a4d828463ffffffff612dfe16565b9050612a5f858263ffffffff61308c16565b336000818152600660205260408082208281556001810183905560028101839055600381018390556004018290555192975090917fcad20625296d189a6fc6e5b39d0d544e5bd99dbda0c8f2f0ecffef3e0fbcc2829190a25050505b612ac3614125565b60408051602081019091526008548152612ae690612ae090612d99565b84612d7b565b9050612af360088261356e565b60408051602081019091526007548152909550612b16908563ffffffff612dfe16565b516007558351855160405133907f9d349c102bec959fb7f20f9a3621e015819d3ae4ed6e9afd1f56a69d5845600690600090a48451600154612b6b916001600160a01b0390911690339063ffffffff61318d16565b8351600954612b8f916001600160a01b03909116903390309063ffffffff612cee16565b6009548451604051630852cd8d60e31b81526001600160a01b03909216916342966c6891612bbf916004016145ec565b600060405180830381600087803b158015612bd957600080fd5b505af1158015612bed573d6000803e3d6000fd5b5050505050505050610d3b612d4c565b600b54612c08610c9a565b106106b85760405162461bcd60e51b815260040161059490614b31565b612c2e81612c9e565b60010154156128135760405162461bcd60e51b81526004016105949061499f565b600054600160a01b900460ff166106b85760405162461bcd60e51b815260040161059490614c57565b6000805460ff60a01b19169055565b6000612c9282612dc2565b51835111905092915050565b600081612caa81613cac565b50506001600160a01b0316600090815260066020526040902090565b612cce614125565b612cdb83600301836130b5565b50612ce76008836130b5565b9392505050565b612d46846323b872dd60e01b858585604051602401612d0f9392919061447c565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613cff565b50505050565b6000805460ff60a01b1916600160a01b179055565b612d6b6000612dc2565b5160028201556000600190910155565b612d83614125565b8151835110612d925781612ce7565b5090919050565b612da1614125565b6040805160208101909152600454815261233f90839063ffffffff612e3016565b612dca614125565b604080516020810190915280612dee84670de0b6b3a764000063ffffffff613de416565b905292915050565b519051111590565b612e06614125565b6040805160208101909152825184518291612e27919063ffffffff613e1e16565b90529392505050565b612e38614125565b6040805160208101909152825184518291670de0b6b3a764000091612e629163ffffffff613de416565b81612e6957fe5b0490529392505050565b519051101590565b612e83614125565b6000612e8d61361c565b600154604051635b97aadd60e01b81529192506001600160a01b0380841692635b97aadd92612ec09216906004016143c2565b60206040518083038186803b158015612ed857600080fd5b505afa158015612eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1091906142de565b91505090565b612f1e614125565b6040805160208101909152825184518291612e2791612f4b90670de0b6b3a764000063ffffffff613de416565b9063ffffffff613e6016565b6000612f6285612c9e565b604080516020810190915281548152909150612f8590859063ffffffff6137d416565b8015612fad5750604080516020810190915260038201548152612fad908490611bd190612d99565b15612fc257612fbb856137db565b5050612d46565b612fcc818461316c565b50612fd5614125565b604080516020810190915282548152612ff4908663ffffffff612dfe16565b6040805160208101909152600d54815290915061301890829063ffffffff612e7316565b6130345760405162461bcd60e51b815260040161059490614852565b8051825560408051602081019091526002830154815261305a908463ffffffff612dfe16565b51600283015560408051602081019091526007548152613080908663ffffffff612dfe16565b51600755505050505050565b613094614125565b6040805160208101909152825184518291612e27919063ffffffff6135f716565b6130bd614125565b6130c5614125565b6040805160208101909152845481526130dd90612d99565b90506130e7614125565b6130f08461313c565b604080516020810190915286548152909150613112908263ffffffff61308c16565b51808655604080516020810190915290815261313390839061127090612d99565b95945050505050565b613144614125565b6040805160208101909152600454815261233f90839063ffffffff612f1616565b5190511190565b613174614125565b613181836003018361356e565b50612ce760088361356e565b6106188363a9059cbb60e01b8484604051602401612d0f9291906143d6565b600060055460ff1660028111156131bf57fe5b146106b85760405162461bcd60e51b8152600401610594906147e4565b6002546040516302abf57960e61b81526000916001600160a01b03169063aafd5e409061322d907f46696e616e6369616c436f6e74726163747341646d696e000000000000000000906004016145ec565b60206040518083038186803b15801561324557600080fd5b505afa158015613259573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4b91906141af565b6000613287613ea2565b600a546040516368ad8ae360e01b81529192506001600160a01b038316916368ad8ae3916132b99186906004016145f5565b600060405180830381600087803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b505050505050565b60006132fb8284613369565b600181810154919250600160a01b90910460ff169081600481111561331c57fe5b118061334d575061332b610c9a565b61333483613edc565b1115801561334d5750600181600481111561334b57fe5b145b612d465760405162461bcd60e51b815260040161059490614681565b6001600160a01b0382166000908152600f602052604081208054831080156133c75750600081848154811061339a57fe5b90600052602060002090600a020160010160149054906101000a900460ff1660048111156133c457fe5b14155b6133e35760405162461bcd60e51b815260040161059490614889565b8083815481106133ef57fe5b90600052602060002090600a020191505092915050565b60006134128284613369565b905060026001820154600160a01b900460ff16600481111561343057fe5b1461343b5750611d43565b6134488160020154613b4f565b516008820155613456614125565b604080516020808201835260088501548252825190810190925260038401548252613487919063ffffffff612e3016565b9050613491614125565b604080516020810190915260125481526134b290839063ffffffff612e3016565b6040805160208101909152600585015481529091506000906134da908363ffffffff612e7316565b9050806134e85760046134eb565b60035b60018501805460ff60a01b1916600160a01b83600481111561350957fe5b0217905550600184015460078501546040516001600160a01b03928316928881169233927f6c5582199868fabbe697f9ea10abe481bacf53ac78c02a965b34dff82fd20e3b9261355e9216908c9088906144ba565b60405180910390a4505050505050565b613576614125565b61357e614125565b60408051602081019091528454815261359690612d99565b90506135a0614125565b6135a98461313c565b6040805160208101909152865481529091506135cb908263ffffffff612dfe16565b518086556040805160208101909152908152613133906135ea90612d99565b839063ffffffff612dfe16565b600082820183811015612ce75760405162461bcd60e51b8152600401610594906146ef565b6002546040516302abf57960e61b81526000916001600160a01b03169063aafd5e409061322d906453746f726560d81b906004016145ec565b61365d614125565b60408051602081019091526010548152611a4b9061367a90612d99565b6111a2613ef7565b600061368d82612dc2565b51835114905092915050565b6136a1614125565b6136b1838363ffffffff613eff16565b90506136e06136c4826112706001612dc2565b604080516020810190915260045481529063ffffffff612e3016565b51600455505050565b600061376d82856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040161371d9291906143ef565b60206040518083038186803b15801561373557600080fd5b505afa158015613749573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f191906142ab565b9050612d468463095ea7b360e01b8584604051602401612d0f9291906143d6565b613796614125565b6137a3836003018361356e565b506137ad83613fa1565b6137c95760405162461bcd60e51b815260040161059490614ad4565b612ce760088361356e565b5190511490565b6137e3614125565b60006137ee83612c9e565b90506137f8614125565b6040805160208101909152600854815261381190612d99565b905061381b614125565b50604080516020808201835260038501548252825190810190925260085482529061384c908263ffffffff612dfe16565b516008556040805160208082018352855482528251908101909252600754825261387c919063ffffffff612dfe16565b516007556001600160a01b038516600081815260066020526040808220828155600181018390556002810183905560038101839055600401829055517fcad20625296d189a6fc6e5b39d0d544e5bd99dbda0c8f2f0ecffef3e0fbcc2829190a260408051602081019091526008548152613133906135ea90612d99565b6000613903614125565b604080516020810190915260085481526139359061392090612d99565b60408051602081019091526007548152613fd7565b905061393f614125565b6139498585613fd7565b905061395b828263ffffffff61316516565b1595945050505050565b600b54613970610c9a565b10156106b85760405162461bcd60e51b815260040161059490614b68565b61399f81600063ffffffff61368216565b156139a957611d43565b6001600160a01b03821630146139e25780516001546139dd916001600160a01b03909116908490309063ffffffff612cee16565b613a2c565b6139ea614125565b6139f2613655565b9050613a04818363ffffffff61316516565b613a205760405162461bcd60e51b815260040161059490614d1b565b613a2a8282613699565b505b80516040517f4f9bf7e8cd0f2456f9c43d2597bedcf1446c9c64544053f1ece6423ae9a07e5290600090a26000613a6161361c565b8251600154919250613a84916001600160a01b031690839063ffffffff6136e916565b60015460405163432ce91960e11b81526001600160a01b0383811692638659d23292613ab8929091169086906004016144a0565b600060405180830381600087803b158015613ad257600080fd5b505af1158015613ae6573d6000803e3d6000fd5b50505050505050565b6000613afb8284613369565b9050613b0681613edc565b613b0e610c9a565b108015613b335750600180820154600160a01b900460ff166004811115613b3157fe5b145b6106185760405162461bcd60e51b815260040161059490614927565b613b57614125565b6000613b61613ea2565b600a5460405163501f440d60e11b81529192506001600160a01b0383169163a03e881a91613b939187906004016145f5565b60206040518083038186803b158015613bab57600080fd5b505afa158015613bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613be3919061428b565b613bff5760405162461bcd60e51b81526004016105949061481b565b600a54604051636494078360e11b81526000916001600160a01b0384169163c9280f0691613c319188906004016145f5565b60206040518083038186803b158015613c4957600080fd5b505afa158015613c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c8191906142ab565b90506000811215613c90575060005b60408051602081019091529081529392505050565b5190511090565b6001600160a01b03811660009081526006602090815260408083208151928301909152600301548152613ce391906129a090612d99565b6128135760405162461bcd60e51b8152600401610594906148f0565b613d11826001600160a01b0316614015565b613d2d5760405162461bcd60e51b815260040161059490614ce4565b60006060836001600160a01b031683604051613d4991906143a6565b6000604051808303816000865af19150503d8060008114613d86576040519150601f19603f3d011682016040523d82523d6000602084013e613d8b565b606091505b509150915081613dad5760405162461bcd60e51b815260040161059490614781565b805115612d465780806020019051810190613dc8919061428b565b612d465760405162461bcd60e51b815260040161059490614c0d565b600082613df35750600061233f565b82820282848281613e0057fe5b0414612ce75760405162461bcd60e51b81526004016105949061495e565b6000612ce783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614051565b6000612ce783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061407d565b6002546040516302abf57960e61b81526000916001600160a01b03169063aafd5e409061322d90654f7261636c6560d01b906004016145ec565b600061233f60115483600201546135f790919063ffffffff16565b611a32614125565b613f07614125565b8251600090613f2490670de0b6b3a764000063ffffffff613de416565b8351909150600090613f3d90839063ffffffff613e6016565b8451909150600090613f5690849063ffffffff6140b416565b90508015613f8857604080516020810190915280613f7b84600163ffffffff6135f716565b815250935050505061233f565b604051806020016040528083815250935050505061233f565b60408051602081019091526003820154815260009061233f90613fc390612d99565b6040805160208101909152845481526138f9565b613fdf614125565b613ff082600063ffffffff612c8716565b61400557613ffe6000612dc2565b905061233f565b613ffe838363ffffffff612f1616565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061404957508115155b949350505050565b600081848411156140755760405162461bcd60e51b81526004016105949190614617565b505050900390565b6000818361409e5760405162461bcd60e51b81526004016105949190614617565b5060008385816140aa57fe5b0495945050505050565b6000612ce783836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250600081836141125760405162461bcd60e51b81526004016105949190614617565b5082848161411c57fe5b06949350505050565b6040518060200160405280600081525090565b600060208284031215611a1c578081fd5b60006020828403121561415a578081fd5b6141646020614df7565b9135825250919050565b60006020828403121561417f578081fd5b6141896020614df7565b9151825250919050565b6000602082840312156141a4578081fd5b8135612ce781614e54565b6000602082840312156141c0578081fd5b8151612ce781614e54565b600080600080600060a086880312156141e2578081fd5b85356141ed81614e54565b94506141fc8760208801614138565b935061420b8760408801614138565b925061421a8760608801614138565b949793965091946080013592915050565b6000806040838503121561423d578182fd5b823561424881614e54565b91506142578460208501614149565b90509250929050565b60008060408385031215614272578182fd5b823561427d81614e54565b946020939093013593505050565b60006020828403121561429c578081fd5b81518015158114612ce7578182fd5b6000602082840312156142bc578081fd5b5051919050565b6000602082840312156142d4578081fd5b612ce78383614149565b6000602082840312156142ef578081fd5b612ce7838361416e565b6000806040838503121561430b578182fd5b6142488484614149565b60008060408385031215614327578182fd5b614331848461416e565b9150614257846020850161416e565b600060208284031215614351578081fd5b5035919050565b6000806040838503121561436a578182fd5b82359150602083013561437c81614e54565b809150509250929050565b6001600160a01b03169052565b61439d81614e4a565b9052565b519052565b600082516143b8818460208701614e1e565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038c811682528b8116602083015261016082019061442d8c614e4a565b604083019b909b52606082019990995296516080880152945160a0870152925160c0860152905160e0850152909416610100830152925161012082015291516101409092019190915292915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0392909216825251602082015260400190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156145df57815161450f858251614387565b8681015161451f88870182614387565b508581015161453087870182614394565b506060818101519086015260808082015161454d828801826143a1565b505060a080820151614561828801826143a1565b505060c080820151614575828801826143a1565b505060e080820151614589828801826143a1565b50506101008082015161459e82880182614387565b5050610120808201516145b3828801826143a1565b5050610140808201516145c8828801826143a1565b5050506101609390930192908501906001016144fa565b5091979650505050505050565b90815260200190565b918252602082015260400190565b602081016003831061461157fe5b91905290565b6000602082528251806020840152614636816040850160208701614e1e565b601f01601f19169190910160400192915050565b60208082526019908201527f496e76616c6964207769746864726177616c20616d6f756e7400000000000000604082015260600190565b6020808252601c908201527f4c69717569646174696f6e206e6f7420776974686472617761626c6500000000604082015260600190565b6020808252601e908201527f43616c6c65722063616e6e6f7420776974686472617720726577617264730000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601390820152722737903832b73234b733903a3930b739b332b960691b604082015260600190565b6020808252601490820152734d696e656420616674657220646561646c696e6560601b604082015260600190565b6020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b602080825260149082015273125b9d985b1a59081d1bdad95b88185b5bdd5b9d60621b604082015260600190565b6020808252601a908201527f436f6e7472616374207374617465206973206e6f74204f50454e000000000000604082015260600190565b60208082526017908201527f556e7265736f6c766564206f7261636c65207072696365000000000000000000604082015260600190565b6020808252601e908201527f42656c6f77206d696e696d756d2073706f6e736f7220706f736974696f6e0000604082015260600190565b602080825260169082015275125b9d985b1a59081b1a5c5d5a59185d1a5bdb88125160521b604082015260600190565b60208082526019908201527f496e76616c696420636f6c6c61746572616c20616d6f756e7400000000000000604082015260600190565b6020808252601a908201527f506f736974696f6e20686173206e6f20636f6c6c61746572616c000000000000604082015260600190565b6020808252601a908201527f4c69717569646174696f6e206e6f742064697370757461626c65000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526012908201527114195b991a5b99c81dda5d1a191c985dd85b60721b604082015260600190565b60208082526018908201527f496e76616c696420776974686472617720726571756573740000000000000000604082015260600190565b60208082526018908201527f496e76616c6964207472616e7366657220726571756573740000000000000000604082015260600190565b60208082526013908201527221b0b63632b9103737ba1023b7bb32b93737b960691b604082015260600190565b6020808252601f908201527f4d696e74696e672073796e74686574696320746f6b656e73206661696c656400604082015260600190565b6020808252601e908201527f4352206973206d6f7265207468616e206d6178206c69712e2070726963650000604082015260600190565b6020808252600c908201526b21a9103132b637bb9023a1a960a11b604082015260600190565b6020808252601c908201527f53706f6e736f7220616c72656164792068617320706f736974696f6e00000000604082015260600190565b60208082526018908201527f4f6e6c792063616c6c61626c65207072652d6578706972790000000000000000604082015260600190565b60208082526019908201527f4f6e6c792063616c6c61626c6520706f73742d65787069727900000000000000604082015260600190565b6020808252601b908201527f52657175657374206578706972657320706f73742d6578706972790000000000604082015260600190565b6020808252601e908201527f4352206973206c657373207468616e206d696e206c69712e2070726963650000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601290820152712ab732bc3834b932b2103837b9b4ba34b7b760711b604082015260600190565b60208082526010908201526f2832b73234b733903a3930b739b332b960811b604082015260600190565b6020808252601f908201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604082015260600190565b6020808252601a908201527f46696e616c20666565206973206d6f7265207468616e20506643000000000000604082015260600190565b602080825260159082015274139bc81c195b991a5b99c81dda5d1a191c985dd85b605a1b604082015260600190565b9051815260200190565b94518552602085019390935290516040840152516060830152608082015260a00190565b9283529051602083015251604082015260600190565b928352602083019190915251604082015260600190565b93845260208401929092526040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715614e1657600080fd5b604052919050565b60005b83811015614e39578181015183820152602001614e21565b83811115612d465750506000910152565b6005811061281357fe5b6001600160a01b038116811461281357600080fd5b6000614e7482612dc2565b5183511090509291505056fea26469706673582212207ce495d0c987eaac5acec76e36eb506151c84b3c44515747b0f2252a2c07354264736f6c63430006060033

Deployed Bytecode Sourcemap

153917:531:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;153917:531:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;85837:49:0;;;:::i;:::-;;;;;;;;;;;;;;;;71411:32;;;:::i;:::-;;;;;;;;94911:755;;;;;;;;;:::i;:::-;;66221:27;;;:::i;101617:497::-;;;:::i;66960:117::-;;;;;;;;;:::i;134475:5471::-;;;;;;;;;:::i;:::-;;;;;;;;;;67329:262;;;:::i;129396:34::-;;;:::i;99960:1577::-;;;:::i;:::-;;;;;;;;112342:702;;;:::i;143072:5844::-;;;;;;;;;:::i;91696:689::-;;;:::i;129776:41::-;;;:::i;74582:2330::-;;;:::i;96835:1274::-;;;;;;;;;:::i;114545:241::-;;;:::i;129536:48::-;;;:::i;129128:57::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;129235:51;;;:::i;85601:49::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;92827:1093;;;;;;;;;:::i;130192:51::-;;;:::i;104816:2061::-;;;;;;;;;:::i;102755:1492::-;;;;;;;;;:::i;86214:35::-;;;:::i;111279:412::-;;;:::i;77390:115::-;;;:::i;84516:34::-;;;:::i;:::-;;;;;;;;86102:53;;;:::i;86711:43::-;;;:::i;86311:30::-;;;:::i;114000:319::-;;;;;;;;;:::i;86462:34::-;;;:::i;86611:33::-;;;:::i;149176:214::-;;;;;;;;;:::i;:::-;;;;;;;;140721:1646;;;;;;;;;:::i;94007:423::-;;;:::i;71528:29::-;;;:::i;98440:1015::-;;;;;;;;;:::i;113516:98::-;;;:::i;129979:50::-;;;:::i;96075:224::-;;;;;;;;;:::i;72204:50::-;;;:::i;86809:38::-;;;:::i;107513:3422::-;;;:::i;85837:49::-;;;;:::o;71411:32::-;;;-1:-1:-1;;;;;71411:32:0;;:::o;94911:755::-;88523:20;:18;:20::i;:::-;95066:7:::1;89094:40;89126:7;89094:31;:40::i;:::-;72755:16:::2;:14;:16::i;:::-;;59104:19:::3;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;95139:33:::4;:16:::0;95170:1:::4;95139:33;:30;:33;:::i;:::-;95131:71;;;;-1:-1:-1::0;;;95131:71:0::4;;;;;;;;;;;;;;;;;95213:33;95249:25;95266:7;95249:16;:25::i;:::-;95213:61;;95373:60;95402:12;95416:16;95373:28;:60::i;:::-;-1:-1:-1::0;95468:25:0;;95451:43:::4;::::0;-1:-1:-1;;;;;95451:43:0;::::4;::::0;::::4;::::0;95468:25:::4;::::0;95451:43:::4;95632:25:::0;;95569:18:::4;::::0;:89:::4;::::0;-1:-1:-1;;;;;95569:18:0;;::::4;::::0;95605:10:::4;::::0;95625:4:::4;::::0;95569:89:::4;:35;:89;:::i;:::-;59162:1;59174:20:::3;:18;:20::i;:::-;88554:1:::1;94911:755:::0;;:::o;66221:27::-;;;-1:-1:-1;;;;;66221:27:0;;:::o;101617:497::-;88523:20;:18;:20::i;:::-;59104:19:::1;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;101700:33:::2;101736:28;101753:10;101736:16;:28::i;:::-;101700:64;;101783:12;:43;;;101830:1;101783:48;;101775:82;;;;-1:-1:-1::0;;;101775:82:0::2;;;;;;;;;101913:36;::::0;::::2;:45:::0;101875:84:::2;::::0;101901:10:::2;::::0;101875:84:::2;::::0;101913:45:::2;::::0;101875:84:::2;102069:37;102093:12;102069:23;:37::i;:::-;59162:1;59174:20:::1;:18;:20::i;:::-;101617:497::o:0;66960:117::-;66753:3;66729:12;-1:-1:-1;;;;;66729:12:0;66721:37;;12:1:-1;9;2:12;66721:37:0;67035:12:::1;::::0;67029:40:::1;::::0;-1:-1:-1;;;67029:40:0;;-1:-1:-1;;;;;67035:12:0;;::::1;::::0;67029:34:::1;::::0;:40:::1;::::0;67064:4;;67029:40:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;67029:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;67029:40:0;;;;66960:117:::0;:::o;134475:5471::-;134863:21;134899:43;;:::i;:::-;134957:39;;:::i;:::-;72755:16;:14;:16::i;:::-;;88523:20:::1;:18;:20::i;:::-;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;135116:8:::3;135096:16;:14;:16::i;:::-;:28;;135088:61;;;;-1:-1:-1::0;;;135088:61:0::3;;;;;;;;;135209:40;135252:25;135269:7;135252:16;:25::i;:::-;135209:68:::0;-1:-1:-1;135309:75:0::3;;;::::0;;::::3;::::0;::::3;135324:20:::0;135309:75:::3;;;;::::0;;::::3;::::0;::::3;::::0;;;;;;;:14:::3;:75::i;:::-;135290:94;;135616:42;;:::i;:::-;135661:60;::::0;;::::3;::::0;::::3;::::0;;;135687:33:::3;::::0;::::3;135661:60:::0;;;::::3;::::0;:25:::3;:60::i;:::-;135616:105;;135732:57;;:::i;:::-;135792:30;135820:1;135792:27;:30::i;:::-;135837:61;::::0;;::::3;::::0;::::3;::::0;;;:43:::3;::::0;::::3;:61:::0;;;135732:90;;-1:-1:-1;135837:78:0::3;::::0;135899:15;135837:78:::3;:61;:78;:::i;:::-;135833:208;;;135965:64;::::0;;::::3;::::0;::::3;::::0;;;135985:43:::3;::::0;::::3;135965:64:::0;;;::::3;::::0;:15;;:64:::3;:19;:64;:::i;:::-;135932:97;;135833:208;136126:38;;:::i;:::-;-1:-1:-1::0;136126:78:0::3;::::0;;::::3;::::0;::::3;::::0;;;;;;;136453:91:::3;136513:30:::0;136453:38:::3;136126:78:::0;136453:25:::3;;::::0;;::::3;::::0;::::3;:21:::0;:25:::3;;;::::0;:38:::3;:25;:38;:::i;:::-;:59:::0;:91:::3;:59;:91;:::i;:::-;136427:183;;;;-1:-1:-1::0;;;136427:183:0::3;;;;;;;;;136738:88;136795:30;136738:38;136764:11;136738:21;:25;;;;;;;;;;;:38;:56:::0;:88:::3;:56;:88;:::i;:::-;136712:180;;;;-1:-1:-1::0;;;136712:180:0::3;;;;;;;;;59162:1;136985:19;:17;:19::i;:::-;136970:34;;137077:43;;:::i;:::-;137131:47;;:::i;:::-;137264:32;;:::i;:::-;137299:59;::::0;;::::3;::::0;::::3;::::0;;;;;;;::::3;::::0;:16;;:59:::3;:20;:59;:::i;:::-;137264:94:::0;-1:-1:-1;137478:26:0::3;:15:::0;137264:94;137478:26:::3;:19;:26;:::i;:::-;137459:45:::0;-1:-1:-1;137703:41:0::3;:30:::0;137738:5;137703:41:::3;:34;:41;:::i;:::-;137680:64;;137918:51;;:::i;:::-;137972:47;::::0;;::::3;::::0;::::3;::::0;;;:43:::3;::::0;::::3;:47:::0;;;:86:::3;::::0;138038:5;137972:86:::3;:47;:86;:::i;:::-;137918:140;;138073:93;138096:7;138105:16;138123;138141:24;138073:22;:93::i;:::-;-1:-1:-1::0;138250:76:0::3;::::0;-1:-1:-1;138265:24:0::3;138291:34;:16:::0;138312:12;138291:34:::3;:20;:34;:::i;:::-;138250:14;:76::i;:::-;-1:-1:-1::0;;;;;;138638:21:0;::::3;;::::0;;;:12:::3;:21;::::0;;;;;;;;:28;;138718:610;;::::3;::::0;::::3;::::0;;;;;138800:10:::3;138718:610:::0;;::::3;::::0;;;;138638:28;;-1:-1:-1;138638:21:0;138718:610;;;138836:17:::3;138718:610;;;;138889:16;:14;:16::i;:::-;138718:610;;;;138943:16;138718:610;;;;138996:16;138718:610;;;;139053:20;138718:610;;;;139111:55;139135:30;139163:1;139135:27;:30::i;:::-;139111:23;:55::i;:::-;138718:610;;;;139203:1;-1:-1:-1::0;;;;;138718:610:0::3;;;;;139241:30;139269:1;139241:27;:30::i;:::-;138718:610:::0;;::::3;::::0;;::::3;::::0;;;27:10:-1;;39:1:::3;23:18:::0;;::::3;45:23:::0;;-1:-1;138677:662:0;;;;;;;;;::::3;::::0;;::::3;;::::0;;-1:-1:-1;;;;;;138677:662:0;;::::3;-1:-1:-1::0;;;;;138677:662:0;;::::3;;::::0;;;;::::3;::::0;;;::::3;::::0;;;;::::3;::::0;;;::::3;::::0;;;::::3;::::0;;;::::3;::::0;::::3;::::0;;;;;;-1:-1:-1;;;;138677:662:0::3;-1:-1:-1::0;;;138677:662:0;::::3;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;138677:662:0::3;;;;;-1:-1:-1::0;;;;;138677:662:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139437:13;139412:10;-1:-1:-1::0;;;;;139357:259:0::3;139390:7;-1:-1:-1::0;;;;;139357:259:0::3;;139465:16;:25;;;139505:16;:25;;;139545:20;:29;;;139589:16;:14;:16::i;:::-;139357:259;;;;;;;;;;;;;;;;;;139714:25:::0;;139656:13:::3;::::0;:84:::3;::::0;-1:-1:-1;;;;;139656:13:0;;::::3;::::0;139687:10:::3;::::0;139707:4:::3;::::0;139656:84:::3;:30;:84;:::i;:::-;139751:13;::::0;139770:25;;139751:45:::3;::::0;-1:-1:-1;;;139751:45:0;;-1:-1:-1;;;;;139751:13:0;;::::3;::::0;:18:::3;::::0;:45:::3;::::0;::::3;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::3;2:2;139751:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;-1:-1:::0;;139916:21:0;;139853:18:::3;::::0;:85:::3;::::0;-1:-1:-1;;;;;;139853:18:0::3;::::0;-1:-1:-1;139889:10:0::3;::::0;139909:4:::3;::::0;139853:85:::3;:35;:85;:::i;:::-;59162:1;;;;;59174:20:::2;:18;:20::i;:::-;134475:5471:::0;;;;;;;;;:::o;67329:262::-;67376:7;67400:12;;-1:-1:-1;;;;;67400:12:0;:28;67396:188;;67458:12;;;;;;;;;-1:-1:-1;;;;;67458:12:0;-1:-1:-1;;;;;67452:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;67452:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;67452:36:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;67452:36:0;;;;;;;;;67445:43;;;;67396:188;-1:-1:-1;67528:3:0;67396:188;67329:262;:::o;129396:34::-;;;;:::o;99960:1577::-;100098:42;;:::i;:::-;88523:20;:18;:20::i;:::-;72755:16:::1;:14;:16::i;:::-;;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;100158:33:::3;100194:28;100211:10;100194:16;:28::i;:::-;100158:64;;100255:12;:43;;;100302:1;100255:48;;:132;;;;;100371:16;:14;:16::i;:::-;100324:12;:43;;;:63;;100255:132;100233:206;;;;-1:-1:-1::0;;;100233:206:0::3;;;;;;;;;100667:43;;:::i;:::-;-1:-1:-1::0;100667:82:0::3;::::0;;::::3;::::0;;::::3;::::0;;100713:36:::3;::::0;::::3;100667:82:::0;;;100815:53;;;;::::3;::::0;;;100841:26:::3;::::0;::::3;100815:53:::0;;;100667:82;100764:105:::3;::::0;100815:53:::3;::::0;:25:::3;:53::i;:::-;100764:50;::::0;;::::3;::::0;::::3;::::0;;;:36:::3;::::0;::::3;:50:::0;;;;:105:::3;:50;:105;:::i;:::-;100760:210;;;100905:53;::::0;;::::3;::::0;::::3;::::0;;;100931:26:::3;::::0;::::3;100905:53:::0;;;::::3;::::0;:25:::3;:53::i;:::-;100886:72;;100760:210;101078:60;101107:12;101121:16;101078:28;:60::i;:::-;101060:78;;101248:37;101272:12;101248:23;:37::i;:::-;101423:24:::0;;101379:18:::3;::::0;:69:::3;::::0;-1:-1:-1;;;;;101379:18:0;;::::3;::::0;101411:10:::3;::::0;101379:69:::3;:31;:69;:::i;:::-;101504:24:::0;;101466:63:::3;::::0;101492:10:::3;::::0;101466:63:::3;::::0;101504:24:::3;::::0;101466:63:::3;59162:1;;59174:20:::2;:18;:20::i;112342:702::-:0;88523:20;:18;:20::i;:::-;88993:16:::1;:14;:16::i;:::-;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;112473:36:::3;:34;:36::i;:::-;-1:-1:-1::0;;;;;112459:50:0::3;:10;-1:-1:-1::0;;;;;112459:50:0::3;;112451:82;;;;-1:-1:-1::0;;;112451:82:0::3;;;;;;;;;112546:13;:51:::0;;-1:-1:-1;;112546:51:0::3;112562:35;112546:51;::::0;;112825:19:::3;::::0;112877:16:::3;:14;:16::i;:::-;112855:19;:38:::0;;;112904:40:::3;::::0;:19:::3;:40::i;:::-;113016:19;::::0;112962:74:::3;::::0;112980:10:::3;::::0;112962:74:::3;::::0;::::3;::::0;112992:22;;112962:74:::3;;;;;;;;;;59162:1;59174:20:::2;:18;:20::i;143072:5844::-:0;143261:42;;:::i;:::-;143179:13;143194:7;131669:37;131683:13;131698:7;131669:13;:37::i;:::-;72755:16:::1;:14;:16::i;:::-;;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;143321:35:::3;143359:43;143379:7;143388:13;143359:19;:43::i;:::-;143450:20;::::0;::::3;::::0;;;-1:-1:-1;;;;;;143450:20:0::3;143436:10;:34;::::0;143435:95:::3;;-1:-1:-1::0;143507:22:0::3;::::0;::::3;::::0;-1:-1:-1;;;;;143507:22:0::3;143493:10;:36;143435:95;:151;;;-1:-1:-1::0;143566:19:0;;-1:-1:-1;;;;;143566:19:0::3;143552:10;:33;143435:151;143413:231;;;;-1:-1:-1::0;;;143413:231:0::3;;;;;;;;;143764:31;143772:13;143787:7;143764;:31::i;:::-;143980:41;;:::i;:::-;144024:56;::::0;;::::3;::::0;::::3;::::0;;;144050:29:::3;::::0;::::3;144024:56:::0;;;::::3;::::0;:25:::3;:56::i;:::-;143980:100;;144091:47;;:::i;:::-;144141:90;::::0;;::::3;::::0;;::::3;::::0;;144203:27:::3;::::0;::::3;144141:90:::0;;;:61;;;;::::3;::::0;;;:43:::3;::::0;::::3;:61:::0;;;:124:::3;::::0;144250:14;;144141:90:::3;::::0;:61;:90:::3;:61;:90;:::i;:124::-;144091:174;;144276:37;;:::i;:::-;144316:32;::::0;;::::3;::::0;::::3;::::0;;;:28:::3;::::0;::::3;:32:::0;;;:48:::3;::::0;144349:14;144316:48:::3;:32;:48;:::i;:::-;144276:88;;144375:48;;:::i;:::-;144426:28;::::0;;::::3;::::0;::::3;::::0;;;:24:::3;:28:::0;;;:50:::3;::::0;144455:20;144426:50:::3;:28;:50;:::i;:::-;144375:101;;144487:47;;:::i;:::-;144537:27;::::0;;::::3;::::0;::::3;::::0;;;:23:::3;:27:::0;;;:49:::3;::::0;144565:20;144537:49:::3;:27;:49;:::i;:::-;144487:99;;144597:44;;:::i;:::-;144644:30;::::0;;::::3;::::0;::::3;::::0;;;144659:14:::3;144644:30:::0;;;::::3;::::0;:10;;:30:::3;:14;:30;:::i;:::-;144597:77;;144685:35;;:::i;:::-;144723:24;::::0;;::::3;::::0;::::3;::::0;;;:20:::3;::::0;::::3;:24:::0;;;:40:::3;::::0;144748:14;144723:40:::3;:24;:40;:::i;:::-;144685:78;;145149:43;;:::i;:::-;145195:30;145223:1;145195:27;:30::i;:::-;145149:76:::0;-1:-1:-1;145261:23:0::3;145240:17;::::0;::::3;::::0;-1:-1:-1;;;145240:17:0;::::3;;;:44;::::0;::::3;;;;;;;145236:3026;;;145417:20;::::0;::::3;::::0;-1:-1:-1;;;;;145417:20:0::3;145403:10;:34;145399:381;;;145544:40;;:::i;:::-;145587:58;145636:8:::0;145587:44:::3;:21:::0;145613:17;145587:44:::3;:25;:44;:::i;:::-;:48:::0;:58:::3;:48;:58;:::i;:::-;145544:101:::0;-1:-1:-1;145683:35:0::3;:16:::0;145544:101;145683:35:::3;:20;:35;:::i;:::-;145744:20;::::0;::::3;145737:27:::0;;-1:-1:-1;;;;;;145737:27:0::3;::::0;;145664:54;-1:-1:-1;;145399:381:0::3;145814:19:::0;;-1:-1:-1;;;;;145814:19:0::3;145800:10;:33;145796:472;;;145944:46;;:::i;:::-;145993:36;:10:::0;146008:20;145993:36:::3;:14;:36;:::i;:::-;145944:85;;146048:39;;:::i;:::-;146090:45;:20:::0;146115:19;146090:45:::3;:24;:45;:::i;:::-;146048:87:::0;-1:-1:-1;146173:34:0::3;:16:::0;146048:87;146173:34:::3;:20;:34;:::i;:::-;146226:26:::0;;-1:-1:-1;;;;;;146226:26:0::3;::::0;;146154:53;-1:-1:-1;;;145796:472:0::3;146302:22;::::0;::::3;::::0;-1:-1:-1;;;;;146302:22:0::3;146288:10;:36;146284:696;;;146683:42;;:::i;:::-;146728:113;146801:21:::0;146728:46:::3;:20:::0;146753;146728:46:::3;:24;:46;:::i;:::-;:50:::0;:113:::3;:50;:113;:::i;:::-;146683:158:::0;-1:-1:-1;146879:37:0::3;:16:::0;146683:158;146879:37:::3;:20;:37;:::i;:::-;146942:22;::::0;::::3;146935:29:::0;;-1:-1:-1;;;;;;146935:29:0::3;::::0;;146860:56;-1:-1:-1;;146284:696:0::3;147132:20;::::0;::::3;::::0;-1:-1:-1;;;;;147132:20:0::3;:34:::0;:88;::::3;;;-1:-1:-1::0;147187:19:0;;-1:-1:-1;;;;;147187:19:0::3;:33:::0;147132:88:::3;:145;;;;-1:-1:-1::0;147241:22:0::3;::::0;::::3;::::0;-1:-1:-1;;;;;147241:22:0::3;:36:::0;147132:145:::3;147110:261;;;-1:-1:-1::0;;;;;147319:21:0;::::3;;::::0;;;:12:::3;:21;::::0;;;;:36;;147341:13;;147319:36;::::3;;;;;;::::0;;;::::3;::::0;;::::3;::::0;;::::3;;147312:43:::0;;-1:-1:-1;;;;;;147312:43:0;;::::3;::::0;;;;::::3;::::0;;-1:-1:-1;;;;;;147312:43:0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;;::::3;::::0;;::::3;::::0;::::3;::::0;;;::::3;;::::0;147110:261:::3;145236:3026;;;147495:20;147474:17;::::0;::::3;::::0;-1:-1:-1;;;147474:17:0;::::3;;;:41;::::0;::::3;;;;;;;:81;;;;-1:-1:-1::0;147533:22:0::3;::::0;::::3;::::0;-1:-1:-1;;;;;147533:22:0::3;147519:10;:36;147474:81;147470:792;;;147670:47;147708:8:::0;147670:33:::3;:10:::0;147685:17;147670:33:::3;:14;:33;:::i;:47::-;-1:-1:-1::0;;;;;147739:21:0;::::3;;::::0;;;:12:::3;:21;::::0;;;;:36;;147651:66;;-1:-1:-1;147739:21:0;147761:13;;147739:36;::::3;;;;147470:792;148011:17;147990::::0;;::::3;::::0;-1:-1:-1;;;147990:17:0;::::3;;;:38;::::0;::::3;;;;;;;:78;;;;-1:-1:-1::0;148046:22:0::3;::::0;::::3;::::0;-1:-1:-1;;;;;148046:22:0::3;148032:10;:36;147990:78;147986:276;;;148168:24;:10:::0;148183:8;148168:24:::3;:14;:24;:::i;:::-;-1:-1:-1::0;;;;;148214:21:0;::::3;;::::0;;;:12:::3;:21;::::0;;;;:36;;148149:43;;-1:-1:-1;148214:21:0;148236:13;;148214:36;::::3;;;;;;::::0;;;::::3;::::0;;::::3;::::0;;::::3;;148207:43:::0;;-1:-1:-1;;;;;;148207:43:0;;::::3;::::0;;;;::::3;::::0;;-1:-1:-1;;;;;;148207:43:0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;;::::3;::::0;;::::3;::::0;::::3;::::0;;;::::3;;::::0;147986:276:::3;148280:33;:16:::0;148311:1:::3;148280:33;:30;:33;:::i;:::-;148272:71;;;;-1:-1:-1::0;;;148272:71:0::3;;;;;;;;;148462:61;148480:24;148506:16;148462:17;:61::i;:::-;148640:17;::::0;::::3;::::0;148444:79;;-1:-1:-1;;;;148640:17:0;::::3;;;148541:178;::::0;::::3;;;;;;148601:24:::0;;148672:27:::3;::::0;::::3;:36:::0;148541:178:::3;::::0;148576:10:::3;::::0;148541:178:::3;::::0;::::3;::::0;::::3;;;;;;;;;;148848:24:::0;;148804:18:::3;::::0;:69:::3;::::0;-1:-1:-1;;;;;148804:18:0;;::::3;::::0;148836:10:::3;::::0;148804:69:::3;:31;:69;:::i;:::-;-1:-1:-1::0;;;;;;;;;59174:20:0::2;:18;:20::i;:::-;143072:5844:::0;;;;;;:::o;91696:689::-;88523:20;:18;:20::i;:::-;59104:19:::1;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;91784:33:::2;91820:28;91837:10;91820:16;:28::i;:::-;91784:64;;91867:12;:49;;;91920:1;91867:54;91859:83;;;;-1:-1:-1::0;;;91859:83:0::2;;;;;;;;;92037:23;92063:40;92084:18;;92063:16;:14;:16::i;:::-;:20:::0;:40:::2;:20;:40;:::i;:::-;92037:66;;92140:19;;92122:15;:37;92114:77;;;;-1:-1:-1::0;;;92114:77:0::2;;;;;;;;;92257:49;::::0;::::2;:67:::0;;;92342:35:::2;::::0;92366:10:::2;::::0;92342:35:::2;::::0;;;::::2;59162:1;;59174:20:::1;:18;:20::i;129776:41::-:0;;;;:::o;74582:2330::-;74639:36;;:::i;:::-;59104:19;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;74688:20:::1;74711:11;:9;:11::i;:::-;74688:34;;74733:12;74748:16;:14;:16::i;:::-;74733:31;;74775:41;;:::i;:::-;74819:6;:4;:6::i;:::-;74775:50:::0;-1:-1:-1;74915:25:0::1;74775:50:::0;74938:1:::1;74915:25;:22;:25;:::i;:::-;74911:74;;;-1:-1:-1::0;74957:16:0::1;::::0;-1:-1:-1;;74957:16:0::1;74911:74;75088:4;75069:15;;:23;75065:72;;;-1:-1:-1::0;75109:16:0::1;::::0;-1:-1:-1;;75109:16:0::1;75065:72;75150:37;;:::i;:::-;75189:38;;:::i;:::-;75269:15;::::0;75231:112:::1;::::0;-1:-1:-1;;;75231:112:0;;-1:-1:-1;;;;;75231:23:0;::::1;::::0;::::1;::::0;:112:::1;::::0;75269:15;75299:4;;75318:14;;75231:112:::1;;;;;;::::0;::::1;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;75231:112:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;75231:112:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;75231:112:0;;;;;;;;;75354:15;:22:::0;;;75149:194;;-1:-1:-1;75149:194:0;-1:-1:-1;75401:27:0::1;75149:194:::0;;75401:27:::1;:14;:27;:::i;:::-;75389:39:::0;-1:-1:-1;75443:20:0::1;75389:39:::0;75461:1:::1;75443:20;:17;:20;:::i;:::-;75439:69;;;-1:-1:-1::0;75480:16:0::1;::::0;-1:-1:-1;;;;75480:16:0::1;75439:69;75886:39;:9:::0;75910:14;75886:39:::1;:23;:39;:::i;:::-;75882:483;;;75942:34;;:::i;:::-;75979:29;:9:::0;75993:14;75979:29:::1;:13;:29;:::i;:::-;75942:66;;76023:47;;:::i;:::-;76073:36;76088:11;76101:7;76073:14;:36::i;:::-;76023:86:::0;-1:-1:-1;76138:37:0::1;:11:::0;76023:86;76138:37:::1;:15;:37;:::i;:::-;76124:51:::0;-1:-1:-1;76200:33:0::1;:7:::0;76212:20;76200:33:::1;:11;:33;:::i;:::-;76190:43;;76261:51;76276:35;76291:10;76303:7;76276:14;:35::i;:::-;76261:10:::0;;:51:::1;:14;:51;:::i;:::-;76248:64;;76339:14;76327:26;;75882:483;;;76419:20:::0;;76398:19;;76382:58:::1;::::0;::::1;::::0;76419:20:::1;::::0;76382:58:::1;76453:57;76484:9;76495:14;76453:30;:57::i;:::-;76527:27;:10:::0;76552:1:::1;76527:27;:24;:27;:::i;:::-;76523:217;;;76628:19:::0;;76571:18:::1;::::0;:77:::1;::::0;-1:-1:-1;;;;;76571:18:0;;::::1;::::0;76620:5;;76571:77:::1;:40;:77;:::i;:::-;76696:18;::::0;76663:65:::1;::::0;-1:-1:-1;;;76663:65:0;;-1:-1:-1;;;;;76663:24:0;;::::1;::::0;::::1;::::0;:65:::1;::::0;76696:18;;::::1;::::0;76717:10;;76663:65:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;76663:65:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;76663:65:0;;;;76523:217;76756:28;:11:::0;76782:1:::1;76756:28;:25;:28;:::i;:::-;76752:126;;;76845:20:::0;;76801:18:::1;::::0;:65:::1;::::0;-1:-1:-1;;;;;76801:18:0;;::::1;::::0;76833:10:::1;::::0;76801:65:::1;:31;:65;:::i;:::-;-1:-1:-1::0;;;;;59162:1:0::1;59174:20:::0;:18;:20::i;96835:1274::-;97042:42;;:::i;:::-;88523:20;:18;:20::i;:::-;96972:10:::1;89094:40;89126:7;89094:31;:40::i;:::-;72755:16:::2;:14;:16::i;:::-;;59104:19:::3;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;97102:33:::4;97138:28;97155:10;97138:16;:28::i;:::-;97102:64:::0;-1:-1:-1;97185:33:0::4;:16:::0;97216:1:::4;97185:33;:30;:33;:::i;:::-;97177:71;;;;-1:-1:-1::0;;;97177:71:0::4;;;;;;;;;97521:68;97558:12;97572:16;97521:36;:68::i;:::-;97630:24:::0;;97607:48:::4;::::0;97503:86;;-1:-1:-1;97630:24:0;97618:10:::4;::::0;97607:48:::4;::::0;97630:24:::4;::::0;97607:48:::4;98076:24:::0;;98032:18:::4;::::0;:69:::4;::::0;-1:-1:-1;;;;;98032:18:0;;::::4;::::0;98064:10:::4;::::0;98032:69:::4;:31;:69;:::i;:::-;59162:1;59174:20:::3;:18;:20::i;:::-;88554:1:::1;96835:1274:::0;;;:::o;114545:241::-;114658:42;;:::i;:::-;59400:19;:17;:19::i;:::-;114725:53:::1;::::0;;::::1;::::0;::::1;::::0;;;114751:26:::1;114725:53:::0;;;::::1;::::0;:25:::1;:53::i;:::-;114718:60;;114545:241:::0;:::o;129536:48::-;;;;:::o;129128:57::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;129128:57:0;;;;-1:-1:-1;129128:57:0;;;;-1:-1:-1;;;;129128:57:0;;;;;;;;;;;;;;;;;;;;;;:::o;129235:51::-;;;;:::o;85601:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;92827:1093::-;88523:20;:18;:20::i;:::-;92967:10:::1;89094:40;89126:7;89094:31;:40::i;:::-;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;93041:141:::3;93137:30;93165:1;93137:27;:30::i;:::-;-1:-1:-1::0;;;;;93067:28:0;::::3;;::::0;;;:9:::3;:28;::::0;;;;;;;;93041:69;;;;::::3;::::0;;;93067:42:::3;::::0;;::::3;93041:69:::0;;;::::3;::::0;:25:::3;:69::i;:::-;:77:::0;:141:::3;:77;:141;:::i;:::-;93019:219;;;;-1:-1:-1::0;;;93019:219:0::3;;;;;;;;;93249:33;93285:28;93302:10;93285:16;:28::i;:::-;93249:64;;93346:12;:49;;;93399:1;93346:54;;:144;;;;;93474:16;:14;:16::i;:::-;93421:12;:49;;;:69;;93346:144;93324:218;;;;-1:-1:-1::0;;;93324:218:0::3;;;;;;;;;93643:1;93591:49;::::0;;::::3;:53:::0;;;-1:-1:-1;;;;;93657:28:0;::::3;::::0;;;:9:::3;:28;::::0;;;;;:43;;;;::::3;::::0;;::::3;::::0;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;::::3;::::0;;;;;::::3;::::0;;;;93728:10:::3;93718:21:::0;;;;;;93711:28;;;;;::::3;::::0;;;;;::::3;::::0;;;;;::::3;::::0;;;;;;::::3;::::0;;;93757:62;;93657:28;;93728:10;;93757:62:::3;::::0;93643:1;93757:62:::3;93835:29;::::0;-1:-1:-1;;;;;93835:29:0;::::3;::::0;::::3;::::0;;;::::3;93880:32;::::0;93901:10:::3;::::0;93880:32:::3;::::0;;;::::3;59162:1;59174:20:::2;:18;:20::i;:::-;88554:1:::1;92827:1093:::0;:::o;130192:51::-;;;;:::o;104816:2061::-;105014:42;;:::i;:::-;88523:20;:18;:20::i;:::-;104944:10:::1;89094:40;89126:7;89094:31;:40::i;:::-;72755:16:::2;:14;:16::i;:::-;;59104:19:::3;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;105074:33:::4;105110:28;105127:10;105110:16;:28::i;:::-;105158:55;::::0;;::::4;::::0;::::4;::::0;;;;;;;105074:64;;-1:-1:-1;105158:55:0::4;::::0;:9;;:55:::4;:23;:55;:::i;:::-;105157:56;105149:89;;;;-1:-1:-1::0;;;105149:89:0::4;;;;;;;;;105251:43;;:::i;:::-;105297:45;::::0;;::::4;::::0;::::4;::::0;;;;;;;::::4;::::0;:9;;:45:::4;:13;:45;:::i;:::-;105251:91;;105353:45;;:::i;:::-;105436:53;::::0;;::::4;::::0;::::4;::::0;;;105462:26:::4;::::0;::::4;105436:53:::0;;;105401:99:::4;::::0;105436:53:::4;::::0;:25:::4;:53::i;:::-;105401:16:::0;;:99:::4;:20;:99;:::i;:::-;105629:38;::::0;;::::4;::::0;::::4;::::0;;;;;;;105353:147;;-1:-1:-1;105629:49:0::4;::::0;105668:9;105629:49:::4;:38;:49;:::i;:::-;105625:853;;;105713:34;105736:10;105713:22;:34::i;:::-;105695:52;;105625:853;;;105880:62;105909:12;105923:18;105880:28;:62::i;:::-;105862:80;;106060:40;;:::i;:::-;106103:34;::::0;;::::4;::::0;::::4;::::0;;;;;;;:45:::4;::::0;106138:9;106103:45:::4;:34;:45;:::i;:::-;106171:52;::::0;;::::4;::::0;::::4;::::0;;;106206:16:::4;106171:52:::0;;;106060:88;;-1:-1:-1;106171:52:0::4;::::0;106060:88;;106171:52:::4;:34;:52;:::i;:::-;106163:95;;;;-1:-1:-1::0;;;106163:95:0::4;;;;;;;;;106273:46:::0;;;;106429:26:::4;::::0;;::::4;::::0;::::4;::::0;;;:22:::4;:26:::0;;;:37:::4;::::0;106456:9;106429:37:::4;:26;:37;:::i;:::-;106404:62:::0;:22:::4;:62:::0;-1:-1:-1;105625:853:0::4;106540:18:::0;;106514:24;;106495:64:::4;::::0;106502:10:::4;::::0;106495:64:::4;::::0;106540:18:::4;::::0;106495:64:::4;106707:24:::0;;106663:18:::4;::::0;:69:::4;::::0;-1:-1:-1;;;;;106663:18:0;;::::4;::::0;106695:10:::4;::::0;106663:69:::4;:31;:69;:::i;:::-;106801:18:::0;;106743:13:::4;::::0;:77:::4;::::0;-1:-1:-1;;;;;106743:13:0;;::::4;::::0;106774:10:::4;::::0;106794:4:::4;::::0;106743:77:::4;:30;:77;:::i;:::-;106831:13;::::0;106850:18;;106831:38:::4;::::0;-1:-1:-1;;;106831:38:0;;-1:-1:-1;;;;;106831:13:0;;::::4;::::0;:18:::4;::::0;:38:::4;::::0;::::4;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::4;2:2;106831:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::4;77:16;74:1;67:27;5:2;106831:38:0;;;;59162:1;;;59174:20:::3;:18;:20::i;102755:1492::-:0;88523:20;:18;:20::i;:::-;72755:16:::1;:14;:16::i;:::-;;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;102963:52:::3;102987:16;103005:9;102963:23;:52::i;:::-;102955:77;;;;-1:-1:-1::0;;;102955:77:0::3;;;;;;;;;103091:10;103045:33;103081:21:::0;;;:9:::3;:21;::::0;;;;103121:43:::3;::::0;::::3;::::0;:48;103113:79:::3;;;;-1:-1:-1::0;;;103113:79:0::3;;;;;;;;;103207:38;::::0;;::::3;::::0;::::3;::::0;;;;;;;:41:::3;::::0;103246:1:::3;103207:41;:38;:41;:::i;:::-;103203:207;;;103273:48;::::0;;::::3;::::0;::::3;::::0;;;103304:16:::3;103273:48:::0;;;::::3;::::0;:9;;:48:::3;:30;:48;:::i;:::-;103265:91;;;;-1:-1:-1::0;;;103265:91:0::3;;;;;;;;;103376:22;::::0;103387:10:::3;::::0;103376:22:::3;::::0;;;::::3;103203:207;103508:60;103537:12;103551:16;103508:28;:60::i;:::-;-1:-1:-1::0;103697:34:0::3;::::0;;::::3;::::0;::::3;::::0;;;;;;;:45:::3;::::0;103732:9;103697:45:::3;:34;:45;:::i;:::-;103664:78:::0;;;103780:26:::3;::::0;;::::3;::::0;::::3;::::0;;;:22:::3;:26:::0;;;:37:::3;::::0;103807:9;103780:37:::3;:26;:37;:::i;:::-;103755:62:::0;:22:::3;:62:::0;103890:18;;103863:25;;103835:74:::3;::::0;103851:10:::3;::::0;103835:74:::3;::::0;103755:62:::3;::::0;103835:74:::3;104108:25:::0;;104045:18:::3;::::0;:89:::3;::::0;-1:-1:-1;;;;;104045:18:0;;::::3;::::0;104081:10:::3;::::0;104101:4:::3;::::0;104045:89:::3;:35;:89;:::i;:::-;104153:13;::::0;104184:18;;104153:50:::3;::::0;-1:-1:-1;;;104153:50:0;;-1:-1:-1;;;;;104153:13:0;;::::3;::::0;:18:::3;::::0;:50:::3;::::0;104172:10:::3;::::0;104184:18;104153:50:::3;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::3;2:2;104153:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;104153:50:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;104153:50:0;;;;;;;;;104145:94;;;;-1:-1:-1::0;;;104145:94:0::3;;;;;;;;;59162:1;59174:20:::2;:18;:20::i;86214:35::-:0;;;-1:-1:-1;;;;;86214:35:0;;:::o;111279:412::-;88612:21;:19;:21::i;:::-;88993:16:::1;:14;:16::i;:::-;72755::::2;:14;:16::i;:::-;;59104:19:::3;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;111376:13:::4;:51:::0;;-1:-1:-1;;111376:51:0::4;111392:35;111376:51;::::0;;111538:49:::4;111560:4;111567:19;:17;:19::i;:::-;111538:13;:49::i;:::-;111598:40;111618:19;;111598;:40::i;:::-;111656:27;::::0;111672:10:::4;::::0;111656:27:::4;::::0;;;::::4;59174:20:::3;:18;:20::i;77390:115::-:0;77445:26;;:::i;:::-;59400:19;:17;:19::i;:::-;77491:6:::1;:4;:6::i;84516:34::-:0;;;;;;:::o;86102:53::-;;;;:::o;86711:43::-;;;;:::o;86311:30::-;;;;:::o;114000:319::-;114118:43;;:::i;:::-;59400:19;:17;:19::i;:::-;-1:-1:-1;;;;;114278:18:0;::::1;;::::0;;;:9:::1;:18;::::0;;;;;;;;114252:59;;;;::::1;::::0;;;114278:32:::1;::::0;;::::1;114252:59:::0;;;::::1;::::0;:25:::1;:59::i;:::-;114245:66:::0;114000:319;-1:-1:-1;;114000:319:0:o;86462:34::-;;;;:::o;86611:33::-;;;;:::o;149176:214::-;149296:40;59400:19;:17;:19::i;:::-;-1:-1:-1;;;;;149361:21:0;::::1;;::::0;;;:12:::1;:21;::::0;;;;;;;149354:28;;;;;;::::1;::::0;;;;;;;;;;;;149361:21;;149354:28;::::1;;;;;;;;;::::0;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;-1:-1:-1;;;;;149354:28:0;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;;;;;;-1:-1:-1;;;149354:28:0;::::1;;;;::::0;::::1;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;149354:28:0::1;::::0;;;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;;;;;;;;;;::::1;::::0;::::1;;;;;;;;;;149176:214:::0;;;:::o;140721:1646::-;140898:36;;:::i;:::-;140816:13;140831:7;131533:35;131545:13;131560:7;131533:11;:35::i;:::-;72755:16:::1;:14;:16::i;:::-;;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;140952:43:::3;140998;141018:7;141027:13;140998:19;:43::i;:::-;140952:89;;141171:44;;:::i;:::-;141293:64;::::0;;::::3;::::0;::::3;::::0;;;141319:37:::3;::::0;::::3;141293:64:::0;;;141218:150:::3;::::0;141293:64:::3;::::0;:25:::3;:64::i;:::-;141218:56;::::0;;::::3;::::0;;::::3;::::0;;141259:14:::3;141218:56:::0;;;:40;;;;::::3;::::0;;;:36:::3;::::0;::::3;:40:::0;;;:56:::3;::::0;:40;:56:::3;:40;:56;:::i;:150::-;141171:197;;141379:59;141394:24;141420:17;141379:14;:59::i;:::-;-1:-1:-1::0;141547:25:0::3;::::0;::::3;:49:::0;;-1:-1:-1;;;;141547:49:0::3;-1:-1:-1::0;;;141547:49:0::3;::::0;;141607:28:::3;::::0;::::3;:41:::0;;-1:-1:-1;;;;;;141607:41:0::3;141638:10;141607:41;::::0;;141575:21:::3;141725:35:::0;::::3;::::0;141705:56:::3;::::0;:19:::3;:56::i;:::-;141835:30;::::0;::::3;::::0;141933:26;;141779:191:::3;::::0;141880:10:::3;::::0;-1:-1:-1;;;;;141835:30:0;;::::3;::::0;141779:191;;::::3;::::0;::::3;::::0;::::3;::::0;141905:13;;141933:26;141779:191:::3;;;;;;;;;;141993:51;::::0;;::::3;::::0;::::3;::::0;;;142015:28:::3;::::0;::::3;141993:51:::0;;;::::3;::::0;:17;;:51:::3;:21;:51;:::i;:::-;142122:55;::::0;;::::3;::::0;::::3;::::0;;;142148:28:::3;::::0;::::3;142122:55:::0;;;141981:63;;-1:-1:-1;142122:55:0::3;::::0;142136:10:::3;::::0;142122:13:::3;:55::i;:::-;142332:26:::0;;142269:18:::3;::::0;:90:::3;::::0;-1:-1:-1;;;;;142269:18:0;;::::3;::::0;142305:10:::3;::::0;142325:4:::3;::::0;142269:90:::3;:35;:90;:::i;:::-;59162:1;;59174:20:::2;:18;:20::i;94007:423::-:0;88523:20;:18;:20::i;:::-;59104:19:::1;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;94096:33:::2;94132:28;94149:10;94132:16;:28::i;:::-;94096:64;;94179:12;:49;;;94232:1;94179:54;;94171:86;;;;-1:-1:-1::0;;;94171:86:0::2;;;;;;;;;94275:43;::::0;94307:10:::2;::::0;94275:43:::2;::::0;;;::::2;94421:1;94369:49;::::0;;::::2;:53:::0;59174:20:::1;:18;:20::i;71528:29::-:0;;;-1:-1:-1;;;;;71528:29:0;;:::o;98440:1015::-;88523:20;:18;:20::i;:::-;98586:10:::1;89094:40;89126:7;89094:31;:40::i;:::-;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;98638:33:::3;98674:28;98691:10;98674:16;:28::i;:::-;98638:64:::0;-1:-1:-1;98735:33:0::3;:16:::0;98766:1:::3;98735:33;:30;:33;:::i;:::-;:143;;;;-1:-1:-1::0;98824:53:0::3;::::0;;::::3;::::0;::::3;::::0;;;98850:26:::3;::::0;::::3;98824:53:::0;;;98789:89:::3;::::0;98824:53:::3;::::0;:25:::3;:53::i;:::-;98789:16:::0;;:89:::3;:34;:89;:::i;:::-;98713:218;;;;-1:-1:-1::0;;;98713:218:0::3;;;;;;;;;99026:23;99052:40;99073:18;;99052:16;:14;:16::i;:40::-;99026:66;;99129:19;;99111:15;:37;99103:77;;;;-1:-1:-1::0;;;99103:77:0::3;;;;;;;;;99246:43;::::0;::::3;:61:::0;;;99318:55;;:36:::3;::::0;::::3;:55:::0;;;99391:56:::3;::::0;99409:10:::3;::::0;99391:56:::3;::::0;99318:55:::3;::::0;99391:56:::3;59162:1;;59174:20:::2;:18;:20::i;113516:98::-:0;88523:20;:18;:20::i;:::-;59104:19:::1;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;59174:20;:18;:20::i;129979:50::-:0;;;;:::o;96075:224::-;96252:39;96262:10;96274:16;96252:9;:39::i;:::-;96075:224;:::o;72204:50::-;;;;:::o;86809:38::-;;;;:::o;107513:3422::-;107644:42;;:::i;:::-;88612:21;:19;:21::i;:::-;72755:16:::1;:14;:16::i;:::-;;59104:19:::2;:17;:19::i;:::-;59134:17;:15;:17::i;:::-;107842:18:::3;107825:13;::::0;::::3;;:35;::::0;::::3;;;;;;;;107817:66;;;;-1:-1:-1::0;;;107817:66:0::3;;;;;;;;;108011:34;107994:13;::::0;::::3;;:51;::::0;::::3;;;;;;;107990:199;;108076:36;108092:19;;108076:15;:36::i;:::-;108062:50:::0;:11:::3;:50:::0;108127:13:::3;:50:::0;;-1:-1:-1;;108127:50:0::3;108143:34;108127:50;::::0;;107990:199:::3;108294:41;;:::i;:::-;108338:56;::::0;;::::3;::::0;::::3;::::0;;;;108358:13:::3;::::0;-1:-1:-1;;;108358:35:0;;;108338:56;;;-1:-1:-1;;;;;108358:13:0::3;:23;:35;108382:10;108358:35:::0;;;::::3;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::3;2:2;108358:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;108358:35:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;108358:35:0;;;;;;;;;108338:56:::0;;108294:100;-1:-1:-1;108405:52:0::3;;:::i;:::-;108460:31;::::0;;::::3;::::0;::::3;::::0;;;108479:11:::3;108460:31:::0;;;::::3;::::0;:14;;:31:::3;:18;:31;:::i;:::-;108685:10;108639:33;108675:21:::0;;;:9:::3;:21;::::0;;;;;;;108711:53;;;;::::3;::::0;;;108737:26:::3;::::0;::::3;108711:53:::0;;;108405:86;;-1:-1:-1;108711:70:0::3;::::0;108639:33;108711:53:::3;::::0;:25:::3;:53::i;:::-;:67:::0;:70:::3;:67;:70;:::i;:::-;108707:1208;;;108909:53;;:::i;:::-;108965:47;::::0;;::::3;::::0;;::::3;::::0;;109000:11:::3;108965:47:::0;;;:34;;;;::::3;::::0;;;;;;;:47:::3;::::0;:34;:47:::3;:34;:47;:::i;:::-;108909:103;;109027:45;;:::i;:::-;109075:53;::::0;;::::3;::::0;::::3;::::0;;;109101:26:::3;::::0;::::3;109075:53:::0;;;::::3;::::0;:25:::3;:53::i;:::-;109027:101;;109244:55;;:::i;:::-;109302:89;:26:::0;109358:18;109302:89:::3;:37;:89;:::i;:::-;:201;;109481:22;;;;;;;;109501:1;109481:22;;::::0;109302:201:::3;;;109411:50;:18:::0;109434:26;109411:50:::3;:22;:50;:::i;:::-;109244:259:::0;-1:-1:-1;109654:59:0::3;:25:::0;109244:259;109654:59:::3;:29;:59;:::i;:::-;109840:10;109830:21;::::0;;;:9:::3;:21;::::0;;;;;109823:28;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;;::::0;;;109871:32;109626:87;;-1:-1:-1;109840:10:0;;109871:32:::3;::::0;109830:21;109871:32:::3;108707:1208;;;;110124:33;;:::i;:::-;110189:53;::::0;;::::3;::::0;::::3;::::0;;;110215:26:::3;110189:53:::0;;;110160:133:::3;::::0;110189:53:::3;::::0;:25:::3;:53::i;:::-;110257:25;110160:14;:133::i;:::-;110124:169;;110394:53;110412:26;110440:6;110394:17;:53::i;:::-;110483:26;::::0;;::::3;::::0;::::3;::::0;;;:22:::3;:26:::0;;;110376:71;;-1:-1:-1;110483:42:0::3;::::0;110510:14;110483:42:::3;:26;:42;:::i;:::-;110458:67:::0;:22:::3;:67:::0;110603:23;;110577:24;;110543:84:::3;::::0;110565:10:::3;::::0;110543:84:::3;::::0;110458:67:::3;::::0;110543:84:::3;110755:24:::0;;110711:18:::3;::::0;:69:::3;::::0;-1:-1:-1;;;;;110711:18:0;;::::3;::::0;110743:10:::3;::::0;110711:69:::3;:31;:69;:::i;:::-;110849:23:::0;;110791:13:::3;::::0;:82:::3;::::0;-1:-1:-1;;;;;110791:13:0;;::::3;::::0;110822:10:::3;::::0;110842:4:::3;::::0;110791:82:::3;:30;:82;:::i;:::-;110884:13;::::0;110903:23;;110884:43:::3;::::0;-1:-1:-1;;;110884:43:0;;-1:-1:-1;;;;;110884:13:0;;::::3;::::0;:18:::3;::::0;:43:::3;::::0;::::3;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::3;2:2;110884:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;110884:43:0;;;;59162:1;;;;59174:20:::2;:18;:20::i;122652:138::-:0;122734:19;;122715:16;:14;:16::i;:::-;:38;122707:75;;;;-1:-1:-1;;;122707:75:0;;;;;;;;123545:183;123636:25;123653:7;123636:16;:25::i;:::-;:56;;;:61;123628:92;;;;-1:-1:-1;;;123628:92:0;;;;;;;;59941:189;60075:11;;-1:-1:-1;;;60075:11:0;;;;60067:55;;;;-1:-1:-1;;;60067:55:0;;;;;;;;60138:139;60264:5;60250:19;;-1:-1:-1;;;;60250:19:0;;;60138:139::o;16730:149::-;16806:4;16843:19;16860:1;16843:16;:19::i;:::-;:28;16830:10;;:41;;-1:-1:-1;16730:149:0;;;;:::o;117972:209::-;118110:20;118083:7;88725:36;88753:7;88725:27;:36::i;:::-;-1:-1:-1;;;;;;;118155:18:0::1;;::::0;;;:9:::1;:18;::::0;;;;;117972:209::o;120246:346::-;120407:26;;:::i;:::-;120446:60;120461:12;:26;;120489:16;120446:14;:60::i;:::-;;120524;120539:26;120567:16;120524:14;:60::i;:::-;120517:67;120246:346;-1:-1:-1;;;120246:346:0:o;11741:205::-;11842:96;11862:5;11892:27;;;11921:4;11927:2;11931:5;11869:68;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;11869:68:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;11869:68:0;;;179:29:-1;;;;160:49;;;11842:19:0;:96::i;:::-;11741:205;;;;:::o;60285:210::-;60469:11;:18;;-1:-1:-1;;;;60469:18:0;-1:-1:-1;;;60469:18:0;;;60285:210::o;119893:223::-;120020:30;120048:1;120020:27;:30::i;:::-;119981:69;:36;;;:69;;120061:43;;;;:47;119893:223::o;20384:148::-;20458:15;;:::i;:::-;20506:10;;20493;;:23;:31;;20523:1;20493:31;;;-1:-1:-1;20519:1:0;;20384:148;-1:-1:-1;20384:148:0:o;79772:239::-;79899:37;;:::i;:::-;79961:42;;;;;;;;;79979:23;79961:42;;;;;:13;;:42;:17;:42;:::i;15474:137::-;15534:15;;:::i;:::-;15569:34;;;;;;;;;;15578:24;:1;15177:6;15578:24;:5;:24;:::i;:::-;15569:34;;15562:41;15474:137;-1:-1:-1;;15474:137:0:o;19382:144::-;19508:10;19494;;:24;;;19382:144::o;21739:153::-;21813:15;;:::i;:::-;21848:36;;;;;;;;;21872:10;;21857;;21848:36;;21857:26;;:10;:26;:14;:26;:::i;:::-;21848:36;;21841:43;21739:153;-1:-1:-1;;;21739:153:0:o;22849:658::-;22923:15;;:::i;:::-;23443:56;;;;;;;;;23467:10;;23452;;23443:56;;15177:6;;23452:26;;;:14;:26;:::i;:::-;:46;;;;;;23443:56;;23436:63;22849:658;-1:-1:-1;;;22849:658:0:o;17398:147::-;17527:10;17513;;:24;;;17398:147::o;79290:211::-;79342:36;;:::i;:::-;79391:20;79414:11;:9;:11::i;:::-;79473:18;;79443:50;;-1:-1:-1;;;79443:50:0;;79391:34;;-1:-1:-1;;;;;;79443:21:0;;;;;;:50;;79473:18;;79443:50;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79443:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79443:50:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;79443:50:0;;;;;;;;;79436:57;;;79290:211;:::o;25321:641::-;25395:15;;:::i;:::-;25895:59;;;;;;;;;25942:10;;25904;;25895:59;;25904:49;;:33;;15177:6;25904:33;:14;:33;:::i;:::-;:37;:49;:37;:49;:::i;115148:1510::-;115403:33;115439:25;115456:7;115439:16;:25::i;:::-;115567:54;;;;;;;;;;;;;115403:61;;-1:-1:-1;115567:54:0;;:14;;:54;:22;:54;:::i;:::-;:152;;;;-1:-1:-1;115638:53:0;;;;;;;;;115664:26;;;115638:53;;;:81;;115700:18;;115638:53;;:25;:53::i;:81::-;115549:261;;;115746:31;115769:7;115746:22;:31::i;:::-;;115792:7;;;115549:261;115900:62;115929:12;115943:18;115900:28;:62::i;:::-;;116064:40;;:::i;:::-;116107:34;;;;;;;;;;;;;:50;;116142:14;116107:50;:34;:50;:::i;:::-;116176:52;;;;;;;;;116211:16;116176:52;;;116064:93;;-1:-1:-1;116176:52:0;;116064:93;;116176:52;:34;:52;:::i;:::-;116168:95;;;;-1:-1:-1;;;116168:95:0;;;;;;;;;116274:46;;;;116428:40;;;;;;;;;:36;;;:40;;;:66;;116469:24;116428:66;:40;:66;:::i;:::-;116389:105;:36;;;:105;116608:26;;;;;;;;;:22;:26;;;:42;;116635:14;116608:42;:26;:42;:::i;:::-;116583:67;:22;:67;-1:-1:-1;;115148:1510:0;;;;:::o;21045:153::-;21119:15;;:::i;:::-;21154:36;;;;;;;;;21178:10;;21163;;21154:36;;21163:26;;:10;:26;:14;:26;:::i;82481:569::-;82628:42;;:::i;:::-;82688:41;;:::i;:::-;82732:40;;;;;;;;;;;;;;;:25;:40::i;:::-;82688:84;;82783:45;;:::i;:::-;82831:40;82855:15;82831:23;:40::i;:::-;82907:17;;;;;;;;;;;;;82783:88;;-1:-1:-1;82907:37:0;;82783:88;82907:37;:17;:37;:::i;:::-;:46;82882:71;;;82982:40;;;;;;;;;;;;:60;;83027:14;;82982:40;;:25;:40::i;:60::-;82964:78;82481:569;-1:-1:-1;;;;;82481:569:0:o;80259:234::-;80381:40;;:::i;:::-;80446:39;;;;;;;;;80461:23;80446:39;;;;;:10;;:39;:14;:39;:::i;16414:139::-;16535:10;16522;;:23;;16414:139::o;121064:352::-;121225:26;;:::i;:::-;121264:63;121282:12;:26;;121310:16;121264:17;:63::i;:::-;;121345;121363:26;121391:16;121345:17;:63::i;11556:177::-;11639:86;11659:5;11689:23;;;11714:2;11718:5;11666:58;;;;;;;;;;122511:133;122587:18;122570:13;;;;:35;;;;;;;;;122562:74;;;;-1:-1:-1;;;122562:74:0;;;;;;;;118579:177;118675:6;;:73;;-1:-1:-1;;;118675:73:0;;118648:7;;-1:-1:-1;;;;;118675:6:0;;:31;;:73;;118707:40;;118675:73;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;118675:73:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118675:73:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;118675:73:0;;;;;;;;118847:179;118919:22;118944:12;:10;:12::i;:::-;118987:15;;118967:51;;-1:-1:-1;;;118967:51:0;;118919:37;;-1:-1:-1;;;;;;118967:19:0;;;;;:51;;119004:13;;118967:51;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;118967:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118967:51:0;;;;118847:179;;:::o;153186:516::-;153274:35;153312:43;153332:7;153341:13;153312:19;:43::i;:::-;153381:17;;;;;;;-1:-1:-1;;;;153381:17:0;;;;;;153501:5;:25;;;;;;;;;153500:138;;;;153588:16;:14;:16::i;:::-;153550:34;153572:11;153550:21;:34::i;:::-;:54;;153549:88;;;;-1:-1:-1;153619:17:0;153610:5;:26;;;;;;;;;153549:88;153478:216;;;;-1:-1:-1;;;153478:216:0;;;;;;;;151701:645;-1:-1:-1;;;;;151918:21:0;;151820:35;151918:21;;;:12;:21;;;;;152151:23;;152135:39;;:104;;;;-1:-1:-1;152219:20:0;152178:16;152195:13;152178:31;;;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;:61;;;;;;;;;;152135:104;152113:176;;;;-1:-1:-1;;;152113:176:0;;;;;;;;;152307:16;152324:13;152307:31;;;;;;;;;;;;;;;;;;152300:38;;;151701:645;;;;:::o;149758:1756::-;149835:35;149873:43;149893:7;149902:13;149873:19;:43::i;:::-;149835:81;-1:-1:-1;150161:21:0;150140:17;;;;-1:-1:-1;;;150140:17:0;;;;:42;;;;;;;;;150136:81;;150199:7;;;150136:81;150353:44;150369:11;:27;;;150353:15;:44::i;:::-;150323:74;:27;;;:74;150481:47;;:::i;:::-;150531:86;;;;;;;;;150579:27;;;150531:86;;;:33;;;;;;;;:29;;;:33;;;:86;;:33;:86;:33;:86;:::i;:::-;150481:136;;150736:45;;:::i;:::-;150784:47;;;;;;;;;150809:21;150784:47;;;;;:20;;:47;:24;:47;:::i;:::-;151116:53;;;;;;;;;:32;;;:53;;;150736:95;;-1:-1:-1;151092:21:0;;151116:73;;150736:95;151116:73;:53;:73;:::i;:::-;151092:97;;151220:16;:65;;151265:20;151220:65;;;151239:23;151220:65;151200:17;;;:85;;-1:-1:-1;;;;151200:85:0;-1:-1:-1;;;151200:85:0;;;;;;;;;;;;;-1:-1:-1;151379:22:0;;;;151416:20;;;;151303:203;;-1:-1:-1;;;;;151379:22:0;;;;151303:203;;;;151332:10;;151303:203;;;;151416:20;;151451:13;;151479:16;;151303:203;;;;;;;;;;149758:1756;;;;;;:::o;81080:582::-;81233:44;;:::i;:::-;81295:41;;:::i;:::-;81339:40;;;;;;;;;;;;;;;:25;:40::i;:::-;81295:84;;81390:45;;:::i;:::-;81438:43;81462:18;81438:23;:43::i;:::-;81517:17;;;;;;;;;;;;;81390:91;;-1:-1:-1;81517:37:0;;81390:91;81517:37;:17;:37;:::i;:::-;:46;81492:71;;;81613:40;;;;;;;;;;;;81594:60;;81613:40;;:25;:40::i;:::-;81594:14;;:60;:18;:60;:::i;913:181::-;971:7;1003:5;;;1027:6;;;;1019:46;;;;-1:-1:-1;;;1019:46:0;;;;;;;;79125:157;79218:6;;:55;;-1:-1:-1;;;79218:55:0;;79169:14;;-1:-1:-1;;;;;79218:6:0;;:31;;:55;;-1:-1:-1;;;79250:22:0;79218:55;;;;151522:171;151570:26;;:::i;:::-;151633:51;;;;;;;;;151659:24;151633:51;;;151616:69;;151633:51;;:25;:51::i;:::-;151616:12;:10;:12::i;15782:144::-;15852:4;15890:19;15907:1;15890:16;:19::i;:::-;:28;15876:10;;:42;;-1:-1:-1;15782:144:0;;;;:::o;83163:338::-;83311:39;;:::i;:::-;83353:26;:6;83368:10;83353:26;:14;:26;:::i;:::-;83311:68;;83416:77;83444:48;83479:12;83444:30;83472:1;83444:27;:30::i;:48::-;83416:27;;;;;;;;;:23;:27;;;;:77;:27;:77;:::i;:::-;83390:103;:23;:103;-1:-1:-1;;;83163:338:0:o;12584:286::-;12681:20;12704:50;12748:5;12704;-1:-1:-1;;;;;12704:15:0;;12728:4;12735:7;12704:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12704:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;12704:39:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;12704:39:0;;;;;;;;:50;12681:73;;12765:97;12785:5;12815:22;;;12839:7;12848:12;12792:69;;;;;;;;;;121785:441;121954:26;;:::i;:::-;121993:63;122011:12;:26;;122039:16;121993:17;:63::i;:::-;;122075:45;122107:12;122075:31;:45::i;:::-;122067:70;;;;-1:-1:-1;;;122067:70:0;;;;;;;;;122155:63;122173:26;122201:16;122155:17;:63::i;16100:134::-;16216:10;16202;;:24;;16100:134::o;116770:1023::-;116837:26;;:::i;:::-;116876:40;116919:25;116936:7;116919:16;:25::i;:::-;116876:68;;116957:51;;:::i;:::-;117011:53;;;;;;;;;117037:26;117011:53;;;;;:25;:53::i;:::-;116957:107;;117160:49;;:::i;:::-;-1:-1:-1;117160:85:0;;;;;;;;;117212:33;;;117160:85;;;117285:30;;;;;;;;:26;:30;;;117160:85;117285:54;;117160:85;117285:54;:30;:54;:::i;:::-;117256:83;:26;:83;117375:65;;;;;;;;;;;;;:26;;;;;;;;:22;:26;;;:65;;:26;:65;:26;:65;:::i;:::-;117350:90;:22;:90;-1:-1:-1;;;;;117541:18:0;;117350:90;117541:18;;;:9;:18;;;;;;117534:25;;;;;;;;;;;;;;;;;;;;;;;;;;117577:29;;;117350:90;117577:29;117731:53;;;;;;;;;117757:26;117731:53;;;117702:83;;117731:53;;:25;:53::i;124335:518::-;124494:4;124516:33;;:::i;:::-;124593:53;;;;;;;;;124619:26;124593:53;;;124552:142;;124593:53;;:25;:53::i;:::-;124552:142;;;;;;;;;124661:22;124552:142;;;:26;:142::i;:::-;124516:178;;124705:37;;:::i;:::-;124745:49;124772:10;124784:9;124745:26;:49::i;:::-;124705:89;-1:-1:-1;124813:32:0;:6;124705:89;124813:32;:20;:32;:::i;:::-;124812:33;;124335:518;-1:-1:-1;;;;;124335:518:0:o;122798:141::-;122882:19;;122862:16;:14;:16::i;:::-;:39;;122854:77;;;;-1:-1:-1;;;122854:77:0;;;;;;;;77961:1073;78058:17;:6;78073:1;78058:17;:14;:17;:::i;:::-;78054:56;;;78092:7;;78054:56;-1:-1:-1;;;;;78126:22:0;;78143:4;78126:22;78122:654;;78308:15;;78250:18;;:74;;-1:-1:-1;;;;;78250:18:0;;;;78286:5;;78301:4;;78250:74;:35;:74;:::i;:::-;78122:654;;;78453:41;;:::i;:::-;78497:6;:4;:6::i;:::-;78453:50;-1:-1:-1;78626:36:0;78453:50;78655:6;78626:36;:28;:36;:::i;:::-;78618:75;;;;-1:-1:-1;;;78618:75:0;;;;;;;;;78710:54;78741:6;78749:14;78710:30;:54::i;:::-;78122:654;;78807:15;;78793:30;;;;78807:15;;78793:30;78836:20;78859:11;:9;:11::i;:::-;78938:15;;78881:18;;78836:34;;-1:-1:-1;78881:73:0;;-1:-1:-1;;;;;78881:18:0;;78836:34;;78881:73;:40;:73;:::i;:::-;78998:18;;78965:61;;-1:-1:-1;;;78965:61:0;;-1:-1:-1;;;;;78965:24:0;;;;;;:61;;78998:18;;;;79019:6;;78965:61;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;78965:61:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;78965:61:0;;;;77961:1073;;;:::o;152817:361::-;152903:35;152941:43;152961:7;152970:13;152941:19;:43::i;:::-;152903:81;;153037:34;153059:11;153037:21;:34::i;:::-;153018:16;:14;:16::i;:::-;:53;153017:99;;;;-1:-1:-1;153098:17:0;153077;;;;-1:-1:-1;;;153077:17:0;;;;:38;;;;;;;;;153017:99;152995:175;;;;-1:-1:-1;;;152995:175:0;;;;;;;;119147:640;119218:26;;:::i;:::-;119358:22;119383:12;:10;:12::i;:::-;119430:15;;119414:47;;-1:-1:-1;;;119414:47:0;;119358:37;;-1:-1:-1;;;;;;119414:15:0;;;;;:47;;119447:13;;119414:47;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;119414:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;119414:47:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;119414:47:0;;;;;;;;;119406:83;;;;-1:-1:-1;;;119406:83:0;;;;;;;;;119537:15;;119521:47;;-1:-1:-1;;;119521:47:0;;119500:18;;-1:-1:-1;;;;;119521:15:0;;;;;:47;;119554:13;;119521:47;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;119521:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;119521:47:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;119521:47:0;;;;;;;;;119500:68;;119676:1;119662:11;:15;119658:63;;;-1:-1:-1;119708:1:0;119658:63;119738:41;;;;;;;;;;;;;119147:640;-1:-1:-1;;;119147:640:0:o;18416:136::-;18534:10;18521;;:23;;18416:136::o;122947:239::-;-1:-1:-1;;;;;123074:18:0;;123122:1;123074:18;;;:9;:18;;;;;;;;123048:59;;;;;;;;123074:32;;123048:59;;;:76;;123122:1;123048:59;;:25;:59::i;:76::-;123026:152;;;;-1:-1:-1;;;123026:152:0;;;;;;;;13600:1115;14205:27;14213:5;-1:-1:-1;;;;;14205:25:0;;:27::i;:::-;14197:71;;;;-1:-1:-1;;;14197:71:0;;;;;;;;;14342:12;14356:23;14391:5;-1:-1:-1;;;;;14383:19:0;14403:4;14383:25;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;14341:67:0;;;;14427:7;14419:52;;;;-1:-1:-1;;;14419:52:0;;;;;;;;;14488:17;;:21;14484:224;;14630:10;14619:30;;;;;;;;;;;;;;14611:85;;;;-1:-1:-1;;;14611:85:0;;;;;;;;2243:471;2301:7;2546:6;2542:47;;-1:-1:-1;2576:1:0;2569:8;;2542:47;2613:5;;;2617:1;2613;:5;:1;2637:5;;;;;:10;2629:56;;;;-1:-1:-1;;;2629:56:0;;;;;;;;1369:136;1427:7;1454:43;1458:1;1461;1454:43;;;;;;;;;;;;;;;;;:3;:43::i;3182:132::-;3240:7;3267:39;3271:1;3274;3267:39;;;;;;;;;;;;;;;;;:3;:39::i;118410:161::-;118506:6;;:56;;-1:-1:-1;;;118506:56:0;;118455:15;;-1:-1:-1;;;;;118506:6:0;;:31;;:56;;-1:-1:-1;;;118538:23:0;118506:56;;;;152354:178;152445:7;152472:52;152504:19;;152472:11;:27;;;:31;;:52;;;;:::i;117801:163::-;117857:26;;:::i;27133:407::-;27211:15;;:::i;:::-;27257:10;;27239:15;;27257:33;;15177:6;27257:33;:14;:33;:::i;:::-;27332:10;;27239:51;;-1:-1:-1;27301:16:0;;27320:23;;27239:51;;27320:23;:11;:23;:::i;:::-;27380:10;;27301:42;;-1:-1:-1;27354:11:0;;27368:23;;:7;;:23;:11;:23;:::i;:::-;27354:37;-1:-1:-1;27406:8:0;;27402:131;;27438:25;;;;;;;;;;27447:15;:8;27460:1;27447:15;:12;:15;:::i;:::-;27438:25;;;27431:32;;;;;;;27402:131;27503:18;;;;;;;;27512:8;27503:18;;;27496:25;;;;;;;123879:302;124056:53;;;;;;;;;124082:26;;;124056:53;;;123977:4;;124014:159;;124056:53;;:25;:53::i;:::-;124014:159;;;;;;;;;;;;;:23;:159::i;124861:381::-;125023:32;;:::i;:::-;125078:26;:9;125102:1;125078:26;:23;:26;:::i;:::-;125073:162;;125128:30;125156:1;125128:27;:30::i;:::-;125121:37;;;;125073:162;125198:25;:10;125213:9;125198:25;:14;:25;:::i;8945:619::-;9005:4;9473:20;;9316:66;9513:23;;;;;;:42;;-1:-1:-1;9540:15:0;;;9513:42;9505:51;8945:619;-1:-1:-1;;;;8945:619:0:o;1800:192::-;1886:7;1922:12;1914:6;;;;1906:29;;;;-1:-1:-1;;;1906:29:0;;;;;;;;;;-1:-1:-1;;;1958:5:0;;;1800:192::o;3802:345::-;3888:7;3990:12;3983:5;3975:28;;;;-1:-1:-1;;;3975:28:0;;;;;;;;;;;4014:9;4030:1;4026;:5;;;;;;;3802:345;-1:-1:-1;;;;;3802:345:0:o;4604:130::-;4662:7;4689:37;4693:1;4696;4689:37;;;;;;;;;;;;;;;;;5297:7;5333:12;5325:6;5317:29;;;;-1:-1:-1;;;5317:29:0;;;;;;;;;;;5368:1;5364;:5;;;;;;;5211:166;-1:-1:-1;;;;5211:166:0:o;153917:531::-;;;;;;;;;;;;;;:::o;592:158:-1:-;;703:2;694:6;689:3;685:16;681:25;678:2;;;-1:-1;;709:12;790:327;;904:4;892:9;887:3;883:19;879:30;876:2;;;-1:-1;;912:12;876:2;940:20;904:4;940:20;;;1580;;1021:75;;-1:-1;931:29;870:247;-1:-1;870:247;1157:349;;1282:4;1270:9;1265:3;1261:19;1257:30;1254:2;;;-1:-1;;1290:12;1254:2;1318:20;1282:4;1318:20;;;1728:13;;1399:86;;-1:-1;1309:29;1248:258;-1:-1;1248:258;1791:241;;1895:2;1883:9;1874:7;1870:23;1866:32;1863:2;;;-1:-1;;1901:12;1863:2;85:6;72:20;97:33;124:5;97:33;;2039:263;;2154:2;2142:9;2133:7;2129:23;2125:32;2122:2;;;-1:-1;;2160:12;2122:2;226:6;220:13;238:33;265:5;238:33;;2309:905;;;;;;2562:3;2550:9;2541:7;2537:23;2533:33;2530:2;;;-1:-1;;2569:12;2530:2;85:6;72:20;97:33;124:5;97:33;;;2621:63;-1:-1;2739:80;2811:7;2721:2;2787:22;;2739:80;;;2729:90;;2874:80;2946:7;2856:2;2926:9;2922:22;2874:80;;;2864:90;;3009:80;3081:7;2991:2;3061:9;3057:22;3009:80;;;2524:690;;;;-1:-1;2524:690;;3126:3;3166:22;1580:20;;2524:690;-1:-1;;2524:690;3221:416;;;3367:2;3355:9;3346:7;3342:23;3338:32;3335:2;;;-1:-1;;3373:12;3335:2;85:6;72:20;97:33;124:5;97:33;;;3425:63;-1:-1;3543:78;3613:7;3525:2;3589:22;;3543:78;;;3533:88;;3329:308;;;;;;3644:366;;;3765:2;3753:9;3744:7;3740:23;3736:32;3733:2;;;-1:-1;;3771:12;3733:2;85:6;72:20;97:33;124:5;97:33;;;3823:63;3923:2;3962:22;;;;1580:20;;-1:-1;;;3727:283;4017:257;;4129:2;4117:9;4108:7;4104:23;4100:32;4097:2;;;-1:-1;;4135:12;4097:2;364:6;358:13;56129:5;53068:13;53061:21;56107:5;56104:32;56094:2;;-1:-1;;56140:12;4281:261;;4395:2;4383:9;4374:7;4370:23;4366:32;4363:2;;;-1:-1;;4401:12;4363:2;-1:-1;495:13;;4357:185;-1:-1;4357:185;4549:291;;4678:2;4666:9;4657:7;4653:23;4649:32;4646:2;;;-1:-1;;4684:12;4646:2;4746:78;4816:7;4792:22;4746:78;;4847:313;;4987:2;4975:9;4966:7;4962:23;4958:32;4955:2;;;-1:-1;;4993:12;4955:2;5055:89;5136:7;5112:22;5055:89;;5167:466;;;5338:2;5326:9;5317:7;5313:23;5309:32;5306:2;;;-1:-1;;5344:12;5306:2;5406:78;5476:7;5452:22;5406:78;;5640:499;;;5822:2;5810:9;5801:7;5797:23;5793:32;5790:2;;;-1:-1;;5828:12;5790:2;5890:89;5971:7;5947:22;5890:89;;;5880:99;;6034:89;6115:7;6016:2;6095:9;6091:22;6034:89;;6146:241;;6250:2;6238:9;6229:7;6225:23;6221:32;6218:2;;;-1:-1;;6256:12;6218:2;-1:-1;1580:20;;6212:175;-1:-1;6212:175;6664:366;;;6785:2;6773:9;6764:7;6760:23;6756:32;6753:2;;;-1:-1;;6791:12;6753:2;1593:6;1580:20;6843:63;;6943:2;6986:9;6982:22;72:20;97:33;124:5;97:33;;;6951:63;;;;6747:283;;;;;;7502:103;-1:-1;;;;;53597:54;7563:37;;7557:48;10061:134;53401:44;53439:5;53401:44;;;10131:59;;10125:70;24921:316;25124:23;8963:37;;25027:210;25870:262;;9172:5;51913:12;9283:52;9328:6;9323:3;9316:4;9309:5;9305:16;9283:52;;;9347:16;;;;;25995:137;-1:-1;;25995:137;26139:213;-1:-1;;;;;53597:54;;;;7563:37;;26257:2;26242:18;;26228:124;26595:340;-1:-1;;;;;53597:54;;;;7432:58;;26921:2;26906:18;;8963:37;26749:2;26734:18;;26720:215;26942:324;-1:-1;;;;;53597:54;;;7563:37;;53597:54;;27252:2;27237:18;;7563:37;27088:2;27073:18;;27059:207;27273:1951;-1:-1;;;;;53597:54;;;7563:37;;53597:54;;;28146:2;28131:18;;7563:37;27981:3;27966:19;;;53401:44;53439:5;53401:44;;;28238:2;28223:18;;10131:59;;;;28321:2;28306:18;;8963:37;;;;25124:23;;28454:3;28439:19;;8963:37;25124:23;;28588:3;28573:19;;8963:37;25124:23;;28722:3;28707:19;;8963:37;25124:23;;28856:3;28841:19;;8963:37;53597:54;;;28940:3;28925:19;;7563:37;25124:23;;29074:3;29059:19;;8963:37;25124:23;;29209:3;29194:19;;;8963:37;;;;27952:1272;;-1:-1;;27952:1272;29231:435;-1:-1;;;;;53597:54;;;7563:37;;53597:54;;;;29569:2;29554:18;;7563:37;29652:2;29637:18;;8963:37;;;;29405:2;29390:18;;29376:290;29673:424;-1:-1;;;;;53597:54;;;;7563:37;;25124:23;30083:2;30068:18;;8963:37;29869:2;29854:18;;29840:257;30435:423;-1:-1;;;;;53597:54;;;;7563:37;;30767:2;30752:18;;8963:37;;;;53068:13;53061:21;30844:2;30829:18;;8846:34;30603:2;30588:18;;30574:284;30865:493;31099:2;31113:47;;;51913:12;;31084:18;;;52511:19;;;30865:493;;31099:2;52551:14;;;;;;51734;;;30865:493;8392:359;8417:6;8414:1;8411:13;8392:359;;;8484:6;8478:13;22815:63;22863:14;22792:16;22786:23;22815:63;;;31099:2;22956:5;22952:16;22946:23;22975:63;31099:2;23027:3;23023:14;23009:12;22975:63;;;;52551:14;23111:5;23107:16;23101:23;23130:72;52551:14;23191:3;23187:14;23173:12;23130:72;;;-1:-1;23292:4;23281:16;;;23275:23;23352:14;;;8963:37;23459:4;23448:16;;;23442:23;23471:113;23569:14;;;23442:23;23471:113;;;;;23675:4;;23668:5;23664:16;23658:23;23687:113;23675:4;23789:3;23785:14;23771:12;23687:113;;;;;23895:4;;23888:5;23884:16;23878:23;23907:113;23895:4;24009:3;24005:14;23991:12;23907:113;;;;;24112:4;;24105:5;24101:16;24095:23;24124:113;24112:4;24226:3;24222:14;24208:12;24124:113;;;;;24320:6;;24313:5;24309:18;24303:25;24334:65;24320:6;24386:3;24382:16;24368:12;24334:65;;;;;24489:6;;24482:5;24478:18;24472:25;24503:115;24489:6;24605:3;24601:16;24587:12;24503:115;;;;;24701:6;;24694:5;24690:18;24684:25;24715:115;24701:6;24817:3;24813:16;24799:12;24715:115;;;-1:-1;;;7332:6;7323:16;;;;;52333:14;;;;8439:1;8432:9;8392:359;;;-1:-1;31166:182;;31070:288;-1:-1;;;;;;;31070:288;31365:213;8963:37;;;31483:2;31468:18;;31454:124;31585:324;8963:37;;;31895:2;31880:18;;8963:37;31731:2;31716:18;;31702:207;32698:245;32832:2;32817:18;;55786:1;55776:12;;55766:2;;55792:9;55766:2;9983:66;;;32803:140;;32950:301;;33088:2;33109:17;33102:47;10498:5;51913:12;52523:6;33088:2;33077:9;33073:18;52511:19;10592:52;10637:6;52551:14;33077:9;52551:14;33088:2;10618:5;10614:16;10592:52;;;55678:7;55662:14;-1:-1;;55658:28;10656:39;;;;52551:14;10656:39;;33059:192;-1:-1;;33059:192;33258:407;33449:2;33463:47;;;10932:2;33434:18;;;52511:19;10968:27;52551:14;;;10948:48;11015:12;;;33420:245;33672:407;33863:2;33877:47;;;11266:2;33848:18;;;52511:19;11302:30;52551:14;;;11282:51;11352:12;;;33834:245;34086:407;34277:2;34291:47;;;11603:2;34262:18;;;52511:19;11639:32;52551:14;;;11619:53;11691:12;;;34248:245;34500:407;34691:2;34705:47;;;11942:2;34676:18;;;52511:19;11978:29;52551:14;;;11958:50;12027:12;;;34662:245;34914:407;35105:2;35119:47;;;12278:2;35090:18;;;52511:19;-1:-1;;;52551:14;;;12294:42;12355:12;;;35076:245;35328:407;35519:2;35533:47;;;12606:2;35504:18;;;52511:19;-1:-1;;;52551:14;;;12622:43;12684:12;;;35490:245;35742:407;35933:2;35947:47;;;35918:18;;;52511:19;12971:34;52551:14;;;12951:55;13025:12;;;35904:245;36156:407;36347:2;36361:47;;;13276:2;36332:18;;;52511:19;-1:-1;;;52551:14;;;13292:43;13354:12;;;36318:245;36570:407;36761:2;36775:47;;;13605:2;36746:18;;;52511:19;13641:28;52551:14;;;13621:49;13689:12;;;36732:245;36984:407;37175:2;37189:47;;;13940:2;37160:18;;;52511:19;13976:25;52551:14;;;13956:46;14021:12;;;37146:245;37398:407;37589:2;37603:47;;;14272:2;37574:18;;;52511:19;14308:32;52551:14;;;14288:53;14360:12;;;37560:245;37812:407;38003:2;38017:47;;;14611:2;37988:18;;;52511:19;-1:-1;;;52551:14;;;14627:45;14691:12;;;37974:245;38226:407;38417:2;38431:47;;;14942:2;38402:18;;;52511:19;14978:27;52551:14;;;14958:48;15025:12;;;38388:245;38640:407;38831:2;38845:47;;;15276:2;38816:18;;;52511:19;15312:28;52551:14;;;15292:49;15360:12;;;38802:245;39054:407;39245:2;39259:47;;;15611:2;39230:18;;;52511:19;15647:28;52551:14;;;15627:49;15695:12;;;39216:245;39468:407;39659:2;39673:47;;;15946:2;39644:18;;;52511:19;15982:34;52551:14;;;15962:55;-1:-1;;;16037:12;;;16030:25;16074:12;;;39630:245;39882:407;40073:2;40087:47;;;16325:2;40058:18;;;52511:19;-1:-1;;;52551:14;;;16341:41;16401:12;;;40044:245;40296:407;40487:2;40501:47;;;16652:2;40472:18;;;52511:19;16688:26;52551:14;;;16668:47;16734:12;;;40458:245;40710:407;40901:2;40915:47;;;16985:2;40886:18;;;52511:19;17021:26;52551:14;;;17001:47;17067:12;;;40872:245;41124:407;41315:2;41329:47;;;17318:2;41300:18;;;52511:19;-1:-1;;;52551:14;;;17334:42;17395:12;;;41286:245;41538:407;41729:2;41743:47;;;17646:2;41714:18;;;52511:19;17682:33;52551:14;;;17662:54;17735:12;;;41700:245;41952:407;42143:2;42157:47;;;17986:2;42128:18;;;52511:19;18022:32;52551:14;;;18002:53;18074:12;;;42114:245;42366:407;42557:2;42571:47;;;18325:2;42542:18;;;52511:19;-1:-1;;;52551:14;;;18341:35;18395:12;;;42528:245;42780:407;42971:2;42985:47;;;18646:2;42956:18;;;52511:19;18682:30;52551:14;;;18662:51;18732:12;;;42942:245;43194:407;43385:2;43399:47;;;18983:2;43370:18;;;52511:19;19019:26;52551:14;;;18999:47;19065:12;;;43356:245;43608:407;43799:2;43813:47;;;19316:2;43784:18;;;52511:19;19352:27;52551:14;;;19332:48;19399:12;;;43770:245;44022:407;44213:2;44227:47;;;19650:2;44198:18;;;52511:19;19686:29;52551:14;;;19666:50;19735:12;;;44184:245;44436:407;44627:2;44641:47;;;19986:2;44612:18;;;52511:19;20022:32;52551:14;;;20002:53;20074:12;;;44598:245;44850:407;45041:2;45055:47;;;20325:2;45026:18;;;52511:19;20361:34;52551:14;;;20341:55;-1:-1;;;20416:12;;;20409:34;20462:12;;;45012:245;45264:407;45455:2;45469:47;;;20713:2;45440:18;;;52511:19;20749:33;52551:14;;;20729:54;20802:12;;;45426:245;45678:407;45869:2;45883:47;;;21053:2;45854:18;;;52511:19;-1:-1;;;52551:14;;;21069:41;21129:12;;;45840:245;46092:407;46283:2;46297:47;;;21380:2;46268:18;;;52511:19;-1:-1;;;52551:14;;;21396:39;21454:12;;;46254:245;46506:407;46697:2;46711:47;;;21705:2;46682:18;;;52511:19;21741:33;52551:14;;;21721:54;21794:12;;;46668:245;46920:407;47111:2;47125:47;;;22045:2;47096:18;;;52511:19;22081:28;52551:14;;;22061:49;22129:12;;;47082:245;47334:407;47525:2;47539:47;;;22380:2;47510:18;;;52511:19;-1:-1;;;52551:14;;;22396:44;22459:12;;;47496:245;47748:313;25124:23;;8963:37;;47916:2;47901:18;;47887:174;48068:959;25124:23;;8963:37;;48663:2;48648:18;;8963:37;;;;25124:23;;48796:2;48781:18;;8963:37;25124:23;48929:2;48914:18;;8963:37;49012:3;48997:19;;8963:37;48448:3;48433:19;;48419:608;49254:635;8963:37;;;25124:23;;49742:2;49727:18;;8963:37;25124:23;49875:2;49860:18;;8963:37;49528:2;49513:18;;49499:390;50227:535;8963:37;;;50615:2;50600:18;;8963:37;;;;25124:23;50748:2;50733:18;;8963:37;50451:2;50436:18;;50422:340;50769:547;8963:37;;;51136:2;51121:18;;8963:37;;;;51219:2;51204:18;;8963:37;51302:2;51287:18;;8963:37;50971:3;50956:19;;50942:374;51323:256;51385:2;51379:9;51411:17;;;51486:18;51471:34;;51507:22;;;51468:62;51465:2;;;51543:1;;51533:12;51465:2;51385;51552:22;51363:216;;-1:-1;51363:216;55318:268;55383:1;55390:101;55404:6;55401:1;55398:13;55390:101;;;55471:11;;;55465:18;55452:11;;;55445:39;55426:2;55419:10;55390:101;;;55506:6;55503:1;55500:13;55497:2;;;-1:-1;;55383:1;55553:16;;55546:27;55367:219;55815:102;55895:1;55888:5;55885:12;55875:2;;55901:9;55924:117;-1:-1;;;;;53597:54;;55983:35;;55973:2;;56032:1;;56022:12;55967:74;18799:4:0;18836:19;18853:1;18836:16;:19::i;:::-;:28;18823:10;;:41;;-1:-1:-1;18726:146:0;;;;:::o

Swarm Source

ipfs://7ce495d0c987eaac5acec76e36eb506151c84b3c44515747b0f2252a2c073542

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.