Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multi Chain
Multichain Addresses
0 address found via
Latest 10 from a total of 10 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Settle | 14669152 | 407 days 4 mins ago | IN | 0 ETH | 0.01433929 | ||||
Settle | 14669151 | 407 days 5 mins ago | IN | 0 ETH | 0.01186438 | ||||
Settle | 14669150 | 407 days 5 mins ago | IN | 0 ETH | 0.01211912 | ||||
Settle | 13626786 | 569 days 9 hrs ago | IN | 0 ETH | 0.02529701 | ||||
Settle | 13626785 | 569 days 9 hrs ago | IN | 0 ETH | 0.03074359 | ||||
Settle | 13626784 | 569 days 9 hrs ago | IN | 0 ETH | 0.02517865 | ||||
Settle | 13626780 | 569 days 9 hrs ago | IN | 0 ETH | 0.0276642 | ||||
Settle | 13540979 | 582 days 21 hrs ago | IN | 0 ETH | 0.03734106 | ||||
Settle | 13540979 | 582 days 21 hrs ago | IN | 0 ETH | 0.03734025 | ||||
0x60806040 | 13454342 | 596 days 11 hrs ago | IN | Create: SkinnyOptimisticOracle | 0 ETH | 0.20852819 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
SkinnyOptimisticOracle
Compiler Version
v0.8.9+commit.e5eed63a
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ 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.