ETH Price: $1,852.04 (+1.21%)
Gas: 19 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multi Chain

Multichain Addresses

0 address found via
Transaction Hash
Method
Block
From
To
Value
Settle146691522022-04-27 22:30:42407 days 4 mins ago1651098642IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.0143392974.10102999
Settle146691512022-04-27 22:29:59407 days 5 mins ago1651098599IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.0118643866.09134318
Settle146691502022-04-27 22:29:44407 days 5 mins ago1651098584IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.0121191265.74794522
Settle136267862021-11-16 13:16:19569 days 9 hrs ago1637068579IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.02529701140.94376665
Settle136267852021-11-16 13:16:11569 days 9 hrs ago1637068571IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.03074359152.63807909
Settle136267842021-11-16 13:15:26569 days 9 hrs ago1637068526IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.02517865136.60665211
Settle136267802021-11-16 13:14:34569 days 9 hrs ago1637068474IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.0276642150.09200548
Settle135409792021-11-03 1:29:00582 days 21 hrs ago1635902940IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.03734106202.61133973
Settle135409792021-11-03 1:29:00582 days 21 hrs ago1635902940IN
Across Protocol: Skinny Optimistic Oracle
0 ETH0.03734025202.61133973
0x60806040134543422021-10-20 11:26:45596 days 11 hrs ago1634729205IN
 Create: SkinnyOptimisticOracle
0 ETH0.2085281963.13140108

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SkinnyOptimisticOracle

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-20
*/

// Sources flattened with hardhat v2.5.0 https://hardhat.org

// File @openzeppelin/contracts/token/ERC20/[email protected]



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/utils/[email protected]



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]



pragma solidity ^0.8.0;


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

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

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

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

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

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

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

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File @openzeppelin/contracts/utils/math/[email protected]



pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // 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 (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @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) {
        return a + b;
    }

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

    /**
     * @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) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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 a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards 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).
     *
     * 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}


// File @openzeppelin/contracts/utils/math/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SignedSafeMath {
    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        return a / b;
    }

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

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        return a + b;
    }
}


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


pragma solidity ^0.8.0;


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

    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // For unsigned values:
    //   This 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;

    // --------------------------------------- UNSIGNED -----------------------------------------------------------------------------
    struct Unsigned {
        uint256 rawValue;
    }

    /**
     * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**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);
        }
    }

    // ------------------------------------------------- SIGNED -------------------------------------------------------------
    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // For signed values:
    //   This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76.
    int256 private constant SFP_SCALING_FACTOR = 10**18;

    struct Signed {
        int256 rawValue;
    }

    function fromSigned(Signed memory a) internal pure returns (Unsigned memory) {
        require(a.rawValue >= 0, "Negative value provided");
        return Unsigned(uint256(a.rawValue));
    }

    function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) {
        require(a.rawValue <= uint256(type(int256).max), "Unsigned too large");
        return Signed(int256(a.rawValue));
    }

    /**
     * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`.
     * @param a int to convert into a FixedPoint.Signed.
     * @return the converted FixedPoint.Signed.
     */
    function fromUnscaledInt(int256 a) internal pure returns (Signed memory) {
        return Signed(a.mul(SFP_SCALING_FACTOR));
    }

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

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

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

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

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

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Signed memory a, Signed 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.Signed.
     * @param b an int256.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue >= fromUnscaledInt(b).rawValue;
    }

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

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

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

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

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Signed memory a, Signed 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.Signed.
     * @param b an int256.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue <= fromUnscaledInt(b).rawValue;
    }

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

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

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

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

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

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

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

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

    /**
     * @notice Multiplies two `Signed`s, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the product of `a` and `b`.
     */
    function mul(Signed memory a, Signed memory b) internal pure returns (Signed 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 an int256 ~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 SFP_SCALING_FACTOR != 0.
        return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR);
    }

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

    /**
     * @notice Multiplies two `Signed`s and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the product of `a` and `b`.
     */
    function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        int256 mulRaw = a.rawValue.mul(b.rawValue);
        int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR;
        // Manual mod because SignedSafeMath doesn't support it.
        int256 mod = mulRaw % SFP_SCALING_FACTOR;
        if (mod != 0) {
            bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
            int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
            return Signed(mulTowardsZero.add(valueToAdd));
        } else {
            return Signed(mulTowardsZero);
        }
    }

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

    /**
     * @notice Divides one `Signed` by an `Signed`, 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(Signed memory a, Signed memory b) internal pure returns (Signed 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 an int256 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 Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue));
    }

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

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

    /**
     * @notice Divides one `Signed` by an `Signed` 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 divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR);
        int256 divTowardsZero = aScaled.div(b.rawValue);
        // Manual mod because SignedSafeMath doesn't support it.
        int256 mod = aScaled % b.rawValue;
        if (mod != 0) {
            bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
            int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
            return Signed(divTowardsZero.add(valueToAdd));
        } else {
            return Signed(divTowardsZero);
        }
    }

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

    /**
     * @notice Raises an `Signed` 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.Signed.
     * @param b a uint256 (negative exponents are not allowed).
     * @return output is `a` to the power of `b`.
     */
    function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) {
        output = fromUnscaledInt(1);
        for (uint256 i = 0; i < b; i = i.add(1)) {
            output = mul(output, a);
        }
    }
}


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


pragma solidity ^0.8.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/OracleAncillaryInterface.sol


pragma solidity ^0.8.0;

/**
 * @title Financial contract facing Oracle interface.
 * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
 */
abstract contract OracleAncillaryInterface {
    /**
     * @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 ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
     * @param time unix timestamp for the price request.
     */

    function requestPrice(
        bytes32 identifier,
        uint256 time,
        bytes memory ancillaryData
    ) public virtual;

    /**
     * @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.
     * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
     * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
     */
    function hasPrice(
        bytes32 identifier,
        uint256 time,
        bytes memory ancillaryData
    ) public view virtual 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.
     * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
     * @return int256 representing the resolved price for the given identifier and timestamp.
     */

    function getPrice(
        bytes32 identifier,
        uint256 time,
        bytes memory ancillaryData
    ) public view virtual returns (int256);
}


// File contracts/oracle/interfaces/OptimisticOracleInterface.sol


pragma solidity ^0.8.0;

/**
 * @title Financial contract facing Oracle interface.
 * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
 */
abstract contract OptimisticOracleInterface {
    // Struct representing the state of a price request.
    enum State {
        Invalid, // Never requested.
        Requested, // Requested, no other actions taken.
        Proposed, // Proposed, but not expired or disputed yet.
        Expired, // Proposed, not disputed, past liveness.
        Disputed, // Disputed, but no DVM price returned yet.
        Resolved, // Disputed and DVM price is available.
        Settled // Final price has been set in the contract (can get here from Expired or Resolved).
    }

    // Struct representing a price request.
    struct Request {
        address proposer; // Address of the proposer.
        address disputer; // Address of the disputer.
        IERC20 currency; // ERC20 token used to pay rewards and fees.
        bool settled; // True if the request is settled.
        bool refundOnDispute; // True if the requester should be refunded their reward on dispute.
        int256 proposedPrice; // Price that the proposer submitted.
        int256 resolvedPrice; // Price resolved once the request is settled.
        uint256 expirationTime; // Time at which the request auto-settles without a dispute.
        uint256 reward; // Amount of the currency to pay to the proposer on settlement.
        uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.
        uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.
        uint256 customLiveness; // Custom liveness value set by the requester.
    }

    // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible
    // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses
    // to accept a price request made with ancillary data length over a certain size.
    uint256 public constant ancillaryBytesLimit = 8192;

    /**
     * @notice Requests a new price.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data representing additional args being passed with the price request.
     * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.
     * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,
     *               which could make sense if the contract requests and proposes the value in the same call or
     *               provides its own reward system.
     * @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay.
     * This can be changed with a subsequent call to setBond().
     */
    function requestPrice(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        IERC20 currency,
        uint256 reward
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Set the proposal bond associated with a price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param bond custom bond amount to set.
     * @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be
     * changed again with a subsequent call to setBond().
     */
    function setBond(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        uint256 bond
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Sets the request to refund the reward if the proposal is disputed. This can help to "hedge" the caller
     * in the event of a dispute-caused delay. Note: in the event of a dispute, the winner still receives the other's
     * bond, so there is still profit to be made even if the reward is refunded.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     */
    function setRefundOnDispute(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) external virtual;

    /**
     * @notice Sets a custom liveness value for the request. Liveness is the amount of time a proposal must wait before
     * being auto-resolved.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param customLiveness new custom liveness.
     */
    function setCustomLiveness(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        uint256 customLiveness
    ) external virtual;

    /**
     * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come
     * from this proposal. However, any bonds are pulled from the caller.
     * @param proposer address to set as the proposer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePriceFor(
        address proposer,
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        int256 proposedPrice
    ) public virtual returns (uint256 totalBond);

    /**
     * @notice Proposes a price value for an existing price request.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePrice(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        int256 proposedPrice
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will
     * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.
     * @param disputer address to set as the disputer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was value (the proposal was incorrect).
     */
    function disputePriceFor(
        address disputer,
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) public virtual returns (uint256 totalBond);

    /**
     * @notice Disputes a price value for an existing price request with an active proposal.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was valid (the proposal was incorrect).
     */
    function disputePrice(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled
     * or settleable. Note: this method is not view so that this call may actually settle the price request if it
     * hasn't been settled.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return resolved price.
     */
    function settleAndGetPrice(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) external virtual returns (int256);

    /**
     * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes
     * the returned bonds as well as additional rewards.
     */
    function settle(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) external virtual returns (uint256 payout);

    /**
     * @notice Gets the current data structure containing all information about a price request.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return the Request data structure.
     */
    function getRequest(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) public view virtual returns (Request memory);

    /**
     * @notice Returns the state of a price request.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return the State enum value.
     */
    function getState(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) public view virtual returns (State);

    /**
     * @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price).
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @return true if price has resolved or settled, false otherwise.
     */
    function hasPrice(
        address requester,
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData
    ) public view virtual returns (bool);

    function stampAncillaryData(bytes memory ancillaryData, address requester)
        public
        view
        virtual
        returns (bytes memory);
}


// File contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol


pragma solidity ^0.8.0;


/**
 * @title Interface for the gas-cost-reduced version of the OptimisticOracle.
 * @notice Differences from normal OptimisticOracle:
 * - refundOnDispute: flag is removed, by default there are no refunds on disputes.
 * - customizing request parameters: In the OptimisticOracle, parameters like `bond` and `customLiveness` can be reset
 *   after a request is already made via `requestPrice`. In the SkinnyOptimisticOracle, these parameters can only be
 *   set in `requestPrice`, which has an expanded input set.
 * - settleAndGetPrice: Replaced by `settle`, which can only be called once per settleable request. The resolved price
 *   can be fetched via the `Settle` event or the return value of `settle`.
 * - general changes to interface: Functions that interact with existing requests all require the parameters of the
 *   request to modify to be passed as input. These parameters must match with the existing request parameters or the
 *   function will revert. This change reflects the internal refactor to store hashed request parameters instead of the
 *   full request struct.
 * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
 */
abstract contract SkinnyOptimisticOracleInterface {
    // Struct representing a price request. Note that this differs from the OptimisticOracleInterface's Request struct
    // in that refundOnDispute is removed.
    struct Request {
        address proposer; // Address of the proposer.
        address disputer; // Address of the disputer.
        IERC20 currency; // ERC20 token used to pay rewards and fees.
        bool settled; // True if the request is settled.
        int256 proposedPrice; // Price that the proposer submitted.
        int256 resolvedPrice; // Price resolved once the request is settled.
        uint256 expirationTime; // Time at which the request auto-settles without a dispute.
        uint256 reward; // Amount of the currency to pay to the proposer on settlement.
        uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.
        uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.
        uint256 customLiveness; // Custom liveness value set by the requester.
    }

    // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible
    // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses
    // to accept a price request made with ancillary data length over a certain size.
    uint256 public constant ancillaryBytesLimit = 8192;

    /**
     * @notice Requests a new price.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data representing additional args being passed with the price request.
     * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.
     * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,
     *               which could make sense if the contract requests and proposes the value in the same call or
     *               provides its own reward system.
     * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.
     * @param customLiveness custom proposal liveness to set for request.
     * @return totalBond default bond + final fee that the proposer and disputer will be required to pay.
     */
    function requestPrice(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        IERC20 currency,
        uint256 reward,
        uint256 bond,
        uint256 customLiveness
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come
     * from this proposal. However, any bonds are pulled from the caller.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * propose a price for.
     * @param proposer address to set as the proposer.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePriceFor(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        address proposer,
        int256 proposedPrice
    ) public virtual returns (uint256 totalBond);

    /**
     * @notice Proposes a price value where caller is the proposer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * propose a price for.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        int256 proposedPrice
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Combines logic of requestPrice and proposePrice while taking advantage of gas savings from not having to
     * overwrite Request params that a normal requestPrice() => proposePrice() flow would entail. Note: The proposer
     * will receive any rewards that come from this proposal. However, any bonds are pulled from the caller.
     * @dev The caller is the requester, but the proposer can be customized.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.
     * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,
     *               which could make sense if the contract requests and proposes the value in the same call or
     *               provides its own reward system.
     * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.
     * @param customLiveness custom proposal liveness to set for request.
     * @param proposer address to set as the proposer.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function requestAndProposePriceFor(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        IERC20 currency,
        uint256 reward,
        uint256 bond,
        uint256 customLiveness,
        address proposer,
        int256 proposedPrice
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will
     * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * dispute.
     * @param disputer address to set as the disputer.
     * @param requester sender of the initial price request.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was valid (the proposal was incorrect).
     */
    function disputePriceFor(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        address disputer,
        address requester
    ) public virtual returns (uint256 totalBond);

    /**
     * @notice Disputes a price request with an active proposal where caller is the disputer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * dispute.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was valid (the proposal was incorrect).
     */
    function disputePrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external virtual returns (uint256 totalBond);

    /**
     * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * settle.
     * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes
     * the returned bonds as well as additional rewards.
     * @return resolvedPrice the price that the request settled to.
     */
    function settle(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external virtual returns (uint256 payout, int256 resolvedPrice);

    /**
     * @notice Computes the current state of a price request. See the State enum for more details.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters.
     * @return the State.
     */
    function getState(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external virtual returns (OptimisticOracleInterface.State);

    /**
     * @notice Checks if a given request has resolved, expired or been settled (i.e the optimistic oracle has a price).
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters. The hash of these parameters must match with the request hash that is
     * associated with the price request unique ID {requester, identifier, timestamp, ancillaryData}, or this method
     * will revert.
     * @return boolean indicating true if price exists and false if not.
     */
    function hasPrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) public virtual returns (bool);

    /**
     * @notice Generates stamped ancillary data in the format that it would be used in the case of a price dispute.
     * @param ancillaryData ancillary data of the price being requested.
     * @param requester sender of the initial price request.
     * @return the stamped ancillary bytes.
     */
    function stampAncillaryData(bytes memory ancillaryData, address requester)
        public
        pure
        virtual
        returns (bytes memory);
}


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


pragma solidity ^0.8.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/oracle/interfaces/IdentifierWhitelistInterface.sol


pragma solidity ^0.8.0;

/**
 * @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/implementation/Constants.sol


pragma solidity ^0.8.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";
    bytes32 public constant OptimisticOracle = "OptimisticOracle";
    bytes32 public constant Bridge = "Bridge";
    bytes32 public constant GenericHandler = "GenericHandler";
    bytes32 public constant SkinnyOptimisticOracle = "SkinnyOptimisticOracle";
}


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


pragma solidity ^0.8.0;

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

    constructor() {
        currentTime = block.timestamp; // 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 currentTime variable set in the Timer.
     * @return uint256 for the current Testable timestamp.
     */
    function getCurrentTime() public view returns (uint256) {
        return currentTime;
    }
}


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


pragma solidity ^0.8.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 in production, 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) {
        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 virtual returns (uint256) {
        if (timerAddress != address(0x0)) {
            return Timer(timerAddress).getCurrentTime();
        } else {
            return block.timestamp; // solhint-disable-line not-rely-on-time
        }
    }
}


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


pragma solidity ^0.8.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() {
        // 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 percentage of the total
        // transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full
        // refund coming into effect.
        _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 making it call a `private`
     * function that does the actual state modification.
     */
    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/common/implementation/AncillaryData.sol


pragma solidity ^0.8.0;

/**
 * @title Library for encoding and decoding ancillary data for DVM price requests.
 * @notice  We assume that on-chain ancillary data can be formatted directly from bytes to utf8 encoding via
 * web3.utils.hexToUtf8, and that clients will parse the utf8-encoded ancillary data as a comma-delimitted key-value
 * dictionary. Therefore, this library provides internal methods that aid appending to ancillary data from Solidity
 * smart contracts. More details on UMA's ancillary data guidelines below:
 * https://docs.google.com/document/d/1zhKKjgY1BupBGPPrY_WOJvui0B6DMcd-xDR8-9-SPDw/edit
 */
library AncillaryData {
    // This converts the bottom half of a bytes32 input to hex in a highly gas-optimized way.
    // Source: the brilliant implementation at https://gitter.im/ethereum/solidity?at=5840d23416207f7b0ed08c9b.
    function toUtf8Bytes32Bottom(bytes32 bytesIn) private pure returns (bytes32) {
        unchecked {
            uint256 x = uint256(bytesIn);

            // Nibble interleave
            x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
            x = (x | (x * 2**64)) & 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff;
            x = (x | (x * 2**32)) & 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff;
            x = (x | (x * 2**16)) & 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff;
            x = (x | (x * 2**8)) & 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff;
            x = (x | (x * 2**4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;

            // Hex encode
            uint256 h = (x & 0x0808080808080808080808080808080808080808080808080808080808080808) / 8;
            uint256 i = (x & 0x0404040404040404040404040404040404040404040404040404040404040404) / 4;
            uint256 j = (x & 0x0202020202020202020202020202020202020202020202020202020202020202) / 2;
            x = x + (h & (i | j)) * 0x27 + 0x3030303030303030303030303030303030303030303030303030303030303030;

            // Return the result.
            return bytes32(x);
        }
    }

    /**
     * @notice Returns utf8-encoded bytes32 string that can be read via web3.utils.hexToUtf8.
     * @dev Will return bytes32 in all lower case hex characters and without the leading 0x.
     * This has minor changes from the toUtf8BytesAddress to control for the size of the input.
     * @param bytesIn bytes32 to encode.
     * @return utf8 encoded bytes32.
     */
    function toUtf8Bytes(bytes32 bytesIn) internal pure returns (bytes memory) {
        return abi.encodePacked(toUtf8Bytes32Bottom(bytesIn >> 128), toUtf8Bytes32Bottom(bytesIn));
    }

    /**
     * @notice Returns utf8-encoded address that can be read via web3.utils.hexToUtf8.
     * Source: https://ethereum.stackexchange.com/questions/8346/convert-address-to-string/8447#8447
     * @dev Will return address in all lower case characters and without the leading 0x.
     * @param x address to encode.
     * @return utf8 encoded address bytes.
     */
    function toUtf8BytesAddress(address x) internal pure returns (bytes memory) {
        return
            abi.encodePacked(toUtf8Bytes32Bottom(bytes32(bytes20(x)) >> 128), bytes8(toUtf8Bytes32Bottom(bytes20(x))));
    }

    /**
     * @notice Converts a uint into a base-10, UTF-8 representation stored in a `string` type.
     * @dev This method is based off of this code: https://stackoverflow.com/a/65707309.
     */
    function toUtf8BytesUint(uint256 x) internal pure returns (bytes memory) {
        if (x == 0) {
            return "0";
        }
        uint256 j = x;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len;
        while (x != 0) {
            k = k - 1;
            uint8 temp = (48 + uint8(x - (x / 10) * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            x /= 10;
        }
        return bstr;
    }

    function appendKeyValueBytes32(
        bytes memory currentAncillaryData,
        bytes memory key,
        bytes32 value
    ) internal pure returns (bytes memory) {
        bytes memory prefix = constructPrefix(currentAncillaryData, key);
        return abi.encodePacked(prefix, toUtf8Bytes(value));
    }

    /**
     * @notice Adds "key:value" to `currentAncillaryData` where `value` is an address that first needs to be converted
     * to utf8 bytes. For example, if `utf8(currentAncillaryData)="k1:v1"`, then this function will return
     * `utf8(k1:v1,key:value)`, and if `currentAncillaryData` is blank, then this will return `utf8(key:value)`.
     * @param currentAncillaryData This bytes data should ideally be able to be utf8-decoded, but its OK if not.
     * @param key Again, this bytes data should ideally be able to be utf8-decoded, but its OK if not.
     * @param value An address to set as the value in the key:value pair to append to `currentAncillaryData`.
     * @return Newly appended ancillary data.
     */
    function appendKeyValueAddress(
        bytes memory currentAncillaryData,
        bytes memory key,
        address value
    ) internal pure returns (bytes memory) {
        bytes memory prefix = constructPrefix(currentAncillaryData, key);
        return abi.encodePacked(currentAncillaryData, prefix, toUtf8BytesAddress(value));
    }

    /**
     * @notice Adds "key:value" to `currentAncillaryData` where `value` is a uint that first needs to be converted
     * to utf8 bytes. For example, if `utf8(currentAncillaryData)="k1:v1"`, then this function will return
     * `utf8(k1:v1,key:value)`, and if `currentAncillaryData` is blank, then this will return `utf8(key:value)`.
     * @param currentAncillaryData This bytes data should ideally be able to be utf8-decoded, but its OK if not.
     * @param key Again, this bytes data should ideally be able to be utf8-decoded, but its OK if not.
     * @param value A uint to set as the value in the key:value pair to append to `currentAncillaryData`.
     * @return Newly appended ancillary data.
     */
    function appendKeyValueUint(
        bytes memory currentAncillaryData,
        bytes memory key,
        uint256 value
    ) internal pure returns (bytes memory) {
        bytes memory prefix = constructPrefix(currentAncillaryData, key);
        return abi.encodePacked(currentAncillaryData, prefix, toUtf8BytesUint(value));
    }

    /**
     * @notice Helper method that returns the left hand side of a "key:value" pair plus the colon ":" and a leading
     * comma "," if the `currentAncillaryData` is not empty. The return value is intended to be prepended as a prefix to
     * some utf8 value that is ultimately added to a comma-delimited, key-value dictionary.
     */
    function constructPrefix(bytes memory currentAncillaryData, bytes memory key) internal pure returns (bytes memory) {
        if (currentAncillaryData.length > 0) {
            return abi.encodePacked(",", key, ":");
        } else {
            return abi.encodePacked(key, ":");
        }
    }
}


// File contracts/common/interfaces/AddressWhitelistInterface.sol


pragma solidity ^0.8.0;

interface AddressWhitelistInterface {
    function addToWhitelist(address newElement) external;

    function removeFromWhitelist(address newElement) external;

    function isOnWhitelist(address newElement) external view returns (bool);

    function getWhitelist() external view returns (address[] memory);
}


// File @openzeppelin/contracts/utils/[email protected]



pragma solidity ^0.8.0;

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

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


// File @openzeppelin/contracts/access/[email protected]



pragma solidity ^0.8.0;

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

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

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

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

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

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

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


// File contracts/common/implementation/AddressWhitelist.sol


pragma solidity ^0.8.0;



/**
 * @title A contract to track a whitelist of addresses.
 */
contract AddressWhitelist is AddressWhitelistInterface, Ownable, Lockable {
    enum Status { None, In, Out }
    mapping(address => Status) public whitelist;

    address[] public whitelistIndices;

    event AddedToWhitelist(address indexed addedAddress);
    event RemovedFromWhitelist(address indexed removedAddress);

    /**
     * @notice Adds an address to the whitelist.
     * @param newElement the new address to add.
     */
    function addToWhitelist(address newElement) external override nonReentrant() onlyOwner {
        // Ignore if address is already included
        if (whitelist[newElement] == Status.In) {
            return;
        }

        // Only append new addresses to the array, never a duplicate
        if (whitelist[newElement] == Status.None) {
            whitelistIndices.push(newElement);
        }

        whitelist[newElement] = Status.In;

        emit AddedToWhitelist(newElement);
    }

    /**
     * @notice Removes an address from the whitelist.
     * @param elementToRemove the existing address to remove.
     */
    function removeFromWhitelist(address elementToRemove) external override nonReentrant() onlyOwner {
        if (whitelist[elementToRemove] != Status.Out) {
            whitelist[elementToRemove] = Status.Out;
            emit RemovedFromWhitelist(elementToRemove);
        }
    }

    /**
     * @notice Checks whether an address is on the whitelist.
     * @param elementToCheck the address to check.
     * @return True if `elementToCheck` is on the whitelist, or False.
     */
    function isOnWhitelist(address elementToCheck) external view override nonReentrantView() returns (bool) {
        return whitelist[elementToCheck] == Status.In;
    }

    /**
     * @notice Gets all addresses that are currently included in the whitelist.
     * @dev Note: This method skips over, but still iterates through addresses. It is possible for this call to run out
     * of gas if a large number of addresses have been removed. To reduce the likelihood of this unlikely scenario, we
     * can modify the implementation so that when addresses are removed, the last addresses in the array is moved to
     * the empty index.
     * @return activeWhitelist the list of addresses on the whitelist.
     */
    function getWhitelist() external view override nonReentrantView() returns (address[] memory activeWhitelist) {
        // Determine size of whitelist first
        uint256 activeCount = 0;
        for (uint256 i = 0; i < whitelistIndices.length; i++) {
            if (whitelist[whitelistIndices[i]] == Status.In) {
                activeCount++;
            }
        }

        // Populate whitelist
        activeWhitelist = new address[](activeCount);
        activeCount = 0;
        for (uint256 i = 0; i < whitelistIndices.length; i++) {
            address addr = whitelistIndices[i];
            if (whitelist[addr] == Status.In) {
                activeWhitelist[activeCount] = addr;
                activeCount++;
            }
        }
    }
}


// File contracts/oracle/implementation/SkinnyOptimisticOracle.sol


pragma solidity ^0.8.0;














/**
 * @title Optimistic Requester.
 * @notice Optional interface that requesters can implement to receive callbacks.
 * @dev This contract does _not_ work with ERC777 collateral currencies or any others that call into the receiver on
 * transfer(). Using an ERC777 token would allow a user to maliciously grief other participants (while also losing
 * money themselves).
 */
interface OptimisticRequester {
    /**
     * @notice Callback for proposals.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request request params after proposal.
     */
    function priceProposed(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        SkinnyOptimisticOracleInterface.Request memory request
    ) external;

    /**
     * @notice Callback for disputes.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request request params after dispute.
     */
    function priceDisputed(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        SkinnyOptimisticOracleInterface.Request memory request
    ) external;

    /**
     * @notice Callback for settlement.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request request params after settlement.
     */
    function priceSettled(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        SkinnyOptimisticOracleInterface.Request memory request
    ) external;
}

/**
 * @title Optimistic Oracle with a different interface and fewer features that emphasizes gas cost reductions.
 * @notice Pre-DVM escalation contract that allows faster settlement.
 */
contract SkinnyOptimisticOracle is SkinnyOptimisticOracleInterface, Testable, Lockable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using Address for address;

    event RequestPrice(
        address indexed requester,
        bytes32 indexed identifier,
        uint32 timestamp,
        bytes ancillaryData,
        Request request
    );
    event ProposePrice(
        address indexed requester,
        bytes32 indexed identifier,
        uint32 timestamp,
        bytes ancillaryData,
        Request request
    );
    event DisputePrice(
        address indexed requester,
        bytes32 indexed identifier,
        uint32 timestamp,
        bytes ancillaryData,
        Request request
    );
    event Settle(
        address indexed requester,
        bytes32 indexed identifier,
        uint32 timestamp,
        bytes ancillaryData,
        Request request
    );

    // Maps hash of unique request params {identifier, timestamp, ancillary data} to customizable variables such as
    // reward and bond amounts.
    mapping(bytes32 => bytes32) public requests;

    // Finder to provide addresses for DVM contracts.
    FinderInterface public finder;

    // Default liveness value for all price requests.
    uint256 public defaultLiveness;

    /**
     * @notice Constructor.
     * @param _liveness default liveness applied to each price request.
     * @param _finderAddress finder to use to get addresses of DVM contracts.
     * @param _timerAddress address of the timer contract. Should be 0x0 in prod.
     */
    constructor(
        uint256 _liveness,
        address _finderAddress,
        address _timerAddress
    ) Testable(_timerAddress) {
        finder = FinderInterface(_finderAddress);
        _validateLiveness(_liveness);
        defaultLiveness = _liveness;
    }

    /**
     * @notice Requests a new price.
     * @param identifier price identifier being requested.
     * @param timestamp timestamp of the price being requested.
     * @param ancillaryData ancillary data representing additional args being passed with the price request.
     * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.
     * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,
     *               which could make sense if the contract requests and proposes the value in the same call or
     *               provides its own reward system.
     * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.
     * @param customLiveness custom proposal liveness to set for request.
     * @return totalBond default bond + final fee that the proposer and disputer will be required to pay.
     */
    function requestPrice(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        IERC20 currency,
        uint256 reward,
        uint256 bond,
        uint256 customLiveness
    ) external override nonReentrant() returns (uint256 totalBond) {
        bytes32 requestId = _getId(msg.sender, identifier, timestamp, ancillaryData);
        require(requests[requestId] == bytes32(0), "Request already initialized");
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier), "Unsupported identifier");
        require(_getCollateralWhitelist().isOnWhitelist(address(currency)), "Unsupported currency");
        require(timestamp <= getCurrentTime(), "Timestamp in future");
        require(
            _stampAncillaryData(ancillaryData, msg.sender).length <= ancillaryBytesLimit,
            "Ancillary Data too long"
        );
        uint256 finalFee = _getStore().computeFinalFee(address(currency)).rawValue;

        // Associate new request with ID
        Request memory request;
        request.currency = currency;
        request.reward = reward;
        request.finalFee = finalFee;
        request.bond = bond != 0 ? bond : finalFee;
        request.customLiveness = customLiveness;
        _storeRequestHash(requestId, request);

        if (reward > 0) currency.safeTransferFrom(msg.sender, address(this), reward);

        emit RequestPrice(msg.sender, identifier, timestamp, ancillaryData, request);

        return request.bond.add(finalFee);
    }

    /**
     * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come
     * from this proposal. However, any bonds are pulled from the caller.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * propose a price for.
     * @param proposer address to set as the proposer.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePriceFor(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        address proposer,
        int256 proposedPrice
    ) public override nonReentrant() returns (uint256 totalBond) {
        require(proposer != address(0), "Proposer address must be non 0");
        require(
            _getState(requester, identifier, timestamp, ancillaryData, request) ==
                OptimisticOracleInterface.State.Requested,
            "Must be requested"
        );
        bytes32 requestId = _getId(requester, identifier, timestamp, ancillaryData);
        _validateRequestHash(requestId, request);

        // Associate newly proposed request params with ID
        Request memory proposedRequest =
            Request({
                proposer: proposer, // Modified
                disputer: request.disputer,
                currency: request.currency,
                settled: request.settled,
                proposedPrice: proposedPrice, // Modified
                resolvedPrice: request.resolvedPrice,
                expirationTime: getCurrentTime().add(
                    request.customLiveness != 0 ? request.customLiveness : defaultLiveness
                ), // Modified
                reward: request.reward,
                finalFee: request.finalFee,
                bond: request.bond,
                customLiveness: request.customLiveness
            });
        _storeRequestHash(requestId, proposedRequest);

        totalBond = request.bond.add(request.finalFee);
        if (totalBond > 0) request.currency.safeTransferFrom(msg.sender, address(this), totalBond);

        emit ProposePrice(requester, identifier, timestamp, ancillaryData, proposedRequest);

        // Callback.
        if (address(msg.sender).isContract())
            try
                OptimisticRequester(msg.sender).priceProposed(identifier, timestamp, ancillaryData, proposedRequest)
            {} catch {}
    }

    /**
     * @notice Proposes a price value where caller is the proposer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     * propose a price for.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function proposePrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        int256 proposedPrice
    ) external override returns (uint256 totalBond) {
        // Note: re-entrancy guard is done in the inner call.
        return proposePriceFor(requester, identifier, timestamp, ancillaryData, request, msg.sender, proposedPrice);
    }

    /**
     * @notice Combines logic of requestPrice and proposePrice while taking advantage of gas savings from not having to
     * overwrite Request params that a normal requestPrice() => proposePrice() flow would entail. Note: The proposer
     * will receive any rewards that come from this proposal. However, any bonds are pulled from the caller.
     * @dev The caller is the requester, but the proposer can be customized.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.
     * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,
     *               which could make sense if the contract requests and proposes the value in the same call or
     *               provides its own reward system.
     * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.
     * @param customLiveness custom proposal liveness to set for request.
     * @param proposer address to set as the proposer.
     * @param proposedPrice price being proposed.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the proposer once settled if the proposal is correct.
     */
    function requestAndProposePriceFor(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        IERC20 currency,
        uint256 reward,
        uint256 bond,
        uint256 customLiveness,
        address proposer,
        int256 proposedPrice
    ) external override returns (uint256 totalBond) {
        bytes32 requestId = _getId(msg.sender, identifier, timestamp, ancillaryData);
        require(requests[requestId] == bytes32(0), "Request already initialized");
        require(proposer != address(0), "proposer address must be non 0");
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier), "Unsupported identifier");
        require(_getCollateralWhitelist().isOnWhitelist(address(currency)), "Unsupported currency");
        require(timestamp <= getCurrentTime(), "Timestamp in future");
        require(
            _stampAncillaryData(ancillaryData, msg.sender).length <= ancillaryBytesLimit,
            "Ancillary Data too long"
        );
        uint256 finalFee = _getStore().computeFinalFee(address(currency)).rawValue;

        // Associate new request with ID
        Request memory request;
        request.currency = currency;
        request.reward = reward;
        request.finalFee = finalFee;
        request.bond = bond;
        request.customLiveness = customLiveness;
        request.proposer = proposer;
        request.proposedPrice = proposedPrice;
        request.expirationTime = getCurrentTime().add(customLiveness != 0 ? customLiveness : defaultLiveness);
        _storeRequestHash(requestId, request);

        // Pull reward from requester, who is the caller.
        if (reward > 0) currency.safeTransferFrom(msg.sender, address(this), reward);
        // Pull proposal bond from caller.
        totalBond = request.bond.add(request.finalFee);
        if (totalBond > 0) currency.safeTransferFrom(msg.sender, address(this), totalBond);

        emit RequestPrice(msg.sender, identifier, timestamp, ancillaryData, request);
        emit ProposePrice(msg.sender, identifier, timestamp, ancillaryData, request);

        // Callback.
        if (address(msg.sender).isContract())
            try OptimisticRequester(msg.sender).priceProposed(identifier, timestamp, ancillaryData, request) {} catch {}
    }

    /**
     * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will
     * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     *              dispute.
     * @param disputer address to set as the disputer.
     * @param requester sender of the initial price request.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was valid (the proposal was incorrect).
     */
    function disputePriceFor(
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request,
        address disputer,
        address requester
    ) public override nonReentrant() returns (uint256 totalBond) {
        require(disputer != address(0), "disputer address must be non 0");
        require(
            _getState(requester, identifier, timestamp, ancillaryData, request) ==
                OptimisticOracleInterface.State.Proposed,
            "Must be proposed"
        );
        bytes32 requestId = _getId(requester, identifier, timestamp, ancillaryData);
        _validateRequestHash(requestId, request);

        // Associate newly disputed request params with ID
        Request memory disputedRequest =
            Request({
                proposer: request.proposer,
                disputer: disputer, // Modified
                currency: request.currency,
                settled: request.settled,
                proposedPrice: request.proposedPrice,
                resolvedPrice: request.resolvedPrice,
                expirationTime: request.expirationTime,
                reward: request.reward,
                finalFee: request.finalFee,
                bond: request.bond,
                customLiveness: request.customLiveness
            });
        _storeRequestHash(requestId, disputedRequest);

        totalBond = request.bond.add(request.finalFee);
        if (totalBond > 0) request.currency.safeTransferFrom(msg.sender, address(this), totalBond);

        StoreInterface store = _getStore();

        // Avoids stack too deep compilation error.
        {
            // Along with the final fee, "burn" part of the loser's bond to ensure that a larger bond always makes it
            // proportionally more expensive to delay the resolution even if the proposer and disputer are the same
            // party.
            uint256 burnedBond = _computeBurnedBond(disputedRequest);

            // The total fee is the burned bond and the final fee added together.
            uint256 totalFee = request.finalFee.add(burnedBond);

            if (totalFee > 0) {
                request.currency.safeIncreaseAllowance(address(store), totalFee);
                _getStore().payOracleFeesErc20(address(request.currency), FixedPoint.Unsigned(totalFee));
            }
        }

        _getOracle().requestPrice(identifier, timestamp, _stampAncillaryData(ancillaryData, requester));

        emit DisputePrice(requester, identifier, timestamp, ancillaryData, disputedRequest);

        // Callback.
        if (address(requester).isContract())
            try
                OptimisticRequester(requester).priceDisputed(identifier, timestamp, ancillaryData, disputedRequest)
            {} catch {}
    }

    /**
     * @notice Disputes a price request with an active proposal where caller is the disputer.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     *             dispute.
     * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to
     * the disputer once settled if the dispute was valid (the proposal was incorrect).
     */
    function disputePrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external override returns (uint256 totalBond) {
        // Note: re-entrancy guard is done in the inner call.
        return disputePriceFor(identifier, timestamp, ancillaryData, request, msg.sender, requester);
    }

    /**
     * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters whose hash must match the request that the caller wants to
     *              settle.
     * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes
     * the returned bonds as well as additional rewards.
     * @return resolvedPrice the price that the request settled to.
     */
    function settle(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external override nonReentrant() returns (uint256 payout, int256 resolvedPrice) {
        return _settle(requester, identifier, timestamp, ancillaryData, request);
    }

    /**
     * @notice Computes the current state of a price request. See the State enum for more details.
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters.
     * @return the State.
     */
    function getState(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) external override nonReentrant() returns (OptimisticOracleInterface.State) {
        return _getState(requester, identifier, timestamp, ancillaryData, request);
    }

    /**
     * @notice Checks if a given request has resolved, expired or been settled (i.e the optimistic oracle has a price).
     * @param requester sender of the initial price request.
     * @param identifier price identifier to identify the existing request.
     * @param timestamp timestamp to identify the existing request.
     * @param ancillaryData ancillary data of the price being requested.
     * @param request price request parameters. The hash of these parameters must match with the request hash that is
     * associated with the price request unique ID {requester, identifier, timestamp, ancillaryData}, or this method
     * will revert.
     * @return boolean indicating true if price exists and false if not.
     */
    function hasPrice(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) public override nonReentrant() returns (bool) {
        bytes32 requestId = _getId(requester, identifier, timestamp, ancillaryData);
        _validateRequestHash(requestId, request);
        OptimisticOracleInterface.State state = _getState(requester, identifier, timestamp, ancillaryData, request);
        return
            state == OptimisticOracleInterface.State.Settled ||
            state == OptimisticOracleInterface.State.Resolved ||
            state == OptimisticOracleInterface.State.Expired;
    }

    /**
     * @notice Generates stamped ancillary data in the format that it would be used in the case of a price dispute.
     * @param ancillaryData ancillary data of the price being requested.
     * @param requester sender of the initial price request.
     * @return the stamped ancillary bytes.
     */
    function stampAncillaryData(bytes memory ancillaryData, address requester)
        public
        pure
        override
        returns (bytes memory)
    {
        return _stampAncillaryData(ancillaryData, requester);
    }

    /****************************************
     *    PRIVATE AND INTERNAL FUNCTIONS    *
     ****************************************/
    // Returns hash of unique request identifiers. This contract maps request ID hashes to hashes of the request's
    // parameters.
    function _getId(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData
    ) private pure returns (bytes32) {
        return keccak256(abi.encode(requester, identifier, timestamp, ancillaryData));
    }

    // Returns hash of request parameters. These are mapped to the unique request ID to track a request's lifecycle.
    function _getRequestHash(Request memory request) private pure returns (bytes32) {
        return keccak256(abi.encode(request));
    }

    // Resolves a price request that has expired or been disputed and a price is available from the DVM. This will
    // revert if the unique request ID does not match the hashed request parameters. This also marks the request
    // as settled, therefore this method can only be triggered once per eligible request.
    function _settle(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) private returns (uint256 payout, int256 resolvedPrice) {
        bytes32 requestId = _getId(requester, identifier, timestamp, ancillaryData);
        _validateRequestHash(requestId, request);

        // Associate settled request params with ID.
        Request memory settledRequest =
            Request({
                proposer: request.proposer,
                disputer: request.disputer,
                currency: request.currency,
                settled: true, // Modified
                proposedPrice: request.proposedPrice,
                resolvedPrice: request.resolvedPrice,
                expirationTime: request.expirationTime,
                reward: request.reward,
                finalFee: request.finalFee,
                bond: request.bond,
                customLiveness: request.customLiveness
            });

        OptimisticOracleInterface.State state = _getState(requester, identifier, timestamp, ancillaryData, request);
        if (state == OptimisticOracleInterface.State.Expired) {
            // In the expiry case, just pay back the proposer's bond and final fee along with the reward.
            resolvedPrice = request.proposedPrice;
            settledRequest.resolvedPrice = resolvedPrice;
            payout = request.bond.add(request.finalFee).add(request.reward);
            request.currency.safeTransfer(request.proposer, payout);
        } else if (state == OptimisticOracleInterface.State.Resolved) {
            // In the Resolved case, pay either the disputer or the proposer the entire payout (+ bond and reward).
            resolvedPrice = _getOracle().getPrice(identifier, timestamp, _stampAncillaryData(ancillaryData, requester));
            settledRequest.resolvedPrice = resolvedPrice;
            bool disputeSuccess = settledRequest.resolvedPrice != request.proposedPrice;

            // Winner gets:
            // - Their bond back.
            // - The unburned portion of the loser's bond: proposal bond (not including final fee) - burned bond.
            // - Their final fee back.
            // - The request reward (if not already refunded -- if refunded, it will be set to 0).
            payout = request.bond.add(request.bond.sub(_computeBurnedBond(settledRequest))).add(request.finalFee).add(
                request.reward
            );
            request.currency.safeTransfer(disputeSuccess ? request.disputer : request.proposer, payout);
        } else {
            revert("Already settled or not settleable");
        }

        _storeRequestHash(requestId, settledRequest);
        emit Settle(requester, identifier, timestamp, ancillaryData, settledRequest);

        // Callback.
        if (address(requester).isContract())
            try
                OptimisticRequester(requester).priceSettled(identifier, timestamp, ancillaryData, settledRequest)
            {} catch {}
    }

    function _computeBurnedBond(Request memory request) private pure returns (uint256) {
        // burnedBond = floor(bond / 2)
        return request.bond.div(2);
    }

    function _validateLiveness(uint256 liveness) private pure {
        require(liveness < 5200 weeks, "Liveness too large");
        require(liveness > 0, "Liveness cannot be 0");
    }

    function _validateRequestHash(bytes32 requestId, Request memory request) private view {
        require(
            requests[requestId] == _getRequestHash(request),
            "Hashed request params do not match existing request hash"
        );
    }

    function _storeRequestHash(bytes32 requestId, Request memory request) internal {
        requests[requestId] = _getRequestHash(request);
    }

    function _getState(
        address requester,
        bytes32 identifier,
        uint32 timestamp,
        bytes memory ancillaryData,
        Request memory request
    ) internal view returns (OptimisticOracleInterface.State) {
        // Note: This function does not check whether all of the _request parameter values are correct. For example,
        // the request.reward could be any value and it would not impact this function's return value. Therefore, it
        // is the caller's responsibility to check that _request matches with the expected ID corresponding to
        // {requester, identifier, timestamp, ancillaryData} via _validateRequestHash().
        if (address(request.currency) == address(0)) return OptimisticOracleInterface.State.Invalid;

        if (request.proposer == address(0)) return OptimisticOracleInterface.State.Requested;

        if (request.settled) return OptimisticOracleInterface.State.Settled;

        if (request.disputer == address(0))
            return
                request.expirationTime <= getCurrentTime()
                    ? OptimisticOracleInterface.State.Expired
                    : OptimisticOracleInterface.State.Proposed;

        return
            _getOracle().hasPrice(identifier, timestamp, _stampAncillaryData(ancillaryData, requester))
                ? OptimisticOracleInterface.State.Resolved
                : OptimisticOracleInterface.State.Disputed;
    }

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

    function _getCollateralWhitelist() internal view returns (AddressWhitelist) {
        return AddressWhitelist(finder.getImplementationAddress(OracleInterfaces.CollateralWhitelist));
    }

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

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

    /**
     * @dev We don't handle specifically the case where `ancillaryData` is not already readily translateable in utf8.
     * For those cases, we assume that the client will be able to strip out the utf8-translateable part of the
     * ancillary data that this contract stamps.
     */
    function _stampAncillaryData(bytes memory ancillaryData, address requester) internal pure returns (bytes memory) {
        // Since this contract will be the one to formally submit DVM price requests, its useful for voters to know who
        // the original requester was.
        return AncillaryData.appendKeyValueAddress(ancillaryData, "ooRequester", requester);
    }
}

/**
 * @notice This is the SkinnyOptimisticOracle contract that should be deployed on live networks. It is exactly the same
 * as the regular SkinnyOptimisticOracle contract, but it overrides getCurrentTime to make the call a simply return
 * block.timestamp with no branching or storage queries.
 */
contract SkinnyOptimisticOracleProd is SkinnyOptimisticOracle {
    constructor(
        uint256 _liveness,
        address _finderAddress,
        address _timerAddress
    ) SkinnyOptimisticOracle(_liveness, _finderAddress, _timerAddress) {}

    function getCurrentTime() public view virtual override returns (uint256) {
        return block.timestamp;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_liveness","type":"uint256"},{"internalType":"address","name":"_finderAddress","type":"address"},{"internalType":"address","name":"_timerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"indexed":false,"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"DisputePrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"indexed":false,"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"ProposePrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"indexed":false,"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"RequestPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"indexed":false,"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"Settle","type":"event"},{"inputs":[],"name":"ancillaryBytesLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultLiveness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"disputePrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"address","name":"requester","type":"address"}],"name":"disputePriceFor","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finder","outputs":[{"internalType":"contract FinderInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"getState","outputs":[{"internalType":"enum OptimisticOracleInterface.State","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"hasPrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"},{"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"proposePrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"proposePriceFor","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"requestAndProposePriceFor","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"name":"requestPrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requests","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct SkinnyOptimisticOracleInterface.Request","name":"request","type":"tuple"}],"name":"settle","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"address","name":"requester","type":"address"}],"name":"stampAncillaryData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162003b7938038062003b79833981016040819052620000349162000149565b60008054600160a01b6001600160a01b038481166001600160a81b03199093169290921717909155600280546001600160a01b0319169184169190911790556200007e8362000089565b50506003556200018a565b63bb7448008110620000d75760405162461bcd60e51b81526020600482015260126024820152714c6976656e65737320746f6f206c6172676560701b60448201526064015b60405180910390fd5b60008111620001295760405162461bcd60e51b815260206004820152601460248201527f4c6976656e6573732063616e6e6f7420626520300000000000000000000000006044820152606401620000ce565b50565b80516001600160a01b03811681146200014457600080fd5b919050565b6000806000606084860312156200015f57600080fd5b8351925062000171602085016200012c565b915062000181604085016200012c565b90509250925092565b6139df806200019a6000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c8063a337e1ad116100b2578063b730539f11610081578063c371dda711610066578063c371dda7146102bf578063d6228407146102c8578063fe4e1983146102db57600080fd5b8063b730539f14610277578063b9a3c84c1461029f57600080fd5b8063a337e1ad1461020e578063af355d1e14610231578063af5d2f3914610244578063b1a166b21461026457600080fd5b806351205554116100ee57806351205554146101a857806393c44ef7146101c85780639ce320c8146101db5780639d866985146101ee57600080fd5b80631c39c38d1461012057806322f8e5661461016a57806329cb924d1461017f5780633a31577e14610195575b600080fd5b6000546101409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61017d610178366004612ec9565b6102e4565b005b61018761038d565b604051908152602001610161565b6101876101a33660046130f5565b610454565b6101bb6101b63660046130f5565b610470565b60405161016191906131a1565b6101876101d63660046131e2565b6104fa565b6101876101e9366004613268565b610518565b6101876101fc366004612ec9565b60016020526000908152604090205481565b61022161021c3660046130f5565b610a40565b6040519015158152602001610161565b61018761023f3660046132fa565b610b37565b6102576102523660046133a0565b611288565b6040516101619190613468565b61018761027236600461347b565b61129d565b61028a6102853660046130f5565b611637565b60408051928352602083019190915201610161565b6002546101409073ffffffffffffffffffffffffffffffffffffffff1681565b61018761200081565b6101876102d6366004613518565b6116ce565b61018760035481565b60005473ffffffffffffffffffffffffffffffffffffffff1661030657600080fd5b6000546040517f22f8e5660000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff909116906322f8e56690602401600060405180830381600087803b15801561037257600080fd5b505af1158015610386573d6000803e3d6000fd5b5050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff161561044f5760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561041257600080fd5b505afa158015610426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a919061359d565b905090565b504290565b600061046485858585338b610518565b90505b95945050505050565b600061047a611cf6565b6104a7600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6104b48686868686611d7c565b9050610467600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b600061050b8787878787338861129d565b90505b9695505050505050565b6000610522611cf6565b61054f600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b73ffffffffffffffffffffffffffffffffffffffff83166105d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f64697370757465722061646472657373206d757374206265206e6f6e2030000060448201526064015b60405180910390fd5b60026105e08389898989611d7c565b60068111156105f1576105f1613172565b14610658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d7573742062652070726f706f7365640000000000000000000000000000000060448201526064016105c8565b600061066683898989611ed3565b90506106728186611f0d565b6000604051806101600160405280876000015173ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff168152602001876040015173ffffffffffffffffffffffffffffffffffffffff168152602001876060015115158152602001876080015181526020018760a0015181526020018760c0015181526020018760e00151815260200187610100015181526020018761012001518152602001876101400151815250905061073b8282611fb6565b61010086015161012087015161075091611fd5565b9250821561077f57604086015161077f9073ffffffffffffffffffffffffffffffffffffffff16333086611fe1565b60006107896120c3565b9050600061079683612186565b905060006107b2828a6101000151611fd590919063ffffffff16565b905080156108835760408901516107e09073ffffffffffffffffffffffffffffffffffffffff16848361219a565b6107e86120c3565b60408a810151815160208101835284815291517f8659d23200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152915160248301529190911690638659d23290604401600060405180830381600087803b15801561086a57600080fd5b505af115801561087e573d6000803e3d6000fd5b505050505b505061088d6122a7565b73ffffffffffffffffffffffffffffffffffffffff1663216666a48b8b6108b48c8a61231e565b6040518463ffffffff1660e01b81526004016108d2939291906135b6565b600060405180830381600087803b1580156108ec57600080fd5b505af1158015610900573d6000803e3d6000fd5b50505050898573ffffffffffffffffffffffffffffffffffffffff167f2d2ed23d7d2e875b405c36213cc1668e3adf8b4d845653bd9f977c313d599ffe8b8b8660405161094f939291906136a3565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff85163b156109f9576040517f11bad40a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616906311bad40a906109cc908d908d908d9088906004016136d3565b600060405180830381600087803b1580156109e657600080fd5b505af19250505080156109f7575060015b505b50505061050e600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b6000610a4a611cf6565b610a77600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6000610a8587878787611ed3565b9050610a918184611f0d565b6000610aa08888888888611d7c565b90506006816006811115610ab657610ab6613172565b1480610ad357506005816006811115610ad157610ad1613172565b145b80610aef57506003816006811115610aed57610aed613172565b145b92505050610467600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b600080610b46338c8c8c611ed3565b60008181526001602052604090205490915015610bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5265717565737420616c726561647920696e697469616c697a6564000000000060448201526064016105c8565b73ffffffffffffffffffffffffffffffffffffffff8416610c3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f70726f706f7365722061646472657373206d757374206265206e6f6e2030000060448201526064016105c8565b610c44612360565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b8c6040518263ffffffff1660e01b8152600401610c7e91815260200190565b60206040518083038186803b158015610c9657600080fd5b505afa158015610caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce9190613709565b610d34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e737570706f72746564206964656e7469666965720000000000000000000060448201526064016105c8565b610d3c6123d7565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301529190911690633a3ab6729060240160206040518083038186803b158015610da557600080fd5b505afa158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddd9190613709565b610e43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e737570706f727465642063757272656e637900000000000000000000000060448201526064016105c8565b610e4b61038d565b8a63ffffffff161115610eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f54696d657374616d7020696e206675747572650000000000000000000000000060448201526064016105c8565b612000610ec78a3361231e565b511115610f30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f416e63696c6c617279204461746120746f6f206c6f6e6700000000000000000060448201526064016105c8565b6000610f3a6120c3565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b811660048301529190911690635b97aadd9060240160206040518083038186803b158015610fa357600080fd5b505afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb9190613726565b600001519050611082604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff808b16604083015260e082018a905261010082018390526101208201899052610140820188905286168152608081018590526110e9876110d9576003546110db565b875b6110e361038d565b90611fd5565b60c08201526110f88382611fb6565b88156111205761112073ffffffffffffffffffffffffffffffffffffffff8b1633308c611fe1565b61010081015161012082015161113591611fd5565b9350831561115f5761115f73ffffffffffffffffffffffffffffffffffffffff8b16333087611fe1565b8c3373ffffffffffffffffffffffffffffffffffffffff167f6f8b57987b901f40681c863d8aed32c2cc6150062aa4ddb828c89aaa896c16688e8e856040516111aa939291906136a3565b60405180910390a38c3373ffffffffffffffffffffffffffffffffffffffff167fdb27b6b59f934dc351fe9188a12f94a06c3c867c683c6e65c7e2b4c8aa6e9a048e8e856040516111fd939291906136a3565b60405180910390a3333b15611278573373ffffffffffffffffffffffffffffffffffffffff1663724f18148e8e8e856040518563ffffffff1660e01b815260040161124b94939291906136d3565b600060405180830381600087803b15801561126557600080fd5b505af1925050508015611276575060015b505b5050509998505050505050505050565b6060611294838361231e565b90505b92915050565b60006112a7611cf6565b6112d4600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b73ffffffffffffffffffffffffffffffffffffffff8316611351576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f706f7365722061646472657373206d757374206265206e6f6e2030000060448201526064016105c8565b60016113608989898989611d7c565b600681111561137157611371613172565b146113d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4d7573742062652072657175657374656400000000000000000000000000000060448201526064016105c8565b60006113e689898989611ed3565b90506113f28186611f0d565b60006040518061016001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001876020015173ffffffffffffffffffffffffffffffffffffffff168152602001876040015173ffffffffffffffffffffffffffffffffffffffff1681526020018760600151151581526020018581526020018760a00151815260200161149f88610140015160001415611491576003546110db565b8861014001516110e361038d565b81526020018760e0015181526020018761010001518152602001876101200151815260200187610140015181525090506114d98282611fb6565b6101008601516101208701516114ee91611fd5565b9250821561151d57604086015161151d9073ffffffffffffffffffffffffffffffffffffffff16333086611fe1565b888a73ffffffffffffffffffffffffffffffffffffffff167fdb27b6b59f934dc351fe9188a12f94a06c3c867c683c6e65c7e2b4c8aa6e9a048a8a85604051611568939291906136a3565b60405180910390a3333b156115e6576040517f724f1814000000000000000000000000000000000000000000000000000000008152339063724f1814906115b9908c908c908c9087906004016136d3565b600060405180830381600087803b1580156115d357600080fd5b505af19250505080156115e4575060015b505b505061162c600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b979650505050505050565b600080611642611cf6565b61166f600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b61167c878787878761244e565b915091506116c4600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b9550959350505050565b60006116d8611cf6565b611705600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6000611713338a8a8a611ed3565b6000818152600160205260409020549091501561178c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5265717565737420616c726561647920696e697469616c697a6564000000000060448201526064016105c8565b611794612360565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b8a6040518263ffffffff1660e01b81526004016117ce91815260200190565b60206040518083038186803b1580156117e657600080fd5b505afa1580156117fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181e9190613709565b611884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e737570706f72746564206964656e7469666965720000000000000000000060448201526064016105c8565b61188c6123d7565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff88811660048301529190911690633a3ab6729060240160206040518083038186803b1580156118f557600080fd5b505afa158015611909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192d9190613709565b611993576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e737570706f727465642063757272656e637900000000000000000000000060448201526064016105c8565b61199b61038d565b8863ffffffff161115611a0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f54696d657374616d7020696e206675747572650000000000000000000000000060448201526064016105c8565b612000611a17883361231e565b511115611a80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f416e63696c6c617279204461746120746f6f206c6f6e6700000000000000000060448201526064016105c8565b6000611a8a6120c3565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301529190911690635b97aadd9060240160206040518083038186803b158015611af357600080fd5b505afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190613726565b600001519050611bd2604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff8816604082015260e08101879052610100810182905285611c085781611c0a565b855b6101208201526101408101859052611c228382611fb6565b8615611c4a57611c4a73ffffffffffffffffffffffffffffffffffffffff891633308a611fe1565b8a3373ffffffffffffffffffffffffffffffffffffffff167f6f8b57987b901f40681c863d8aed32c2cc6150062aa4ddb828c89aaa896c16688c8c85604051611c95939291906136a3565b60405180910390a3610120810151611cad9083611fd5565b935050505061162c600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b60005474010000000000000000000000000000000000000000900460ff16611d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105c8565b565b604081015160009073ffffffffffffffffffffffffffffffffffffffff16611da657506000610467565b815173ffffffffffffffffffffffffffffffffffffffff16611dca57506001610467565b816060015115611ddc57506006610467565b602082015173ffffffffffffffffffffffffffffffffffffffff16611e1f57611e0361038d565b8260c001511115611e15576002611e18565b60035b9050610467565b611e276122a7565b73ffffffffffffffffffffffffffffffffffffffff1663b551cd508686611e4e878b61231e565b6040518463ffffffff1660e01b8152600401611e6c939291906135b6565b60206040518083038186803b158015611e8457600080fd5b505afa158015611e98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ebc9190613709565b611ec7576004610464565b50600595945050505050565b600084848484604051602001611eec9493929190613768565b6040516020818303038152906040528051906020012090505b949350505050565b611f168161288a565b60008381526001602052604090205414611fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f486173686564207265717565737420706172616d7320646f206e6f74206d617460448201527f6368206578697374696e6720726571756573742068617368000000000000000060648201526084016105c8565b5050565b611fbf8161288a565b6000928352600160205260409092209190915550565b600061129482846137d8565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526120bd9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526128ba565b50505050565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f53746f7265000000000000000000000000000000000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e40906024015b60206040518083038186803b15801561214e57600080fd5b505afa158015612162573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a91906137f0565b6101208101516000906112979060026129cb565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b15801561220c57600080fd5b505afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612244919061359d565b61224e91906137d8565b60405173ffffffffffffffffffffffffffffffffffffffff85166024820152604481018290529091506120bd9085907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161203b565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4f7261636c650000000000000000000000000000000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612136565b6060611294836040518060400160405280600b81526020017f6f6f526571756573746572000000000000000000000000000000000000000000815250846129d7565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4964656e74696669657257686974656c69737400000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612136565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f436f6c6c61746572616c57686974656c69737400000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612136565b600080600061245f88888888611ed3565b905061246b8185611f0d565b6000604051806101600160405280866000015173ffffffffffffffffffffffffffffffffffffffff168152602001866020015173ffffffffffffffffffffffffffffffffffffffff168152602001866040015173ffffffffffffffffffffffffffffffffffffffff168152602001600115158152602001866080015181526020018660a0015181526020018660c0015181526020018660e001518152602001866101000151815260200186610120015181526020018661014001518152509050600061253a8a8a8a8a8a611d7c565b9050600381600681111561255057612550613172565b14156125b357608086015160a0830181905260e0870151610100880151610120890151929650612583926110e391611fd5565b865160408801519196506125ae9173ffffffffffffffffffffffffffffffffffffffff169087612a1e565b61277e565b60058160068111156125c7576125c7613172565b14156126f6576125d56122a7565b73ffffffffffffffffffffffffffffffffffffffff1663719c6d568a8a6125fc8b8f61231e565b6040518463ffffffff1660e01b815260040161261a939291906135b6565b60206040518083038186803b15801561263257600080fd5b505afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266a919061359d565b60a08301819052608087015160e088015161010089015192965090861415916126b791906110e390816126ab61269f89612186565b6101208e015190612a74565b6101208d015190611fd5565b95506126f0816126c85787516126ce565b87602001515b604089015173ffffffffffffffffffffffffffffffffffffffff169088612a1e565b5061277e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f416c726561647920736574746c6564206f72206e6f7420736574746c6561626c60448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016105c8565b6127888383611fb6565b888a73ffffffffffffffffffffffffffffffffffffffff167f0a9a88a76857159cb49d0944fe45537825a67ea75e0df805097782be5bdcd0af8a8a866040516127d3939291906136a3565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff8a163b1561287d576040517f827e7f3e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b169063827e7f3e90612850908c908c908c9088906004016136d3565b600060405180830381600087803b15801561286a57600080fd5b505af192505050801561287b575060015b505b5050509550959350505050565b60008160405160200161289d919061380d565b604051602081830303815290604052805190602001209050919050565b600061291c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612a809092919063ffffffff16565b8051909150156129c6578080602001905181019061293a9190613709565b6129c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105c8565b505050565b6000611294828461384b565b606060006129e58585612a8f565b905084816129f285612ad1565b604051602001612a0493929190613886565b6040516020818303038152906040529150505b9392505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526129c69084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161203b565b600061129482846138c9565b6060611f058484600085612b5f565b815160609015612ac05781604051602001612aaa91906138e0565b6040516020818303038152906040529050611297565b81604051602001612aaa919061394c565b6060612af26fffffffffffffffffffffffffffffffff602084901c16612cd4565b612b0d8360601b6bffffffffffffffffffffffff1916612cd4565b604051602001612b499291909182527fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040529050919050565b606082471015612bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105c8565b843b612c59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105c8565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612c82919061398d565b60006040518083038185875af1925050503d8060008114612cbf576040519150601f19603f3d011682016040523d82523d6000602084013e612cc4565b606091505b509150915061162c828286612e76565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f08080808080808080808080808080808080808080808080808080808080808081681612df857612df861381c565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b60608315612e85575081612a17565b825115612e955782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105c89190613468565b600060208284031215612edb57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114612f0457600080fd5b50565b8035612f1281612ee2565b919050565b803563ffffffff81168114612f1257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715612f7e57612f7e612f2b565b60405290565b600082601f830112612f9557600080fd5b813567ffffffffffffffff80821115612fb057612fb0612f2b565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612ff657612ff6612f2b565b8160405283815286602085880101111561300f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b8015158114612f0457600080fd5b8035612f128161302f565b6000610160828403121561305b57600080fd5b613063612f5a565b905061306e82612f07565b815261307c60208301612f07565b602082015261308d60408301612f07565b604082015261309e6060830161303d565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525061012080830135818301525061014080830135818301525092915050565b60008060008060006101e0868803121561310e57600080fd5b853561311981612ee2565b94506020860135935061312e60408701612f17565b9250606086013567ffffffffffffffff81111561314a57600080fd5b61315688828901612f84565b9250506131668760808801613048565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600783106131dc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060008060008061020087890312156131fc57600080fd5b863561320781612ee2565b95506020870135945061321c60408801612f17565b9350606087013567ffffffffffffffff81111561323857600080fd5b61324489828a01612f84565b9350506132548860808901613048565b91506101e087013590509295509295509295565b600080600080600080610200878903121561328257600080fd5b8635955061329260208801612f17565b9450604087013567ffffffffffffffff8111156132ae57600080fd5b6132ba89828a01612f84565b9450506132ca8860608901613048565b92506101c08701356132db81612ee2565b91506101e08701356132ec81612ee2565b809150509295509295509295565b60008060008060008060008060006101208a8c03121561331957600080fd5b8935985061332960208b01612f17565b975060408a013567ffffffffffffffff81111561334557600080fd5b6133518c828d01612f84565b97505060608a013561336281612ee2565b955060808a0135945060a08a0135935060c08a0135925060e08a013561338781612ee2565b809250506101008a013590509295985092959850929598565b600080604083850312156133b357600080fd5b823567ffffffffffffffff8111156133ca57600080fd5b6133d685828601612f84565b92505060208301356133e781612ee2565b809150509250929050565b60005b8381101561340d5781810151838201526020016133f5565b838111156120bd5750506000910152565b600081518084526134368160208601602086016133f2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611294602083018461341e565b6000806000806000806000610220888a03121561349757600080fd5b87356134a281612ee2565b9650602088013595506134b760408901612f17565b9450606088013567ffffffffffffffff8111156134d357600080fd5b6134df8a828b01612f84565b9450506134ef8960808a01613048565b92506101e088013561350081612ee2565b80925050610200880135905092959891949750929550565b600080600080600080600060e0888a03121561353357600080fd5b8735965061354360208901612f17565b9550604088013567ffffffffffffffff81111561355f57600080fd5b61356b8a828b01612f84565b955050606088013561357c81612ee2565b9699959850939660808101359560a0820135955060c0909101359350915050565b6000602082840312156135af57600080fd5b5051919050565b83815263ffffffff83166020820152606060408201526000610467606083018461341e565b805173ffffffffffffffffffffffffffffffffffffffff168252602081015161361c602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040810151613644604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060810151613658606084018215159052565b506080818101519083015260a0808201519083015260c0808201519083015260e080820151908301526101008082015190830152610120808201519083015261014090810151910152565b60006101a063ffffffff861683528060208401526136c38184018661341e565b915050611f0560408301846135db565b60006101c086835263ffffffff861660208401528060408401526136f98184018661341e565b91505061046760608301846135db565b60006020828403121561371b57600080fd5b8151612a178161302f565b60006020828403121561373857600080fd5b6040516020810181811067ffffffffffffffff8211171561375b5761375b612f2b565b6040529151825250919050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015263ffffffff83166040820152608060608201526000610464608083018461341e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156137eb576137eb6137a9565b500190565b60006020828403121561380257600080fd5b8151612a1781612ee2565b610160810161129782846135db565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613881577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600084516138988184602089016133f2565b8451908301906138ac8183602089016133f2565b84519101906138bf8183602088016133f2565b0195945050505050565b6000828210156138db576138db6137a9565b500390565b7f2c000000000000000000000000000000000000000000000000000000000000008152600082516139188160018501602087016133f2565b7f3a000000000000000000000000000000000000000000000000000000000000006001939091019283015250600201919050565b6000825161395e8184602087016133f2565b7f3a00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b6000825161399f8184602087016133f2565b919091019291505056fea2646970667358221220646dae79d706d017d6d602cb7c3449713d448e652942dc33ff3c39919c23b0d264736f6c634300080900330000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c30000000000000000000000000000000000000000000000000000000000000000

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

0000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c30000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _liveness (uint256): 7200
Arg [1] : _finderAddress (address): 0x40f941E48A552bF496B154Af6bf55725f18D77c3
Arg [2] : _timerAddress (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000001c20
Arg [1] : 00000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c3
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

108733:29373:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87935:27;;;;;;;;;;;;322:42:1;310:55;;;292:74;;280:2;265:18;87935:27:0;;;;;;;;88665:117;;;;;;:::i;:::-;;:::i;:::-;;89034:282;;;:::i;:::-;;;708:25:1;;;696:2;681:18;89034:282:0;562:177:1;125753:403:0;;;;;;:::i;:::-;;:::i;127780:347::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116890:449::-;;;;;;:::i;:::-;;:::i;122145:2864::-;;;;;;:::i;:::-;;:::i;109825:43::-;;;;;;:::i;:::-;;;;;;;;;;;;;;128888:698;;;;;;:::i;:::-;;:::i;:::-;;;7234:14:1;;7227:22;7209:41;;7197:2;7182:18;128888:698:0;7069:187:1;118869:2349:0;;;;;;:::i;:::-;;:::i;129910:231::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;114076:2072::-;;;;;;:::i;:::-;;:::i;126948:348::-;;;;;;:::i;:::-;;:::i;:::-;;;;10657:25:1;;;10713:2;10698:18;;10691:34;;;;10630:18;126948:348:0;10485:246:1;109932:29:0;;;;;;;;;72856:50;;72902:4;72856:50;;111596:1555;;;;;;:::i;:::-;;:::i;110025:30::-;;;;;;88665:117;88458:3;88434:12;:28;:12;88426:37;;;;;;88740:12:::1;::::0;88734:40:::1;::::0;;;;::::1;::::0;::::1;708:25:1::0;;;88740:12:0::1;::::0;;::::1;::::0;88734:34:::1;::::0;681:18:1;;88734:40:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;88665:117:::0;:::o;89034:282::-;89089:7;89113:12;;:28;:12;:28;89109:200;;89171:12;;;;;;;;;;89165:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89158:43;;89034:282;:::o;89109:200::-;-1:-1:-1;89241:15:0;;89034:282::o;125753:403::-;125963:17;126063:85;126079:10;126091:9;126102:13;126117:7;126126:10;126138:9;126063:15;:85::i;:::-;126056:92;;125753:403;;;;;;;;:::o;127780:347::-;128001:31;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;128052:67:::1;128062:9;128073:10;128085:9;128096:13;128111:7;128052:9;:67::i;:::-;128045:74;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;116890:449;117131:17;117231:100;117247:9;117258:10;117270:9;117281:13;117296:7;117305:10;117317:13;117231:15;:100::i;:::-;117224:107;;116890:449;;;;;;;;;:::o;122145:2864::-;122398:17;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;122436:22:::1;::::0;::::1;122428:65;;;::::0;::::1;::::0;;12203:2:1;122428:65:0::1;::::0;::::1;12185:21:1::0;12242:2;12222:18;;;12215:30;12281:32;12261:18;;;12254:60;12331:18;;122428:65:0::1;;;;;;;;;122614:40;122526:67;122536:9;122547:10;122559:9;122570:13;122585:7;122526:9;:67::i;:::-;:128;;;;;;;;:::i;:::-;;122504:194;;;::::0;::::1;::::0;;12562:2:1;122504:194:0::1;::::0;::::1;12544:21:1::0;12601:2;12581:18;;;12574:30;12640:18;12620;;;12613:46;12676:18;;122504:194:0::1;12360:340:1::0;122504:194:0::1;122709:17;122729:55;122736:9;122747:10;122759:9;122770:13;122729:6;:55::i;:::-;122709:75;;122795:40;122816:9;122827:7;122795:20;:40::i;:::-;122908:30;122954:553;;;;;;;;122991:7;:16;;;122954:553;;;;;;123036:8;122954:553;;;;;;123085:7;:16;;;122954:553;;;;;;123129:7;:15;;;122954:553;;;;;;123178:7;:21;;;122954:553;;;;123233:7;:21;;;122954:553;;;;123289:7;:22;;;122954:553;;;;123338:7;:14;;;122954:553;;;;123381:7;:16;;;122954:553;;;;123422:7;:12;;;122954:553;;;;123469:7;:22;;;122954:553;;::::0;122908:599:::1;;123518:45;123536:9;123547:15;123518:17;:45::i;:::-;123605:16;::::0;::::1;::::0;123588:12:::1;::::0;::::1;::::0;:34:::1;::::0;:16:::1;:34::i;:::-;123576:46:::0;-1:-1:-1;123637:13:0;;123633:90:::1;;123652:16;::::0;::::1;::::0;:71:::1;::::0;:33:::1;;123686:10;123706:4;123713:9:::0;123652:33:::1;:71::i;:::-;123736:20;123759:11;:9;:11::i;:::-;123736:34;;124110:18;124131:35;124150:15;124131:18;:35::i;:::-;124110:56;;124266:16;124285:32;124306:10;124285:7;:16;;;:20;;:32;;;;:::i;:::-;124266:51:::0;-1:-1:-1;124338:12:0;;124334:224:::1;;124371:16;::::0;::::1;::::0;:64:::1;::::0;:38:::1;;124418:5:::0;124426:8;124371:38:::1;:64::i;:::-;124454:11;:9;:11::i;:::-;124493:16;::::0;;::::1;::::0;124512:29;;::::1;::::0;::::1;::::0;;;;;124454:88;;;;;:30:::1;12947:55:1::0;;;124454:88:0::1;::::0;::::1;12929:74:1::0;13039:13;;13019:18;;;13012:41;124454:30:0;;;::::1;::::0;::::1;::::0;12902:18:1;;124454:88:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;124334:224;123836:733;;124581:12;:10;:12::i;:::-;:25;;;124607:10;124619:9;124630:45;124650:13;124665:9;124630:19;:45::i;:::-;124581:95;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;124718:10;124707:9;124694:78;;;124730:9;124741:13;124756:15;124694:78;;;;;;;;:::i;:::-;;;;;;;;124811:29;::::0;::::1;4014:20:::0;4053:8;124807:195:::1;;124878:99;::::0;;;;:44:::1;::::0;::::1;::::0;::::1;::::0;:99:::1;::::0;124923:10;;124935:9;;124946:13;;124961:15;;124878:99:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;124857:145:::0;::::1;122417:2592;;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;128888:698;129107:4;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;129124::::1;129144:55;129151:9;129162:10;129174:9;129185:13;129144:6;:55::i;:::-;129124:75;;129210:40;129231:9;129242:7;129210:20;:40::i;:::-;129261:37;129301:67;129311:9;129322:10;129334:9;129345:13;129360:7;129301:9;:67::i;:::-;129261:107:::0;-1:-1:-1;129408:39:0::1;129399:5;:48;;;;;;;;:::i;:::-;;:114;;;-1:-1:-1::0;129473:40:0::1;129464:5;:49;;;;;;;;:::i;:::-;;129399:114;:179;;;-1:-1:-1::0;129539:39:0::1;129530:5;:48;;;;;;;;:::i;:::-;;129399:179;129379:199;;;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;118869:2349;119196:17;119226;119246:56;119253:10;119265;119277:9;119288:13;119246:6;:56::i;:::-;119352:1;119321:19;;;:8;:19;;;;;;119226:76;;-1:-1:-1;119321:33:0;119313:73;;;;;;;15553:2:1;119313:73:0;;;15535:21:1;15592:2;15572:18;;;15565:30;15631:29;15611:18;;;15604:57;15678:18;;119313:73:0;15351:351:1;119313:73:0;119405:22;;;119397:65;;;;;;;15909:2:1;119397:65:0;;;15891:21:1;15948:2;15928:18;;;15921:30;15987:32;15967:18;;;15960:60;16037:18;;119397:65:0;15707:354:1;119397:65:0;119481:25;:23;:25::i;:::-;:47;;;119529:10;119481:59;;;;;;;;;;;;;708:25:1;;696:2;681:18;;562:177;119481:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119473:94;;;;;;;16518:2:1;119473:94:0;;;16500:21:1;16557:2;16537:18;;;16530:30;16596:24;16576:18;;;16569:52;16638:18;;119473:94:0;16316:346:1;119473:94:0;119586:25;:23;:25::i;:::-;:58;;;;;:39;310:55:1;;;119586:58:0;;;292:74:1;119586:39:0;;;;;;;265:18:1;;119586:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119578:91;;;;;;;16869:2:1;119578:91:0;;;16851:21:1;16908:2;16888:18;;;16881:30;16947:22;16927:18;;;16920:50;16987:18;;119578:91:0;16667:344:1;119578:91:0;119701:16;:14;:16::i;:::-;119688:9;:29;;;;119680:61;;;;;;;17218:2:1;119680:61:0;;;17200:21:1;17257:2;17237:18;;;17230:30;17296:21;17276:18;;;17269:49;17335:18;;119680:61:0;17016:343:1;119680:61:0;72902:4;119774:46;119794:13;119809:10;119774:19;:46::i;:::-;:53;:76;;119752:149;;;;;;;17566:2:1;119752:149:0;;;17548:21:1;17605:2;17585:18;;;17578:30;17644:25;17624:18;;;17617:53;17687:18;;119752:149:0;17364:347:1;119752:149:0;119912:16;119931:11;:9;:11::i;:::-;:46;;;;;:27;310:55:1;;;119931:46:0;;;292:74:1;119931:27:0;;;;;;;265:18:1;;119931:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;119912:74;;120041:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120041:22:0;120074:27;;;;:16;;;:27;120112:14;;;:23;;;120146:16;;;:27;;;120184:12;;;:19;;;120214:22;;;:39;;;120264:27;;;;120302:21;;;:37;;;120375:76;120396:19;:54;;120435:15;;120396:54;;;120418:14;120396:54;120375:16;:14;:16::i;:::-;:20;;:76::i;:::-;120350:22;;;:101;120462:37;120480:9;120350:7;120462:17;:37::i;:::-;120575:10;;120571:76;;120587:60;:25;;;120613:10;120633:4;120640:6;120587:25;:60::i;:::-;120731:16;;;;120714:12;;;;:34;;:16;:34::i;:::-;120702:46;-1:-1:-1;120763:13:0;;120759:82;;120778:63;:25;;;120804:10;120824:4;120831:9;120778:25;:63::i;:::-;120884:10;120872;120859:71;;;120896:9;120907:13;120922:7;120859:71;;;;;;;;:::i;:::-;;;;;;;;120971:10;120959;120946:71;;;120983:9;120994:13;121009:7;120946:71;;;;;;;;:::i;:::-;;;;;;;;121064:10;4014:20;4053:8;121052:159;;121127:10;121107:45;;;121153:10;121165:9;121176:13;121191:7;121107:92;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121103:108;;119215:2003;;;118869:2349;;;;;;;;;;;:::o;129910:231::-;130051:12;130088:45;130108:13;130123:9;130088:19;:45::i;:::-;130081:52;;129910:231;;;;;:::o;114076:2072::-;114360:17;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;114398:22:::1;::::0;::::1;114390:65;;;::::0;::::1;::::0;;18365:2:1;114390:65:0::1;::::0;::::1;18347:21:1::0;18404:2;18384:18;;;18377:30;18443:32;18423:18;;;18416:60;18493:18;;114390:65:0::1;18163:354:1::0;114390:65:0::1;114576:41;114488:67;114498:9;114509:10;114521:9;114532:13;114547:7;114488:9;:67::i;:::-;:129;;;;;;;;:::i;:::-;;114466:196;;;::::0;::::1;::::0;;18724:2:1;114466:196:0::1;::::0;::::1;18706:21:1::0;18763:2;18743:18;;;18736:30;18802:19;18782:18;;;18775:47;18839:18;;114466:196:0::1;18522:341:1::0;114466:196:0::1;114673:17;114693:55;114700:9;114711:10;114723:9;114734:13;114693:6;:55::i;:::-;114673:75;;114759:40;114780:9;114791:7;114759:20;:40::i;:::-;114872:30;114918:679;;;;;;;;114955:8;114918:679;;;;;;115004:7;:16;;;114918:679;;;;;;115049:7;:16;;;114918:679;;;;;;115093:7;:15;;;114918:679;;;;;;115142:13;114918:679;;;;115201:7;:21;;;114918:679;;;;115257:132;115300:7;:22;;;115326:1;115300:27;;:70;;115355:15;;115300:70;;;115330:7;:22;;;115257:16;:14;:16::i;:132::-;114918:679;;;;115428:7;:14;;;114918:679;;;;115471:7;:16;;;114918:679;;;;115512:7;:12;;;114918:679;;;;115559:7;:22;;;114918:679;;::::0;114872:725:::1;;115608:45;115626:9;115637:15;115608:17;:45::i;:::-;115695:16;::::0;::::1;::::0;115678:12:::1;::::0;::::1;::::0;:34:::1;::::0;:16:::1;:34::i;:::-;115666:46:::0;-1:-1:-1;115727:13:0;;115723:90:::1;;115742:16;::::0;::::1;::::0;:71:::1;::::0;:33:::1;;115776:10;115796:4;115803:9:::0;115742:33:::1;:71::i;:::-;115855:10;115844:9;115831:78;;;115867:9;115878:13;115893:15;115831:78;;;;;;;;:::i;:::-;;;;;;;;115956:10;4014:20:::0;4053:8;115944:197:::1;;116016:100;::::0;;;;116036:10:::1;::::0;116016:45:::1;::::0;:100:::1;::::0;116062:10;;116074:9;;116085:13;;116100:15;;116016:100:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;115995:146:::0;::::1;114379:1769;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;90753:20;114076:2072;;;;;;;;;:::o;126948:348::-;127167:14;127183:20;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;127223:65:::1;127231:9;127242:10;127254:9;127265:13;127280:7;127223;:65::i;:::-;127216:72;;;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;90753:20;126948:348;;;;;;;;:::o;111596:1555::-;111867:17;90683:19;:17;:19::i;:::-;90713:17;91851:5;91837:19;;;;;;91725:139;90713:17;111897::::1;111917:56;111924:10;111936;111948:9;111959:13;111917:6;:56::i;:::-;112023:1;111992:19:::0;;;:8:::1;:19;::::0;;;;;111897:76;;-1:-1:-1;111992:33:0;111984:73:::1;;;::::0;::::1;::::0;;15553:2:1;111984:73:0::1;::::0;::::1;15535:21:1::0;15592:2;15572:18;;;15565:30;15631:29;15611:18;;;15604:57;15678:18;;111984:73:0::1;15351:351:1::0;111984:73:0::1;112076:25;:23;:25::i;:::-;:47;;;112124:10;112076:59;;;;;;;;;;;;;708:25:1::0;;696:2;681:18;;562:177;112076:59:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112068:94;;;::::0;::::1;::::0;;16518:2:1;112068:94:0::1;::::0;::::1;16500:21:1::0;16557:2;16537:18;;;16530:30;16596:24;16576:18;;;16569:52;16638:18;;112068:94:0::1;16316:346:1::0;112068:94:0::1;112181:25;:23;:25::i;:::-;:58;::::0;;;;:39:::1;310:55:1::0;;;112181:58:0::1;::::0;::::1;292:74:1::0;112181:39:0;;;::::1;::::0;::::1;::::0;265:18:1;;112181:58:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112173:91;;;::::0;::::1;::::0;;16869:2:1;112173:91:0::1;::::0;::::1;16851:21:1::0;16908:2;16888:18;;;16881:30;16947:22;16927:18;;;16920:50;16987:18;;112173:91:0::1;16667:344:1::0;112173:91:0::1;112296:16;:14;:16::i;:::-;112283:9;:29;;;;112275:61;;;::::0;::::1;::::0;;17218:2:1;112275:61:0::1;::::0;::::1;17200:21:1::0;17257:2;17237:18;;;17230:30;17296:21;17276:18;;;17269:49;17335:18;;112275:61:0::1;17016:343:1::0;112275:61:0::1;72902:4;112369:46;112389:13;112404:10;112369:19;:46::i;:::-;:53;:76;;112347:149;;;::::0;::::1;::::0;;17566:2:1;112347:149:0::1;::::0;::::1;17548:21:1::0;17605:2;17585:18;;;17578:30;17644:25;17624:18;;;17617:53;17687:18;;112347:149:0::1;17364:347:1::0;112347:149:0::1;112507:16;112526:11;:9;:11::i;:::-;:46;::::0;;;;:27:::1;310:55:1::0;;;112526:46:0::1;::::0;::::1;292:74:1::0;112526:27:0;;;::::1;::::0;::::1;::::0;265:18:1;;112526:46:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;;;112507:74;;112636:22;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112636:22:0::1;112669:27;::::0;::::1;:16;::::0;::::1;:27:::0;112707:14:::1;::::0;::::1;:23:::0;;;112741:16:::1;::::0;::::1;:27:::0;;;112794:9;:27:::1;;112813:8;112794:27;;;112806:4;112794:27;112779:12;::::0;::::1;:42:::0;112832:22:::1;::::0;::::1;:39:::0;;;112882:37:::1;112900:9:::0;112779:7;112882:17:::1;:37::i;:::-;112936:10:::0;;112932:76:::1;;112948:60;:25;::::0;::::1;112974:10;112994:4;113001:6:::0;112948:25:::1;:60::i;:::-;113051:10;113039;113026:71;;;113063:9;113074:13;113089:7;113026:71;;;;;;;;:::i;:::-;;;;;;;;113117:12;::::0;::::1;::::0;:26:::1;::::0;113134:8;113117:16:::1;:26::i;:::-;113110:33;;;;;90753:20:::0;92056:11;:18;;;;;;;;91872:210;91528:189;91662:11;;;;;;;91654:55;;;;;;;19070:2:1;91654:55:0;;;19052:21:1;19109:2;19089:18;;;19082:30;19148:33;19128:18;;;19121:61;19199:18;;91654:55:0;18868:355:1;91654:55:0;91528:189::o;135190:1460::-;135887:16;;;;135393:31;;135879:39;;135875:91;;-1:-1:-1;135927:39:0;135920:46;;135875:91;135983:16;;:30;;135979:84;;-1:-1:-1;136022:41:0;136015:48;;135979:84;136080:7;:15;;;136076:67;;;-1:-1:-1;136104:39:0;136097:46;;136076:67;136160:16;;;;:30;;136156:242;;136255:16;:14;:16::i;:::-;136229:7;:22;;;:42;;:169;;136358:40;136229:169;;;136295:39;136229:169;136205:193;;;;136156:242;136431:12;:10;:12::i;:::-;:21;;;136453:10;136465:9;136476:45;136496:13;136511:9;136476:19;:45::i;:::-;136431:91;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:211;;136602:40;136431:211;;;-1:-1:-1;136542:40:0;;135190:1460;-1:-1:-1;;;;;135190:1460:0:o;130427:271::-;130593:7;130641:9;130652:10;130664:9;130675:13;130630:59;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;130620:70;;;;;;130613:77;;130427:271;;;;;;;:::o;134772:258::-;134914:24;134930:7;134914:15;:24::i;:::-;134891:19;;;;:8;:19;;;;;;:47;134869:153;;;;;;;19931:2:1;134869:153:0;;;19913:21:1;19970:2;19950:18;;;19943:30;20009:34;19989:18;;;19982:62;20080:26;20060:18;;;20053:54;20124:19;;134869:153:0;19729:420:1;134869:153:0;134772:258;;:::o;135038:144::-;135150:24;135166:7;135150:15;:24::i;:::-;135128:19;;;;:8;:19;;;;;;:46;;;;-1:-1:-1;135038:144:0:o;17543:98::-;17601:7;17628:5;17632:1;17628;:5;:::i;11726:205::-;11854:68;;20688:42:1;20757:15;;;11854:68:0;;;20739:34:1;20809:15;;20789:18;;;20782:43;20841:18;;;20834:34;;;11827:96:0;;11847:5;;11877:27;;20651:18:1;;11854:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11827:19;:96::i;:::-;11726:205;;;;:::o;137042:157::-;137135:6;;:55;;;;;137167:22;137135:55;;;708:25:1;137086:14:0;;137135:6;;;:31;;681:18:1;;137135:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;134402:169::-;134544:12;;;;134476:7;;134544:19;;134561:1;134544:16;:19::i;12830:283::-;12950:39;;;;;12974:4;12950:39;;;21370:34:1;12950:15:0;21440::1;;;21420:18;;;21413:43;12927:20:0;;12992:5;;12950:15;;;;;21282:18:1;;12950:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;:::-;13035:69;;21671:42:1;21659:55;;13035:69:0;;;21641:74:1;21731:18;;;21724:34;;;12927:70:0;;-1:-1:-1;13008:97:0;;13028:5;;13058:22;;21614:18:1;;13035:69:0;21467:297:1;136658:179:0;136772:6;;:56;;;;;136804:23;136772:56;;;708:25:1;136703:24:0;;136772:6;;;:31;;681:18:1;;136772:56:0;562:177:1;137727:376:0;137826:12;138019:76;138055:13;138019:76;;;;;;;;;;;;;;;;;138085:9;138019:35;:76::i;137207:213::-;137342:6;;:69;;;;;137374:36;137342:69;;;708:25:1;137265:28:0;;137342:6;;;:31;;681:18:1;;137342:69:0;562:177:1;136845:189:0;136956:6;;:69;;;;;136988:36;136956:69;;;708:25:1;136903:16:0;;136956:6;;;:31;;681:18:1;;136956:69:0;562:177:1;131289:3105:0;131484:14;131500:20;131533:17;131553:55;131560:9;131571:10;131583:9;131594:13;131553:6;:55::i;:::-;131533:75;;131619:40;131640:9;131651:7;131619:20;:40::i;:::-;131726:29;131771:550;;;;;;;;131808:7;:16;;;131771:550;;;;;;131853:7;:16;;;131771:550;;;;;;131898:7;:16;;;131771:550;;;;;;131942:4;131771:550;;;;;;131992:7;:21;;;131771:550;;;;132047:7;:21;;;131771:550;;;;132103:7;:22;;;131771:550;;;;132152:7;:14;;;131771:550;;;;132195:7;:16;;;131771:550;;;;132236:7;:12;;;131771:550;;;;132283:7;:22;;;131771:550;;;131726:595;;132334:37;132374:67;132384:9;132395:10;132407:9;132418:13;132433:7;132374:9;:67::i;:::-;132334:107;-1:-1:-1;132465:39:0;132456:5;:48;;;;;;;;:::i;:::-;;132452:1564;;;132644:21;;;;132680:28;;;:44;;;132787:14;;;;132765:16;;;;132748:12;;;;132644:21;;-1:-1:-1;132748:54:0;;:34;;:16;:34::i;:54::-;132847:16;;132817;;;;132739:63;;-1:-1:-1;132817:55:0;;:29;;;132739:63;132817:29;:55::i;:::-;132452:1564;;;132903:40;132894:5;:49;;;;;;;;:::i;:::-;;132890:1126;;;133093:12;:10;:12::i;:::-;:21;;;133115:10;133127:9;133138:45;133158:13;133173:9;133138:19;:45::i;:::-;133093:91;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;133199:28;;;:44;;;133312:21;;;;133793:14;;;;133753:16;;;;133077:107;;-1:-1:-1;133280:53:0;;;;;133678:144;;133793:14;133678:92;;;133695:52;133712:34;133199:14;133712:18;:34::i;:::-;133695:12;;;;;:16;:52::i;:::-;133678:12;;;;;:16;:70::i;:144::-;133669:153;;133837:91;133867:14;:52;;133903:16;;133867:52;;;133884:7;:16;;;133867:52;133837:16;;;;:29;;;133921:6;133837:29;:91::i;:::-;132945:995;132890:1126;;;133961:43;;;;;22159:2:1;133961:43:0;;;22141:21:1;22198:2;22178:18;;;22171:30;22237:34;22217:18;;;22210:62;22308:3;22288:18;;;22281:31;22329:19;;133961:43:0;21957:397:1;132890:1126:0;134028:44;134046:9;134057:14;134028:17;:44::i;:::-;134106:10;134095:9;134088:71;;;134118:9;134129:13;134144:14;134088:71;;;;;;;;:::i;:::-;;;;;;;;134198:29;;;4014:20;4053:8;134194:193;;134265:97;;;;;:43;;;;;;:97;;134309:10;;134321:9;;134332:13;;134347:14;;134265:97;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134244:143;;131522:2872;;;131289:3105;;;;;;;;:::o;130824:136::-;130895:7;130943;130932:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;130922:30;;;;;;130915:37;;130824:136;;;:::o;13975:761::-;14399:23;14425:69;14453:4;14425:69;;;;;;;;;;;;;;;;;14433:5;14425:27;;;;:69;;;;;:::i;:::-;14509:17;;14399:95;;-1:-1:-1;14509:21:0;14505:224;;14651:10;14640:30;;;;;;;;;;;;:::i;:::-;14632:85;;;;;;;22813:2:1;14632:85:0;;;22795:21:1;22852:2;22832:18;;;22825:30;22891:34;22871:18;;;22864:62;22962:12;22942:18;;;22935:40;22992:19;;14632:85:0;22611:406:1;14632:85:0;14045:691;13975:761;;:::o;18680:98::-;18738:7;18765:5;18769:1;18765;:5;:::i;97377:344::-;97533:12;97558:19;97580:42;97596:20;97618:3;97580:15;:42::i;:::-;97558:64;;97657:20;97679:6;97687:25;97706:5;97687:18;:25::i;:::-;97640:73;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;97633:80;;;97377:344;;;;;;:::o;11541:177::-;11651:58;;21671:42:1;21659:55;;11651:58:0;;;21641:74:1;21731:18;;;21724:34;;;11624:86:0;;11644:5;;11674:23;;21614:18:1;;11651:58:0;21467:297:1;17924:98:0;17982:7;18009:5;18013:1;18009;:5;:::i;6565:195::-;6668:12;6700:52;6722:6;6730:4;6736:1;6739:12;6700:21;:52::i;99153:301::-;99283:27;;99254:12;;99283:31;99279:168;;99360:3;99338:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;99331:38;;;;99279:168;99426:3;99409:26;;;;;;;;:::i;95311:221::-;95373:12;95435:47;95455:26;;;;;;95435:19;:47::i;:::-;95491:31;95519:1;95511:10;;95491:31;;;:19;:31::i;:::-;95418:106;;;;;;;;25455:19:1;;;25516:66;25504:79;25499:2;25490:12;;25483:101;25609:2;25600:12;;25300:318;95418:106:0;;;;;;;;;;;;;95398:126;;95311:221;;;:::o;7617:530::-;7744:12;7802:5;7777:21;:30;;7769:81;;;;;;;25825:2:1;7769:81:0;;;25807:21:1;25864:2;25844:18;;;25837:30;25903:34;25883:18;;;25876:62;25974:8;25954:18;;;25947:36;26000:19;;7769:81:0;25623:402:1;7769:81:0;4014:20;;7861:60;;;;;;;26232:2:1;7861:60:0;;;26214:21:1;26271:2;26251:18;;;26244:30;26310:31;26290:18;;;26283:59;26359:18;;7861:60:0;26030:353:1;7861:60:0;7995:12;8009:23;8036:6;:11;;8056:5;8064:4;8036:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7994:75;;;;8087:52;8105:7;8114:10;8126:12;8087:17;:52::i;93022:1327::-;93090:7;93135:9;93155:7;93147:16;;93135:28;;93218:1;93222:66;93218:70;93214:74;;93313:1;93317:5;93313:9;93308:1;:15;93327:66;93307:86;93303:90;;93418:1;93422:5;93418:9;93413:1;:15;93432:66;93412:86;93408:90;;93523:1;93527:5;93523:9;93518:1;:15;93537:66;93517:86;93513:90;;93628:1;93632:4;93628:8;93623:1;:14;93641:66;93622:85;93618:89;;93732:1;93736:4;93732:8;93727:1;:14;93745:66;93726:85;93722:89;;93855:9;93942:1;93868;93872:66;93868:70;93867:76;;;;;:::i;:::-;;94045:1;93975:66;93971:70;;93970:76;94148:1;94078:66;94074:70;;94073:76;94178:5;94173:11;94188:4;94172:20;94168:24;;;94195:66;94168:93;;;-1:-1:-1;;;93022:1327:0:o;10157:742::-;10272:12;10301:7;10297:595;;;-1:-1:-1;10332:10:0;10325:17;;10297:595;10446:17;;:21;10442:439;;10709:10;10703:17;10770:15;10757:10;10753:2;10749:19;10742:44;10442:439;10852:12;10845:20;;;;;;;;;;;:::i;377:180:1:-;436:6;489:2;477:9;468:7;464:23;460:32;457:52;;;505:1;502;495:12;457:52;-1:-1:-1;528:23:1;;377:180;-1:-1:-1;377:180:1:o;744:154::-;830:42;823:5;819:54;812:5;809:65;799:93;;888:1;885;878:12;799:93;744:154;:::o;903:134::-;971:20;;1000:31;971:20;1000:31;:::i;:::-;903:134;;;:::o;1042:163::-;1109:20;;1169:10;1158:22;;1148:33;;1138:61;;1195:1;1192;1185:12;1210:184;1262:77;1259:1;1252:88;1359:4;1356:1;1349:15;1383:4;1380:1;1373:15;1399:250;1466:2;1460:9;1508:6;1496:19;;1545:18;1530:34;;1566:22;;;1527:62;1524:88;;;1592:18;;:::i;:::-;1628:2;1621:22;1399:250;:::o;1654:777::-;1696:5;1749:3;1742:4;1734:6;1730:17;1726:27;1716:55;;1767:1;1764;1757:12;1716:55;1803:6;1790:20;1829:18;1866:2;1862;1859:10;1856:36;;;1872:18;;:::i;:::-;2006:2;2000:9;2068:4;2060:13;;1911:66;2056:22;;;2080:2;2052:31;2048:40;2036:53;;;2104:18;;;2124:22;;;2101:46;2098:72;;;2150:18;;:::i;:::-;2190:10;2186:2;2179:22;2225:2;2217:6;2210:18;2271:3;2264:4;2259:2;2251:6;2247:15;2243:26;2240:35;2237:55;;;2288:1;2285;2278:12;2237:55;2352:2;2345:4;2337:6;2333:17;2326:4;2318:6;2314:17;2301:54;2399:1;2392:4;2387:2;2379:6;2375:15;2371:26;2364:37;2419:6;2410:15;;;;;;1654:777;;;;:::o;2436:118::-;2522:5;2515:13;2508:21;2501:5;2498:32;2488:60;;2544:1;2541;2534:12;2559:128;2624:20;;2653:28;2624:20;2653:28;:::i;2692:959::-;2746:5;2794:6;2782:9;2777:3;2773:19;2769:32;2766:52;;;2814:1;2811;2804:12;2766:52;2836:17;;:::i;:::-;2827:26;;2876:29;2895:9;2876:29;:::i;:::-;2869:5;2862:44;2938:38;2972:2;2961:9;2957:18;2938:38;:::i;:::-;2933:2;2926:5;2922:14;2915:62;3009:38;3043:2;3032:9;3028:18;3009:38;:::i;:::-;3004:2;2997:5;2993:14;2986:62;3080:35;3111:2;3100:9;3096:18;3080:35;:::i;:::-;3075:2;3068:5;3064:14;3057:59;3177:3;3166:9;3162:19;3149:33;3143:3;3136:5;3132:15;3125:58;3244:3;3233:9;3229:19;3216:33;3210:3;3203:5;3199:15;3192:58;3311:3;3300:9;3296:19;3283:33;3277:3;3270:5;3266:15;3259:58;3378:3;3367:9;3363:19;3350:33;3344:3;3337:5;3333:15;3326:58;3403:3;3466:2;3455:9;3451:18;3438:32;3433:2;3426:5;3422:14;3415:56;;3490:3;3553:2;3542:9;3538:18;3525:32;3520:2;3513:5;3509:14;3502:56;;3577:3;3640:2;3629:9;3625:18;3612:32;3607:2;3600:5;3596:14;3589:56;;2692:959;;;;:::o;3656:712::-;3784:6;3792;3800;3808;3816;3869:3;3857:9;3848:7;3844:23;3840:33;3837:53;;;3886:1;3883;3876:12;3837:53;3925:9;3912:23;3944:31;3969:5;3944:31;:::i;:::-;3994:5;-1:-1:-1;4046:2:1;4031:18;;4018:32;;-1:-1:-1;4069:37:1;4102:2;4087:18;;4069:37;:::i;:::-;4059:47;;4157:2;4146:9;4142:18;4129:32;4184:18;4176:6;4173:30;4170:50;;;4216:1;4213;4206:12;4170:50;4239:49;4280:7;4271:6;4260:9;4256:22;4239:49;:::i;:::-;4229:59;;;4307:55;4354:7;4348:3;4337:9;4333:19;4307:55;:::i;:::-;4297:65;;3656:712;;;;;;;;:::o;4373:184::-;4425:77;4422:1;4415:88;4522:4;4519:1;4512:15;4546:4;4543:1;4536:15;4562:395;4704:2;4689:18;;4737:1;4726:13;;4716:201;;4773:77;4770:1;4763:88;4874:4;4871:1;4864:15;4902:4;4899:1;4892:15;4716:201;4926:25;;;4562:395;:::o;4962:780::-;5098:6;5106;5114;5122;5130;5138;5191:3;5179:9;5170:7;5166:23;5162:33;5159:53;;;5208:1;5205;5198:12;5159:53;5247:9;5234:23;5266:31;5291:5;5266:31;:::i;:::-;5316:5;-1:-1:-1;5368:2:1;5353:18;;5340:32;;-1:-1:-1;5391:37:1;5424:2;5409:18;;5391:37;:::i;:::-;5381:47;;5479:2;5468:9;5464:18;5451:32;5506:18;5498:6;5495:30;5492:50;;;5538:1;5535;5528:12;5492:50;5561:49;5602:7;5593:6;5582:9;5578:22;5561:49;:::i;:::-;5551:59;;;5629:55;5676:7;5670:3;5659:9;5655:19;5629:55;:::i;:::-;5619:65;;5731:3;5720:9;5716:19;5703:33;5693:43;;4962:780;;;;;;;;:::o;5747:854::-;5884:6;5892;5900;5908;5916;5924;5977:3;5965:9;5956:7;5952:23;5948:33;5945:53;;;5994:1;5991;5984:12;5945:53;6030:9;6017:23;6007:33;;6059:37;6092:2;6081:9;6077:18;6059:37;:::i;:::-;6049:47;;6147:2;6136:9;6132:18;6119:32;6174:18;6166:6;6163:30;6160:50;;;6206:1;6203;6196:12;6160:50;6229:49;6270:7;6261:6;6250:9;6246:22;6229:49;:::i;:::-;6219:59;;;6297:54;6343:7;6338:2;6327:9;6323:18;6297:54;:::i;:::-;6287:64;;6401:3;6390:9;6386:19;6373:33;6415:31;6440:5;6415:31;:::i;:::-;6465:5;-1:-1:-1;6522:3:1;6507:19;;6494:33;6536;6494;6536;:::i;:::-;6588:7;6578:17;;;5747:854;;;;;;;;:::o;7261:1026::-;7412:6;7420;7428;7436;7444;7452;7460;7468;7476;7529:3;7517:9;7508:7;7504:23;7500:33;7497:53;;;7546:1;7543;7536:12;7497:53;7582:9;7569:23;7559:33;;7611:37;7644:2;7633:9;7629:18;7611:37;:::i;:::-;7601:47;;7699:2;7688:9;7684:18;7671:32;7726:18;7718:6;7715:30;7712:50;;;7758:1;7755;7748:12;7712:50;7781:49;7822:7;7813:6;7802:9;7798:22;7781:49;:::i;:::-;7771:59;;;7880:2;7869:9;7865:18;7852:32;7893:31;7918:5;7893:31;:::i;:::-;7943:5;-1:-1:-1;7995:3:1;7980:19;;7967:33;;-1:-1:-1;8047:3:1;8032:19;;8019:33;;-1:-1:-1;8099:3:1;8084:19;;8071:33;;-1:-1:-1;8156:3:1;8141:19;;8128:33;8170;8128;8170;:::i;:::-;8222:7;8212:17;;;8276:3;8265:9;8261:19;8248:33;8238:43;;7261:1026;;;;;;;;;;;:::o;8292:455::-;8369:6;8377;8430:2;8418:9;8409:7;8405:23;8401:32;8398:52;;;8446:1;8443;8436:12;8398:52;8486:9;8473:23;8519:18;8511:6;8508:30;8505:50;;;8551:1;8548;8541:12;8505:50;8574:49;8615:7;8606:6;8595:9;8591:22;8574:49;:::i;:::-;8564:59;;;8673:2;8662:9;8658:18;8645:32;8686:31;8711:5;8686:31;:::i;:::-;8736:5;8726:15;;;8292:455;;;;;:::o;8752:258::-;8824:1;8834:113;8848:6;8845:1;8842:13;8834:113;;;8924:11;;;8918:18;8905:11;;;8898:39;8870:2;8863:10;8834:113;;;8965:6;8962:1;8959:13;8956:48;;;-1:-1:-1;;9000:1:1;8982:16;;8975:27;8752:258::o;9015:316::-;9056:3;9094:5;9088:12;9121:6;9116:3;9109:19;9137:63;9193:6;9186:4;9181:3;9177:14;9170:4;9163:5;9159:16;9137:63;:::i;:::-;9245:2;9233:15;9250:66;9229:88;9220:98;;;;9320:4;9216:109;;9015:316;-1:-1:-1;;9015:316:1:o;9336:217::-;9483:2;9472:9;9465:21;9446:4;9503:44;9543:2;9532:9;9528:18;9520:6;9503:44;:::i;9558:922::-;9703:6;9711;9719;9727;9735;9743;9751;9804:3;9792:9;9783:7;9779:23;9775:33;9772:53;;;9821:1;9818;9811:12;9772:53;9860:9;9847:23;9879:31;9904:5;9879:31;:::i;:::-;9929:5;-1:-1:-1;9981:2:1;9966:18;;9953:32;;-1:-1:-1;10004:37:1;10037:2;10022:18;;10004:37;:::i;:::-;9994:47;;10092:2;10081:9;10077:18;10064:32;10119:18;10111:6;10108:30;10105:50;;;10151:1;10148;10141:12;10105:50;10174:49;10215:7;10206:6;10195:9;10191:22;10174:49;:::i;:::-;10164:59;;;10242:55;10289:7;10283:3;10272:9;10268:19;10242:55;:::i;:::-;10232:65;;10349:3;10338:9;10334:19;10321:33;10363;10388:7;10363:33;:::i;:::-;10415:7;10405:17;;;10469:3;10458:9;10454:19;10441:33;10431:43;;9558:922;;;;;;;;;;:::o;10991:816::-;11125:6;11133;11141;11149;11157;11165;11173;11226:3;11214:9;11205:7;11201:23;11197:33;11194:53;;;11243:1;11240;11233:12;11194:53;11279:9;11266:23;11256:33;;11308:37;11341:2;11330:9;11326:18;11308:37;:::i;:::-;11298:47;;11396:2;11385:9;11381:18;11368:32;11423:18;11415:6;11412:30;11409:50;;;11455:1;11452;11445:12;11409:50;11478:49;11519:7;11510:6;11499:9;11495:22;11478:49;:::i;:::-;11468:59;;;11577:2;11566:9;11562:18;11549:32;11590:31;11615:5;11590:31;:::i;:::-;10991:816;;;;-1:-1:-1;10991:816:1;;11692:3;11677:19;;11664:33;;11744:3;11729:19;;11716:33;;-1:-1:-1;11796:3:1;11781:19;;;11768:33;;-1:-1:-1;10991:816:1;-1:-1:-1;;10991:816:1:o;11812:184::-;11882:6;11935:2;11923:9;11914:7;11910:23;11906:32;11903:52;;;11951:1;11948;11941:12;11903:52;-1:-1:-1;11974:16:1;;11812:184;-1:-1:-1;11812:184:1:o;13064:375::-;13266:6;13255:9;13248:25;13321:10;13313:6;13309:23;13304:2;13293:9;13289:18;13282:51;13369:2;13364;13353:9;13349:18;13342:30;13229:4;13389:44;13429:2;13418:9;13414:18;13406:6;13389:44;:::i;13444:891::-;13524:12;;91:42;80:54;68:67;;13588:4;13581:5;13577:16;13571:23;13603:48;13645:4;13640:3;13636:14;13622:12;91:42;80:54;68:67;;14:127;13603:48;;13699:4;13692:5;13688:16;13682:23;13714:50;13758:4;13753:3;13749:14;13733;91:42;80:54;68:67;;14:127;13714:50;;13812:4;13805:5;13801:16;13795:23;13827:47;13868:4;13863:3;13859:14;13843;7043:13;7036:21;7024:34;;6973:91;13827:47;-1:-1:-1;13923:4:1;13912:16;;;13906:23;13890:14;;;13883:47;13979:4;13968:16;;;13962:23;13946:14;;;13939:47;14035:4;14024:16;;;14018:23;14002:14;;;13995:47;14091:4;14080:16;;;14074:23;14058:14;;;14051:47;14117:6;14159:14;;;14153:21;14139:12;;;14132:43;14194:6;14236:14;;;14230:21;14216:12;;;14209:43;14271:6;14313:14;;;14307:21;14293:12;;14286:43;13444:891::o;14340:465::-;14554:4;14583:3;14625:10;14617:6;14613:23;14602:9;14595:42;14673:2;14668;14657:9;14653:18;14646:30;14693:44;14733:2;14722:9;14718:18;14710:6;14693:44;:::i;:::-;14685:52;;;14746:53;14795:2;14784:9;14780:18;14772:6;14746:53;:::i;14810:536::-;15052:4;15081:3;15111:6;15100:9;15093:25;15166:10;15158:6;15154:23;15149:2;15138:9;15134:18;15127:51;15214:2;15209;15198:9;15194:18;15187:30;15234:44;15274:2;15263:9;15259:18;15251:6;15234:44;:::i;:::-;15226:52;;;15287:53;15336:2;15325:9;15321:18;15313:6;15287:53;:::i;16066:245::-;16133:6;16186:2;16174:9;16165:7;16161:23;16157:32;16154:52;;;16202:1;16199;16192:12;16154:52;16234:9;16228:16;16253:28;16275:5;16253:28;:::i;17716:442::-;17811:6;17864:2;17852:9;17843:7;17839:23;17835:32;17832:52;;;17880:1;17877;17870:12;17832:52;17913:2;17907:9;17955:2;17947:6;17943:15;18024:6;18012:10;18009:22;17988:18;17976:10;17973:34;17970:62;17967:88;;;18035:18;;:::i;:::-;18071:2;18064:22;18110:16;;18095:32;;-1:-1:-1;18102:6:1;17716:442;-1:-1:-1;17716:442:1:o;19228:496::-;19469:42;19461:6;19457:55;19446:9;19439:74;19549:6;19544:2;19533:9;19529:18;19522:34;19604:10;19596:6;19592:23;19587:2;19576:9;19572:18;19565:51;19652:3;19647:2;19636:9;19632:18;19625:31;19420:4;19673:45;19713:3;19702:9;19698:19;19690:6;19673:45;:::i;20154:184::-;20206:77;20203:1;20196:88;20303:4;20300:1;20293:15;20327:4;20324:1;20317:15;20343:128;20383:3;20414:1;20410:6;20407:1;20404:13;20401:39;;;20420:18;;:::i;:::-;-1:-1:-1;20456:9:1;;20343:128::o;20879:251::-;20949:6;21002:2;20990:9;20981:7;20977:23;20973:32;20970:52;;;21018:1;21015;21008:12;20970:52;21050:9;21044:16;21069:31;21094:5;21069:31;:::i;22359:247::-;22543:3;22528:19;;22556:44;22532:9;22582:6;22556:44;:::i;23022:184::-;23074:77;23071:1;23064:88;23171:4;23168:1;23161:15;23195:4;23192:1;23185:15;23211:274;23251:1;23277;23267:189;;23312:77;23309:1;23302:88;23413:4;23410:1;23403:15;23441:4;23438:1;23431:15;23267:189;-1:-1:-1;23470:9:1;;23211:274::o;23490:658::-;23711:3;23749:6;23743:13;23765:53;23811:6;23806:3;23799:4;23791:6;23787:17;23765:53;:::i;:::-;23881:13;;23840:16;;;;23903:57;23881:13;23840:16;23937:4;23925:17;;23903:57;:::i;:::-;24027:13;;23982:20;;;24049:57;24027:13;23982:20;24083:4;24071:17;;24049:57;:::i;:::-;24122:20;;23490:658;-1:-1:-1;;;;;23490:658:1:o;24153:125::-;24193:4;24221:1;24218;24215:8;24212:34;;;24226:18;;:::i;:::-;-1:-1:-1;24263:9:1;;24153:125::o;24283:570::-;24644:3;24639;24632:16;24614:3;24677:6;24671:13;24693:61;24747:6;24743:1;24738:3;24734:11;24727:4;24719:6;24715:17;24693:61;:::i;:::-;24817:3;24813:1;24773:16;;;;24805:10;;;24798:23;-1:-1:-1;24845:1:1;24837:10;;24283:570;-1:-1:-1;24283:570:1:o;24858:437::-;25088:3;25126:6;25120:13;25142:53;25188:6;25183:3;25176:4;25168:6;25164:17;25142:53;:::i;:::-;25256:3;25217:16;;25242:18;;;-1:-1:-1;25287:1:1;25276:13;;24858:437;-1:-1:-1;24858:437:1:o;26388:274::-;26517:3;26555:6;26549:13;26571:53;26617:6;26612:3;26605:4;26597:6;26593:17;26571:53;:::i;:::-;26640:16;;;;;26388:274;-1:-1:-1;;26388:274:1:o

Swarm Source

ipfs://646dae79d706d017d6d602cb7c3449713d448e652942dc33ff3c39919c23b0d2

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.