Contract 0x22A9AaAC9c3184f68C7B7C95b1300C4B1D2fB95C 5
Contract Overview
Balance:
0 xDAI
xDAI Value:
$0.00
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
View more zero value Internal Transactions in Advanced View mode
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
OptimisticOracleV3
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @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() { _transferOwnership(_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 { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @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' 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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) 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; 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 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) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) 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 generally not needed starting with Solidity 0.8, since 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. 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; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol) 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; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; import "../interfaces/AddressWhitelistInterface.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./Lockable.sol"; /** * @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++; } } } }
// SPDX-License-Identifier: AGPL-3.0-only 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(currentAncillaryData, 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, ":"); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/math/SignedSafeMath.sol"; /** * @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 uint, 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); } } }
// SPDX-License-Identifier: AGPL-3.0-only 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; } // These functions are intended to be used by child contracts to temporarily disable and re-enable the guard. // Intended use: // _startReentrantGuardDisabled(); // ... // _endReentrantGuardDisabled(); // // IMPORTANT: these should NEVER be used in a method that isn't inside a nonReentrant block. Otherwise, it's // possible to permanently lock your contract. function _startReentrantGuardDisabled() internal { _notEntered = true; } function _endReentrantGuardDisabled() internal { _notEntered = false; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; // This contract is taken from Uniswap's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol) // and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value // set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits. /// @title MultiCaller /// @notice Enables calling multiple methods in a single call to the contract contract MultiCaller { function multicall(bytes[] calldata data) external returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } }
// SPDX-License-Identifier: AGPL-3.0-only 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); }
// SPDX-License-Identifier: AGPL-3.0-only 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 OptimisticOracleV2 = "OptimisticOracleV2"; bytes32 public constant OptimisticOracleV3 = "OptimisticOracleV3"; bytes32 public constant Bridge = "Bridge"; bytes32 public constant GenericHandler = "GenericHandler"; bytes32 public constant SkinnyOptimisticOracle = "SkinnyOptimisticOracle"; bytes32 public constant ChildMessenger = "ChildMessenger"; bytes32 public constant OracleHub = "OracleHub"; bytes32 public constant OracleSpoke = "OracleSpoke"; } /** * @title Commonly re-used values for contracts associated with the OptimisticOracle. */ library OptimisticOracleConstraints { // Any price request submitted to the OptimisticOracle must contain ancillary data no larger than this value. // This value must be <= the Voting contract's `ancillaryBytesLimit` constant value otherwise it is possible // that a price can be requested to the OptimisticOracle successfully, but cannot be resolved by the DVM which // refuses to accept a price request made with ancillary data length over a certain size. uint256 public constant ancillaryBytesLimit = 8192; }
// SPDX-License-Identifier: AGPL-3.0-only 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); }
// SPDX-License-Identifier: AGPL-3.0-only 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); }
// SPDX-License-Identifier: AGPL-3.0-only 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); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../../common/implementation/FixedPoint.sol"; /** * @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); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.16; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/OptimisticOracleV3CallbackRecipientInterface.sol"; import "../interfaces/OptimisticOracleV3Interface.sol"; import "../interfaces/EscalationManagerInterface.sol"; import "../../data-verification-mechanism/implementation/Constants.sol"; import "../../data-verification-mechanism/interfaces/FinderInterface.sol"; import "../../data-verification-mechanism/interfaces/IdentifierWhitelistInterface.sol"; import "../../data-verification-mechanism/interfaces/OracleAncillaryInterface.sol"; import "../../data-verification-mechanism/interfaces/StoreInterface.sol"; import "../../common/implementation/AddressWhitelist.sol"; import "../../common/implementation/AncillaryData.sol"; import "../../common/implementation/Lockable.sol"; import "../../common/implementation/MultiCaller.sol"; /** * @title Optimistic Oracle V3. * @notice The OOv3 is used to assert truths about the world which are verified using an optimistic escalation game. * @dev Core idea: an asserter makes a statement about a truth, calling "assertTruth". If this statement is not * challenged, it is taken as the state of the world. If challenged, it is arbitrated using the UMA DVM, or if * configured, an escalation manager. Escalation managers enable integrations to define their own security properties and * tradeoffs, enabling the notion of "sovereign security". */ contract OptimisticOracleV3 is OptimisticOracleV3Interface, Lockable, Ownable, MultiCaller { using SafeERC20 for IERC20; FinderInterface public immutable finder; // Finder used to discover other UMA ecosystem contracts. // Cached UMA parameters. address public cachedOracle; mapping(address => WhitelistedCurrency) public cachedCurrencies; mapping(bytes32 => bool) public cachedIdentifiers; mapping(bytes32 => Assertion) public assertions; // All assertions made by the Optimistic Oracle V3. uint256 public burnedBondPercentage; // Percentage of the bond that is paid to the UMA store if the assertion is disputed. bytes32 public constant defaultIdentifier = "ASSERT_TRUTH"; int256 public constant numericalTrue = 1e18; // Numerical representation of true. IERC20 public defaultCurrency; uint64 public defaultLiveness; /** * @notice Construct the OptimisticOracleV3 contract. * @param _finder keeps track of all contracts within the UMA system based on their interfaceName. * @param _defaultCurrency the default currency to bond asserters in assertTruthWithDefaults. * @param _defaultLiveness the default liveness for assertions in assertTruthWithDefaults. */ constructor( FinderInterface _finder, IERC20 _defaultCurrency, uint64 _defaultLiveness ) { finder = _finder; setAdminProperties(_defaultCurrency, _defaultLiveness, 0.5e18); } /** * @notice Sets the default currency, liveness, and burned bond percentage. * @dev Only callable by the contract owner (UMA governor). * @param _defaultCurrency the default currency to bond asserters in assertTruthWithDefaults. * @param _defaultLiveness the default liveness for assertions in assertTruthWithDefaults. * @param _burnedBondPercentage the percentage of the bond that is sent as fee to UMA Store contract on disputes. */ function setAdminProperties( IERC20 _defaultCurrency, uint64 _defaultLiveness, uint256 _burnedBondPercentage ) public onlyOwner { require(_burnedBondPercentage <= 1e18, "Burned bond percentage > 100"); require(_burnedBondPercentage > 0, "Burned bond percentage is 0"); burnedBondPercentage = _burnedBondPercentage; defaultCurrency = _defaultCurrency; defaultLiveness = _defaultLiveness; syncUmaParams(defaultIdentifier, address(_defaultCurrency)); emit AdminPropertiesSet(_defaultCurrency, _defaultLiveness, _burnedBondPercentage); } /** * @notice Asserts a truth about the world, using the default currency and liveness. No callback recipient or * escalation manager is enabled. The caller is expected to provide a bond of finalFee/burnedBondPercentage * (with burnedBondPercentage set to 50%, the bond is 2x final fee) of the default currency. * @dev The caller must approve this contract to spend at least the result of getMinimumBond(defaultCurrency). * @param claim the truth claim being asserted. This is an assertion about the world, and is verified by disputers. * @param asserter account that receives bonds back at settlement. This could be msg.sender or * any other account that the caller wants to receive the bond at settlement time. * @return assertionId unique identifier for this assertion. */ function assertTruthWithDefaults(bytes calldata claim, address asserter) external returns (bytes32) { // Note: re-entrancy guard is done in the inner call. return assertTruth( claim, asserter, // asserter address(0), // callbackRecipient address(0), // escalationManager defaultLiveness, defaultCurrency, getMinimumBond(address(defaultCurrency)), defaultIdentifier, bytes32(0) ); } /** * @notice Asserts a truth about the world, using a fully custom configuration. * @dev The caller must approve this contract to spend at least bond amount of currency. * @param claim the truth claim being asserted. This is an assertion about the world, and is verified by disputers. * @param asserter account that receives bonds back at settlement. This could be msg.sender or * any other account that the caller wants to receive the bond at settlement time. * @param callbackRecipient if configured, this address will receive a function call assertionResolvedCallback and * assertionDisputedCallback at resolution or dispute respectively. Enables dynamic responses to these events. The * recipient _must_ implement these callbacks and not revert or the assertion resolution will be blocked. * @param escalationManager if configured, this address will control escalation properties of the assertion. This * means a) choosing to arbitrate via the UMA DVM, b) choosing to discard assertions on dispute, or choosing to * validate disputes. Combining these, the asserter can define their own security properties for the assertion. * escalationManager also _must_ implement the same callbacks as callbackRecipient. * @param liveness time to wait before the assertion can be resolved. Assertion can be disputed in this time. * @param currency bond currency pulled from the caller and held in escrow until the assertion is resolved. * @param bond amount of currency to pull from the caller and hold in escrow until the assertion is resolved. This * must be >= getMinimumBond(address(currency)). * @param identifier UMA DVM identifier to use for price requests in the event of a dispute. Must be pre-approved. * @param domainId optional domain that can be used to relate this assertion to others in the escalationManager and * can be used by the configured escalationManager to define custom behavior for groups of assertions. This is * typically used for "escalation games" by changing bonds or other assertion properties based on the other * assertions that have come before. If not needed this value should be 0 to save gas. * @return assertionId unique identifier for this assertion. */ function assertTruth( bytes memory claim, address asserter, address callbackRecipient, address escalationManager, uint64 liveness, IERC20 currency, uint256 bond, bytes32 identifier, bytes32 domainId ) public nonReentrant returns (bytes32 assertionId) { uint64 time = uint64(getCurrentTime()); assertionId = _getId(claim, bond, time, liveness, currency, callbackRecipient, escalationManager, identifier); require(asserter != address(0), "Asserter cant be 0"); require(assertions[assertionId].asserter == address(0), "Assertion already exists"); require(_validateAndCacheIdentifier(identifier), "Unsupported identifier"); require(_validateAndCacheCurrency(address(currency)), "Unsupported currency"); require(bond >= getMinimumBond(address(currency)), "Bond amount too low"); assertions[assertionId] = Assertion({ escalationManagerSettings: EscalationManagerSettings({ arbitrateViaEscalationManager: false, // Default behavior: use the DVM as an oracle. discardOracle: false, // Default behavior: respect the Oracle result. validateDisputers: false, // Default behavior: disputer will not be validated. escalationManager: escalationManager, assertingCaller: msg.sender }), asserter: asserter, disputer: address(0), callbackRecipient: callbackRecipient, currency: currency, domainId: domainId, identifier: identifier, bond: bond, settled: false, settlementResolution: false, assertionTime: time, expirationTime: time + liveness }); { EscalationManagerInterface.AssertionPolicy memory assertionPolicy = _getAssertionPolicy(assertionId); require(!assertionPolicy.blockAssertion, "Assertion not allowed"); // Check if the assertion is permitted. EscalationManagerSettings storage emSettings = assertions[assertionId].escalationManagerSettings; (emSettings.arbitrateViaEscalationManager, emSettings.discardOracle, emSettings.validateDisputers) = ( // Choose which oracle to arbitrate disputes via. If set to true then the escalation manager will // arbitrate disputes. Else, the DVM arbitrates disputes. This lets integrations "unplug" the DVM. assertionPolicy.arbitrateViaEscalationManager, // Choose whether to discard the Oracle result. If true then "throw away" the assertion. To get an // assertion to be true it must be re-asserted and not disputed. assertionPolicy.discardOracle, // Configures if the escalation manager should validate the disputer on assertions. This enables you // to construct setups such as whitelisted disputers. assertionPolicy.validateDisputers ); } currency.safeTransferFrom(msg.sender, address(this), bond); // Pull the bond from the caller. emit AssertionMade( assertionId, domainId, claim, asserter, callbackRecipient, escalationManager, msg.sender, time + liveness, currency, bond, identifier ); } /** * @notice Disputes an assertion. Depending on how the assertion was configured, this may either escalate to the UMA * DVM or the configured escalation manager for arbitration. * @dev The caller must approve this contract to spend at least bond amount of currency for the associated assertion. * @param assertionId unique identifier for the assertion to dispute. * @param disputer receives bonds back at settlement. */ function disputeAssertion(bytes32 assertionId, address disputer) external nonReentrant { require(disputer != address(0), "Disputer can't be 0"); Assertion storage assertion = assertions[assertionId]; require(assertion.asserter != address(0), "Assertion does not exist"); require(assertion.disputer == address(0), "Assertion already disputed"); require(assertion.expirationTime > getCurrentTime(), "Assertion is expired"); require(_isDisputeAllowed(assertionId), "Dispute not allowed"); assertion.disputer = disputer; assertion.currency.safeTransferFrom(msg.sender, address(this), assertion.bond); _oracleRequestPrice(assertionId, assertion.identifier, assertion.assertionTime); _callbackOnAssertionDispute(assertionId); // Send resolve callback if dispute resolution is discarded if (assertion.escalationManagerSettings.discardOracle) _callbackOnAssertionResolve(assertionId, false); emit AssertionDisputed(assertionId, msg.sender, disputer); } /** * @notice Resolves an assertion. If the assertion has not been disputed, the assertion is resolved as true and the * asserter receives the bond. If the assertion has been disputed, the assertion is resolved depending on the oracle * result. Based on the result, the asserter or disputer receives the bond. If the assertion was disputed then an * amount of the bond is sent to the UMA Store as an oracle fee based on the burnedBondPercentage. The remainder of * the bond is returned to the asserter or disputer. * @param assertionId unique identifier for the assertion to resolve. */ function settleAssertion(bytes32 assertionId) public nonReentrant { Assertion storage assertion = assertions[assertionId]; require(assertion.asserter != address(0), "Assertion does not exist"); // Revert if assertion does not exist. require(!assertion.settled, "Assertion already settled"); // Revert if assertion already settled. assertion.settled = true; if (assertion.disputer == address(0)) { // No dispute, settle with the asserter require(assertion.expirationTime <= getCurrentTime(), "Assertion not expired"); // Revert if not expired. assertion.settlementResolution = true; assertion.currency.safeTransfer(assertion.asserter, assertion.bond); _callbackOnAssertionResolve(assertionId, true); emit AssertionSettled(assertionId, assertion.asserter, false, true, msg.sender); } else { // Dispute, settle with the disputer. Reverts if price not resolved. int256 resolvedPrice = _oracleGetPrice(assertionId, assertion.identifier, assertion.assertionTime); // If set to discard settlement resolution then false. Else, use oracle value to find resolution. if (assertion.escalationManagerSettings.discardOracle) assertion.settlementResolution = false; else assertion.settlementResolution = resolvedPrice == numericalTrue; address bondRecipient = resolvedPrice == numericalTrue ? assertion.asserter : assertion.disputer; // Calculate oracle fee and the remaining amount of bonds to send to the correct party (asserter or disputer). uint256 oracleFee = (burnedBondPercentage * assertion.bond) / 1e18; uint256 bondRecipientAmount = assertion.bond * 2 - oracleFee; // Pay out the oracle fee and remaining bonds to the correct party. Note: the oracle fee is sent to the // Store contract, even if the escalation manager is used to arbitrate disputes. assertion.currency.safeTransfer(address(_getStore()), oracleFee); assertion.currency.safeTransfer(bondRecipient, bondRecipientAmount); if (!assertion.escalationManagerSettings.discardOracle) _callbackOnAssertionResolve(assertionId, assertion.settlementResolution); emit AssertionSettled(assertionId, bondRecipient, true, assertion.settlementResolution, msg.sender); } } /** * @notice Settles an assertion and returns the resolution. * @param assertionId unique identifier for the assertion to resolve and return the resolution for. * @return resolution of the assertion. */ function settleAndGetAssertionResult(bytes32 assertionId) external returns (bool) { // Note: re-entrancy guard is done in the inner settleAssertion call. if (!assertions[assertionId].settled) settleAssertion(assertionId); return getAssertionResult(assertionId); } /** * @notice Fetches information about a specific identifier & currency from the UMA contracts and stores a local copy * of the information within this contract. This is used to save gas when making assertions as we can avoid an * external call to the UMA contracts to fetch this. * @param identifier identifier to fetch information for and store locally. * @param currency currency to fetch information for and store locally. */ function syncUmaParams(bytes32 identifier, address currency) public { cachedOracle = finder.getImplementationAddress(OracleInterfaces.Oracle); cachedIdentifiers[identifier] = _getIdentifierWhitelist().isIdentifierSupported(identifier); cachedCurrencies[currency].isWhitelisted = _getCollateralWhitelist().isOnWhitelist(currency); cachedCurrencies[currency].finalFee = _getStore().computeFinalFee(currency).rawValue; } /** * @notice Fetches information about a specific assertion and returns it. * @param assertionId unique identifier for the assertion to fetch information for. * @return assertion information about the assertion. */ function getAssertion(bytes32 assertionId) external view returns (Assertion memory) { return assertions[assertionId]; } /** * @notice Fetches the resolution of a specific assertion and returns it. If the assertion has not been settled then * this will revert. If the assertion was disputed and configured to discard the oracle resolution return false. * @param assertionId unique identifier for the assertion to fetch the resolution for. * @return resolution of the assertion. */ function getAssertionResult(bytes32 assertionId) public view returns (bool) { Assertion memory assertion = assertions[assertionId]; // Return early if not using answer from resolved dispute. if (assertion.disputer != address(0) && assertion.escalationManagerSettings.discardOracle) return false; require(assertion.settled, "Assertion not settled"); // Revert if assertion not settled. return assertion.settlementResolution; } /** * @notice Returns the current block timestamp. * @dev Can be overridden to control contract time. * @return current block timestamp. */ function getCurrentTime() public view virtual returns (uint256) { return block.timestamp; } /** * @notice Appends information onto an assertionId to construct ancillary data used for dispute resolution. * @param assertionId unique identifier for the assertion to construct ancillary data for. * @return ancillaryData stamped assertion information. */ function stampAssertion(bytes32 assertionId) public view returns (bytes memory) { return _stampAssertion(assertionId); } /** * @notice Returns the minimum bond amount required to make an assertion. This is calculated as the final fee of the * currency divided by the burnedBondPercentage. If burn percentage is 50% then the min bond is 2x the final fee. * @param currency currency to calculate the minimum bond for. * @return minimum bond amount. */ function getMinimumBond(address currency) public view returns (uint256) { uint256 finalFee = cachedCurrencies[currency].finalFee; return (finalFee * 1e18) / burnedBondPercentage; } // Returns the unique identifier for this assertion. This identifier is used to identify the assertion. function _getId( bytes memory claim, uint256 bond, uint256 time, uint64 liveness, IERC20 currency, address callbackRecipient, address escalationManager, bytes32 identifier ) internal view returns (bytes32) { return keccak256( abi.encode( claim, bond, time, liveness, currency, callbackRecipient, escalationManager, identifier, msg.sender ) ); } // Returns ancillary data for the Oracle request containing assertionId and asserter. function _stampAssertion(bytes32 assertionId) internal view returns (bytes memory) { return AncillaryData.appendKeyValueAddress( AncillaryData.appendKeyValueBytes32("", "assertionId", assertionId), "ooAsserter", assertions[assertionId].asserter ); } // Returns the Address Whitelist contract to validate the currency. function _getCollateralWhitelist() internal view returns (AddressWhitelist) { return AddressWhitelist(finder.getImplementationAddress(OracleInterfaces.CollateralWhitelist)); } // Returns the Identifier Whitelist contract to validate the identifier. function _getIdentifierWhitelist() internal view returns (IdentifierWhitelistInterface) { return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist)); } // Returns the Store contract to fetch the final fee. function _getStore() internal view returns (StoreInterface) { return StoreInterface(finder.getImplementationAddress(OracleInterfaces.Store)); } // Returns the Oracle contract to use on dispute. This can be either UMA DVM or the escalation manager. function _getOracle(bytes32 assertionId) internal view returns (OracleAncillaryInterface) { if (assertions[assertionId].escalationManagerSettings.arbitrateViaEscalationManager) return OracleAncillaryInterface(_getEscalationManager(assertionId)); return OracleAncillaryInterface(cachedOracle); } // Requests resolving dispute from the Oracle (UMA DVM or escalation manager). function _oracleRequestPrice( bytes32 assertionId, bytes32 identifier, uint256 time ) internal { _getOracle(assertionId).requestPrice(identifier, time, _stampAssertion(assertionId)); } // Returns the resolved resolution from the Oracle (UMA DVM or escalation manager). function _oracleGetPrice( bytes32 assertionId, bytes32 identifier, uint256 time ) internal view returns (int256) { return _getOracle(assertionId).getPrice(identifier, time, _stampAssertion(assertionId)); } // Returns the escalation manager address for the assertion. function _getEscalationManager(bytes32 assertionId) internal view returns (address) { return assertions[assertionId].escalationManagerSettings.escalationManager; } // Returns the assertion policy parameters from the escalation manager. If no escalation manager is set then return // default values. function _getAssertionPolicy(bytes32 assertionId) internal view returns (EscalationManagerInterface.AssertionPolicy memory) { address em = _getEscalationManager(assertionId); if (em == address(0)) return EscalationManagerInterface.AssertionPolicy(false, false, false, false); return EscalationManagerInterface(em).getAssertionPolicy(assertionId); } // Returns whether the dispute is allowed by the escalation manager. If no escalation manager is set or the // escalation manager is not configured to validate disputers then return true. function _isDisputeAllowed(bytes32 assertionId) internal view returns (bool) { if (!assertions[assertionId].escalationManagerSettings.validateDisputers) return true; address em = assertions[assertionId].escalationManagerSettings.escalationManager; if (em == address(0)) return true; return EscalationManagerInterface(em).isDisputeAllowed(assertionId, msg.sender); } // Validates if the identifier is whitelisted by first checking the cache. If not whitelisted in the cache then // checks it from the identifier whitelist contract and caches result. function _validateAndCacheIdentifier(bytes32 identifier) internal returns (bool) { if (cachedIdentifiers[identifier]) return true; cachedIdentifiers[identifier] = _getIdentifierWhitelist().isIdentifierSupported(identifier); return cachedIdentifiers[identifier]; } // Validates if the currency is whitelisted by first checking the cache. If not whitelisted in the cache then // checks it from the collateral whitelist contract and caches whitelist status and final fee. function _validateAndCacheCurrency(address currency) internal returns (bool) { if (cachedCurrencies[currency].isWhitelisted) return true; cachedCurrencies[currency].isWhitelisted = _getCollateralWhitelist().isOnWhitelist(currency); cachedCurrencies[currency].finalFee = _getStore().computeFinalFee(currency).rawValue; return cachedCurrencies[currency].isWhitelisted; } // Sends assertion resolved callback to the callback recipient and escalation manager (if set). function _callbackOnAssertionResolve(bytes32 assertionId, bool assertedTruthfully) internal { address cr = assertions[assertionId].callbackRecipient; address em = _getEscalationManager(assertionId); if (cr != address(0)) OptimisticOracleV3CallbackRecipientInterface(cr).assertionResolvedCallback(assertionId, assertedTruthfully); if (em != address(0)) EscalationManagerInterface(em).assertionResolvedCallback(assertionId, assertedTruthfully); } // Sends assertion disputed callback to the callback recipient and escalation manager (if set). function _callbackOnAssertionDispute(bytes32 assertionId) internal { address cr = assertions[assertionId].callbackRecipient; address em = _getEscalationManager(assertionId); if (cr != address(0)) OptimisticOracleV3CallbackRecipientInterface(cr).assertionDisputedCallback(assertionId); if (em != address(0)) EscalationManagerInterface(em).assertionDisputedCallback(assertionId); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.16; import "./OptimisticOracleV3CallbackRecipientInterface.sol"; /** * @title Escalation Manager Interface * @notice Interface for contracts that manage the escalation policy for assertions. */ interface EscalationManagerInterface is OptimisticOracleV3CallbackRecipientInterface { // Assertion policy parameters as returned by the escalation manager. struct AssertionPolicy { bool blockAssertion; // If true, the the assertion should be blocked. bool arbitrateViaEscalationManager; // If true, the escalation manager will arbitrate the assertion. bool discardOracle; // If true, the Optimistic Oracle V3 should discard the oracle price. bool validateDisputers; // If true, the escalation manager will validate the disputers. } /** * @notice Returns the assertion policy for the given assertion. * @param assertionId the assertion identifier to get the assertion policy for. * @return the assertion policy for the given assertion identifier. */ function getAssertionPolicy(bytes32 assertionId) external view returns (AssertionPolicy memory); /** * @notice Callback function that is called by Optimistic Oracle V3 when an assertion is disputed. Used to validate * if the dispute should be allowed based on the escalation policy. * @param assertionId the assertionId to validate the dispute for. * @param disputeCaller the caller of the dispute function. * @return bool true if the dispute is allowed, false otherwise. */ function isDisputeAllowed(bytes32 assertionId, address disputeCaller) external view returns (bool); /** * @notice Implements price getting logic. This method is called by Optimistic Oracle V3 settling an assertion that * is configured to use the escalation manager as the oracle. The interface is constructed to mimic the UMA DVM. * @param identifier price identifier being requested. * @param time timestamp of the price being requested. * @param ancillaryData ancillary data of the price being requested. * @return price from the escalation manager to inform the resolution of the dispute. */ function getPrice( bytes32 identifier, uint256 time, bytes memory ancillaryData ) external returns (int256); /** * @notice Implements price requesting logic for the escalation manager. This function is called by the Optimistic * Oracle V3 on dispute and is constructed to mimic that of the UMA DVM interface. * @param identifier the identifier to fetch the price for. * @param time the time to fetch the price for. * @param ancillaryData ancillary data of the price being requested. */ function requestPrice( bytes32 identifier, uint256 time, bytes memory ancillaryData ) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.16; /** * @title Optimistic Oracle V3 Callback Recipient Interface * @notice Interface for contracts implementing callbacks to be received from the Optimistic Oracle V3. */ interface OptimisticOracleV3CallbackRecipientInterface { /** * @notice Callback function that is called by Optimistic Oracle V3 when an assertion is resolved. * @param assertionId The identifier of the assertion that was resolved. * @param assertedTruthfully Whether the assertion was resolved as truthful or not. */ function assertionResolvedCallback(bytes32 assertionId, bool assertedTruthfully) external; /** * @notice Callback function that is called by Optimistic Oracle V3 when an assertion is disputed. * @param assertionId The identifier of the assertion that was disputed. */ function assertionDisputedCallback(bytes32 assertionId) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.16; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title Optimistic Oracle V3 Interface that callers must use to assert truths about the world. */ interface OptimisticOracleV3Interface { // Struct grouping together the settings related to the escalation manager stored in the assertion. struct EscalationManagerSettings { bool arbitrateViaEscalationManager; // False if the DVM is used as an oracle (EscalationManager on True). bool discardOracle; // False if Oracle result is used for resolving assertion after dispute. bool validateDisputers; // True if the EM isDisputeAllowed should be checked on disputes. address assertingCaller; // Stores msg.sender when assertion was made. address escalationManager; // Address of the escalation manager (zero address if not configured). } // Struct for storing properties and lifecycle of an assertion. struct Assertion { EscalationManagerSettings escalationManagerSettings; // Settings related to the escalation manager. address asserter; // Address of the asserter. uint64 assertionTime; // Time of the assertion. bool settled; // True if the request is settled. IERC20 currency; // ERC20 token used to pay rewards and fees. uint64 expirationTime; // Unix timestamp marking threshold when the assertion can no longer be disputed. bool settlementResolution; // Resolution of the assertion (false till resolved). bytes32 domainId; // Optional domain that can be used to relate the assertion to others in the escalationManager. bytes32 identifier; // UMA DVM identifier to use for price requests in the event of a dispute. uint256 bond; // Amount of currency that the asserter has bonded. address callbackRecipient; // Address that receives the callback. address disputer; // Address of the disputer. } // Struct for storing cached currency whitelist. struct WhitelistedCurrency { bool isWhitelisted; // True if the currency is whitelisted. uint256 finalFee; // Final fee of the currency. } /** * @notice Returns the default identifier used by the Optimistic Oracle V3. * @return The default identifier. */ function defaultIdentifier() external view returns (bytes32); /** * @notice Fetches information about a specific assertion and returns it. * @param assertionId unique identifier for the assertion to fetch information for. * @return assertion information about the assertion. */ function getAssertion(bytes32 assertionId) external view returns (Assertion memory); /** * @notice Asserts a truth about the world, using the default currency and liveness. No callback recipient or * escalation manager is enabled. The caller is expected to provide a bond of finalFee/burnedBondPercentage * (with burnedBondPercentage set to 50%, the bond is 2x final fee) of the default currency. * @dev The caller must approve this contract to spend at least the result of getMinimumBond(defaultCurrency). * @param claim the truth claim being asserted. This is an assertion about the world, and is verified by disputers. * @param asserter receives bonds back at settlement. This could be msg.sender or * any other account that the caller wants to receive the bond at settlement time. * @return assertionId unique identifier for this assertion. */ function assertTruthWithDefaults(bytes memory claim, address asserter) external returns (bytes32); /** * @notice Asserts a truth about the world, using a fully custom configuration. * @dev The caller must approve this contract to spend at least bond amount of currency. * @param claim the truth claim being asserted. This is an assertion about the world, and is verified by disputers. * @param asserter receives bonds back at settlement. This could be msg.sender or * any other account that the caller wants to receive the bond at settlement time. * @param callbackRecipient if configured, this address will receive a function call assertionResolvedCallback and * assertionDisputedCallback at resolution or dispute respectively. Enables dynamic responses to these events. The * recipient _must_ implement these callbacks and not revert or the assertion resolution will be blocked. * @param escalationManager if configured, this address will control escalation properties of the assertion. This * means a) choosing to arbitrate via the UMA DVM, b) choosing to discard assertions on dispute, or choosing to * validate disputes. Combining these, the asserter can define their own security properties for the assertion. * escalationManager also _must_ implement the same callbacks as callbackRecipient. * @param liveness time to wait before the assertion can be resolved. Assertion can be disputed in this time. * @param currency bond currency pulled from the caller and held in escrow until the assertion is resolved. * @param bond amount of currency to pull from the caller and hold in escrow until the assertion is resolved. This * must be >= getMinimumBond(address(currency)). * @param identifier UMA DVM identifier to use for price requests in the event of a dispute. Must be pre-approved. * @param domainId optional domain that can be used to relate this assertion to others in the escalationManager and * can be used by the configured escalationManager to define custom behavior for groups of assertions. This is * typically used for "escalation games" by changing bonds or other assertion properties based on the other * assertions that have come before. If not needed this value should be 0 to save gas. * @return assertionId unique identifier for this assertion. */ function assertTruth( bytes memory claim, address asserter, address callbackRecipient, address escalationManager, uint64 liveness, IERC20 currency, uint256 bond, bytes32 identifier, bytes32 domainId ) external returns (bytes32); /** * @notice Fetches information about a specific identifier & currency from the UMA contracts and stores a local copy * of the information within this contract. This is used to save gas when making assertions as we can avoid an * external call to the UMA contracts to fetch this. * @param identifier identifier to fetch information for and store locally. * @param currency currency to fetch information for and store locally. */ function syncUmaParams(bytes32 identifier, address currency) external; /** * @notice Resolves an assertion. If the assertion has not been disputed, the assertion is resolved as true and the * asserter receives the bond. If the assertion has been disputed, the assertion is resolved depending on the oracle * result. Based on the result, the asserter or disputer receives the bond. If the assertion was disputed then an * amount of the bond is sent to the UMA Store as an oracle fee based on the burnedBondPercentage. The remainder of * the bond is returned to the asserter or disputer. * @param assertionId unique identifier for the assertion to resolve. */ function settleAssertion(bytes32 assertionId) external; /** * @notice Settles an assertion and returns the resolution. * @param assertionId unique identifier for the assertion to resolve and return the resolution for. * @return resolution of the assertion. */ function settleAndGetAssertionResult(bytes32 assertionId) external returns (bool); /** * @notice Fetches the resolution of a specific assertion and returns it. If the assertion has not been settled then * this will revert. If the assertion was disputed and configured to discard the oracle resolution return false. * @param assertionId unique identifier for the assertion to fetch the resolution for. * @return resolution of the assertion. */ function getAssertionResult(bytes32 assertionId) external view returns (bool); /** * @notice Returns the minimum bond amount required to make an assertion. This is calculated as the final fee of the * currency divided by the burnedBondPercentage. If burn percentage is 50% then the min bond is 2x the final fee. * @param currency currency to calculate the minimum bond for. * @return minimum bond amount. */ function getMinimumBond(address currency) external view returns (uint256); event AssertionMade( bytes32 indexed assertionId, bytes32 domainId, bytes claim, address indexed asserter, address callbackRecipient, address escalationManager, address caller, uint64 expirationTime, IERC20 currency, uint256 bond, bytes32 indexed identifier ); event AssertionDisputed(bytes32 indexed assertionId, address indexed caller, address indexed disputer); event AssertionSettled( bytes32 indexed assertionId, address indexed bondRecipient, bool disputed, bool settlementResolution, address settleCaller ); event AdminPropertiesSet(IERC20 defaultCurrency, uint64 defaultLiveness, uint256 burnedBondPercentage); }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"contract FinderInterface","name":"_finder","type":"address"},{"internalType":"contract IERC20","name":"_defaultCurrency","type":"address"},{"internalType":"uint64","name":"_defaultLiveness","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20","name":"defaultCurrency","type":"address"},{"indexed":false,"internalType":"uint64","name":"defaultLiveness","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"burnedBondPercentage","type":"uint256"}],"name":"AdminPropertiesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assertionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"}],"name":"AssertionDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assertionId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"domainId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"claim","type":"bytes"},{"indexed":true,"internalType":"address","name":"asserter","type":"address"},{"indexed":false,"internalType":"address","name":"callbackRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"escalationManager","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint64","name":"expirationTime","type":"uint64"},{"indexed":false,"internalType":"contract IERC20","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"bond","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"AssertionMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"assertionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"bondRecipient","type":"address"},{"indexed":false,"internalType":"bool","name":"disputed","type":"bool"},{"indexed":false,"internalType":"bool","name":"settlementResolution","type":"bool"},{"indexed":false,"internalType":"address","name":"settleCaller","type":"address"}],"name":"AssertionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes","name":"claim","type":"bytes"},{"internalType":"address","name":"asserter","type":"address"},{"internalType":"address","name":"callbackRecipient","type":"address"},{"internalType":"address","name":"escalationManager","type":"address"},{"internalType":"uint64","name":"liveness","type":"uint64"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"bytes32","name":"domainId","type":"bytes32"}],"name":"assertTruth","outputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"claim","type":"bytes"},{"internalType":"address","name":"asserter","type":"address"}],"name":"assertTruthWithDefaults","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"assertions","outputs":[{"components":[{"internalType":"bool","name":"arbitrateViaEscalationManager","type":"bool"},{"internalType":"bool","name":"discardOracle","type":"bool"},{"internalType":"bool","name":"validateDisputers","type":"bool"},{"internalType":"address","name":"assertingCaller","type":"address"},{"internalType":"address","name":"escalationManager","type":"address"}],"internalType":"struct OptimisticOracleV3Interface.EscalationManagerSettings","name":"escalationManagerSettings","type":"tuple"},{"internalType":"address","name":"asserter","type":"address"},{"internalType":"uint64","name":"assertionTime","type":"uint64"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"settlementResolution","type":"bool"},{"internalType":"bytes32","name":"domainId","type":"bytes32"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"address","name":"callbackRecipient","type":"address"},{"internalType":"address","name":"disputer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnedBondPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"cachedCurrencies","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cachedIdentifiers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cachedOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultCurrency","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultLiveness","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"},{"internalType":"address","name":"disputer","type":"address"}],"name":"disputeAssertion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finder","outputs":[{"internalType":"contract FinderInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"name":"getAssertion","outputs":[{"components":[{"components":[{"internalType":"bool","name":"arbitrateViaEscalationManager","type":"bool"},{"internalType":"bool","name":"discardOracle","type":"bool"},{"internalType":"bool","name":"validateDisputers","type":"bool"},{"internalType":"address","name":"assertingCaller","type":"address"},{"internalType":"address","name":"escalationManager","type":"address"}],"internalType":"struct OptimisticOracleV3Interface.EscalationManagerSettings","name":"escalationManagerSettings","type":"tuple"},{"internalType":"address","name":"asserter","type":"address"},{"internalType":"uint64","name":"assertionTime","type":"uint64"},{"internalType":"bool","name":"settled","type":"bool"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"settlementResolution","type":"bool"},{"internalType":"bytes32","name":"domainId","type":"bytes32"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"address","name":"callbackRecipient","type":"address"},{"internalType":"address","name":"disputer","type":"address"}],"internalType":"struct OptimisticOracleV3Interface.Assertion","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"name":"getAssertionResult","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"}],"name":"getMinimumBond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"numericalTrue","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_defaultCurrency","type":"address"},{"internalType":"uint64","name":"_defaultLiveness","type":"uint64"},{"internalType":"uint256","name":"_burnedBondPercentage","type":"uint256"}],"name":"setAdminProperties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"name":"settleAndGetAssertionResult","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"name":"settleAssertion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"assertionId","type":"bytes32"}],"name":"stampAssertion","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"address","name":"currency","type":"address"}],"name":"syncUmaParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162004ddd38038062004ddd833981016040819052620000349162000634565b6000805460ff19166001179055620000536200004d3390565b6200007e565b6001600160a01b0383166080526200007582826706f05b59d3b20000620000d7565b5050506200072f565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6000546001600160a01b036101009091041633146200013d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b670de0b6b3a7640000811115620001975760405162461bcd60e51b815260206004820152601c60248201527f4275726e656420626f6e642070657263656e74616765203e2031303000000000604482015260640162000134565b60008111620001e95760405162461bcd60e51b815260206004820152601b60248201527f4275726e656420626f6e642070657263656e7461676520697320300000000000604482015260640162000134565b6005819055600680546001600160401b038416600160a01b026001600160e01b03199091166001600160a01b03861617179055620002376b082a6a68aa4a8bea8a4aaa8960a31b846200028e565b604080516001600160a01b03851681526001600160401b03841660208201529081018290527fd0f09246d369018534c67fec6a6c3259c6f962ef82c5521c337ae0ccc104e4bd9060600160405180910390a1505050565b6080516040516302abf57960e61b8152654f7261636c6560d01b60048201526001600160a01b039091169063aafd5e4090602401602060405180830381865afa158015620002e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000306919062000693565b600180546001600160a01b0319166001600160a01b039290921691909117905562000330620004f9565b6001600160a01b03166390978d1b836040518263ffffffff1660e01b81526004016200035e91815260200190565b602060405180830381865afa1580156200037c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a29190620006ba565b6000838152600360205260409020805460ff1916911515919091179055620003c96200058f565b604051631d1d5b3960e11b81526001600160a01b0383811660048301529190911690633a3ab67290602401602060405180830381865afa15801562000412573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004389190620006ba565b6001600160a01b0382166000908152600260205260409020805460ff191691151591909117905562000469620005e1565b604051635b97aadd60e01b81526001600160a01b0383811660048301529190911690635b97aadd90602401602060405180830381865afa158015620004b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004d89190620006de565b516001600160a01b0390911660009081526002602052604090206001015550565b6080516040516302abf57960e61b81527f4964656e74696669657257686974656c6973740000000000000000000000000060048201526000916001600160a01b03169063aafd5e40906024015b602060405180830381865afa15801562000564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200058a919062000693565b905090565b6080516040516302abf57960e61b81527f436f6c6c61746572616c57686974656c6973740000000000000000000000000060048201526000916001600160a01b03169063aafd5e409060240162000546565b6080516040516302abf57960e61b81526453746f726560d81b60048201526000916001600160a01b03169063aafd5e409060240162000546565b6001600160a01b03811681146200063157600080fd5b50565b6000806000606084860312156200064a57600080fd5b835162000657816200061b565b60208501519093506200066a816200061b565b60408501519092506001600160401b03811681146200068857600080fd5b809150509250925092565b600060208284031215620006a657600080fd5b8151620006b3816200061b565b9392505050565b600060208284031215620006cd57600080fd5b81518015158114620006b357600080fd5b600060208284031215620006f157600080fd5b604051602081016001600160401b03811182821017156200072257634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b60805161467662000767600039600081816105a601528181611e72015281816129c40152818161323801526132cd01526146766000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80638ea2f2ab116100ee578063b9a3c84c11610097578063da03b36e11610071578063da03b36e1461071b578063e39dfd7f1461072a578063f2fde38b1461073d578063fe4e19831461075057600080fd5b8063b9a3c84c146105a1578063d509b017146105c8578063d60715b5146105ef57600080fd5b8063a8655785116100c8578063a86557851461054e578063ac9650d814610561578063afedba4f1461058157600080fd5b80638ea2f2ab14610508578063a6a22b431461051b578063a7af2d0f1461052e57600080fd5b8063530dd3921161015b578063715018a611610135578063715018a6146102df57806382762520146102e757806388302884146102fa5780638da5cb5b146104e557600080fd5b8063530dd392146102555780636457c97914610288578063707621571461029b57600080fd5b806336b13af41161018c57806336b13af41461021a5780634124beef1461022d5780634360af3d1461024257600080fd5b806308e7c3e6146101b357806320402e1d146101cf57806329cb924d14610214575b600080fd5b6101bc60055481565b6040519081526020015b60405180910390f35b6006546101ef9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c6565b426101bc565b6101bc610228366004613a49565b610795565b61024061023b366004613acc565b61084c565b005b6101bc610250366004613ae5565b610e41565b610278610263366004613acc565b60036020526000908152604090205460ff1681565b60405190151581526020016101c6565b6101bc610296366004613bde565b610e89565b6102c86102a9366004613ae5565b6002602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016101c6565b6102406116ef565b6102406102f5366004613ccf565b611782565b6104d8610308366004613acc565b6040805161022081018252600061018082018181526101a083018290526101c083018290526101e083018290526102008301829052825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915250600090815260046020818152604092839020835161022081018552815460ff80821615156101808401908152610100808404831615156101a0860152620100008404831615156101c086015273ffffffffffffffffffffffffffffffffffffffff630100000090940484166101e08601526001860154841661020086015290845260028501548084169685019690965267ffffffffffffffff740100000000000000000000000000000000000000008088048216998601999099527c010000000000000000000000000000000000000000000000000000000096879004831615156060860152600386015480851660808701529889041660a085015294909604909516151560c08201529281015460e08401526005810154918301919091526006810154610120830152600781015483166101408301526008015490911661016082015290565b6040516101c69190613d0d565b600054610100900473ffffffffffffffffffffffffffffffffffffffff166101ef565b610278610516366004613acc565b6119de565b610240610529366004613e29565b611a2f565b6001546101ef9073ffffffffffffffffffffffffffffffffffffffff1681565b61024061055c366004613e29565b611e24565b61057461056f366004613e59565b6121a9565b6040516101c69190613f3c565b61059461058f366004613acc565b61231b565b6040516101c69190613fbc565b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6101bc7f4153534552545f5452555448000000000000000000000000000000000000000081565b6107036105fd366004613acc565b600460208181526000928352604092839020835160a081018552815460ff8082161515835261010082048116151594830194909452620100008104841615159582019590955273ffffffffffffffffffffffffffffffffffffffff630100000090950485166060820152600182015485166080820152600282015460038301549483015460058401546006850154600786015460089096015494988481169867ffffffffffffffff7401000000000000000000000000000000000000000080880482169a7c01000000000000000000000000000000000000000000000000000000009889900481169a8486169a928504909316989093049092169594939290811691168c565b6040516101c69c9b9a99989796959493929190613fcf565b6101bc670de0b6b3a764000081565b610278610738366004613acc565b612326565b61024061074b366004613ae5565b6124fe565b60065461077c9074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101c6565b600061084284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060065488945090925082915067ffffffffffffffff740100000000000000000000000000000000000000008204169073ffffffffffffffffffffffffffffffffffffffff1661081a81610e41565b7f4153534552545f545255544800000000000000000000000000000000000000006000610e89565b90505b9392505050565b610854612631565b610881600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000818152600460205260409020600281015473ffffffffffffffffffffffffffffffffffffffff16610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20646f6573206e6f74206578697374000000000000000060448201526064015b60405180910390fd5b60028101547c0100000000000000000000000000000000000000000000000000000000900460ff16156109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f417373657274696f6e20616c726561647920736574746c656400000000000000604482015260640161090c565b6002810180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000179055600881015473ffffffffffffffffffffffffffffffffffffffff16610b865742600382015474010000000000000000000000000000000000000000900467ffffffffffffffff161115610a9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420657870697265640000000000000000000000604482015260640161090c565b6003810180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81167c01000000000000000000000000000000000000000000000000000000001790915560028201546006830154610b159273ffffffffffffffffffffffffffffffffffffffff90811692169061269d565b610b20826001612776565b60028101546040805160008152600160208201523381830152905173ffffffffffffffffffffffffffffffffffffffff9092169184917ff4fa324b13daeb4e1aae736c2553632ae0fb16fb31f2d4da8ac99fd056313a13919081900360600190a3610e0d565b60058101546002820154600091610bc19185919074010000000000000000000000000000000000000000900467ffffffffffffffff166128e3565b8254909150610100900460ff1615610c02576003820180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff169055610c58565b6003820180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16670de0b6b3a764000083147c0100000000000000000000000000000000000000000000000000000000021790555b6000670de0b6b3a76400008214610c8957600883015473ffffffffffffffffffffffffffffffffffffffff16610ca5565b600283015473ffffffffffffffffffffffffffffffffffffffff165b90506000670de0b6b3a76400008460060154600554610cc491906140da565b610cce9190614146565b905060008185600601546002610ce491906140da565b610cee9190614181565b9050610d1d610cfb612973565b600387015473ffffffffffffffffffffffffffffffffffffffff16908461269d565b6003850154610d439073ffffffffffffffffffffffffffffffffffffffff16848361269d565b8454610100900460ff16610d84576003850154610d849087907c0100000000000000000000000000000000000000000000000000000000900460ff16612776565b600385015460408051600181527c010000000000000000000000000000000000000000000000000000000090920460ff1615156020830152339082015273ffffffffffffffffffffffffffffffffffffffff84169087907ff4fa324b13daeb4e1aae736c2553632ae0fb16fb31f2d4da8ac99fd056313a139060600160405180910390a3505050505b50610e3e600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812060010154600554610e7f82670de0b6b3a76400006140da565b6108459190614146565b6000610e93612631565b610ec0600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b42610edb8b8667ffffffffffffffff84168a8a8e8e8b612a4a565b915073ffffffffffffffffffffffffffffffffffffffff8a16610f5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f41737365727465722063616e7420626520300000000000000000000000000000604482015260640161090c565b60008281526004602052604090206002015473ffffffffffffffffffffffffffffffffffffffff1615610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20616c7265616479206578697374730000000000000000604482015260640161090c565b610ff284612a91565b611058576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e737570706f72746564206964656e74696669657200000000000000000000604482015260640161090c565b61106186612b75565b6110c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e737570706f727465642063757272656e6379000000000000000000000000604482015260640161090c565b6110d086610e41565b851015611139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f426f6e6420616d6f756e7420746f6f206c6f7700000000000000000000000000604482015260640161090c565b6040805161022081018252600061018082018181526101a083018290526101c08301829052336101e084015273ffffffffffffffffffffffffffffffffffffffff8c81166102008501529083528d8116602084015267ffffffffffffffff8516938301939093526060820152908716608082015260a081016111bb8984614194565b67ffffffffffffffff1681526020016000151581526020018481526020018581526020018681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152506004600084815260200190815260200160002060008201518160000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548160ff02191690831515021790555060608201518160000160036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505060208201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550606082015181600201601c6101000a81548160ff02191690831515021790555060808201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160030160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060c082015181600301601c6101000a81548160ff02191690831515021790555060e08201518160040155610100820151816005015561012082015181600601556101408201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101608201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050600061151283612d68565b80519091501561157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420616c6c6f7765640000000000000000000000604482015260640161090c565b600083815260046020908152604091829020908301519183015160609093015181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1662010000911515919091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010093151593909302929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690151517905561164873ffffffffffffffffffffffffffffffffffffffff8716333088612e70565b838a73ffffffffffffffffffffffffffffffffffffffff16837fdb1513f0abeb57a364db56aa3eb52015cca5268f00fd67bc73aaf22bccab02b7868f8e8e338f8a6116939190614194565b8f8f6040516116a99897969594939291906141b5565b60405180910390a4506116e2600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b9998505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314611776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b6117806000612ece565b565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314611809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b670de0b6b3a764000081111561187b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4275726e656420626f6e642070657263656e74616765203e2031303000000000604482015260640161090c565b600081116118e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4275726e656420626f6e642070657263656e7461676520697320300000000000604482015260640161090c565b60058190556006805467ffffffffffffffff841674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8616171790556119797f4153534552545f5452555448000000000000000000000000000000000000000084611e24565b6040805173ffffffffffffffffffffffffffffffffffffffff8516815267ffffffffffffffff841660208201529081018290527fd0f09246d369018534c67fec6a6c3259c6f962ef82c5521c337ae0ccc104e4bd9060600160405180910390a1505050565b6000818152600460205260408120600201547c0100000000000000000000000000000000000000000000000000000000900460ff16611a2057611a208261084c565b611a2982612326565b92915050565b611a37612631565b611a64600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8116611ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f44697370757465722063616e2774206265203000000000000000000000000000604482015260640161090c565b6000828152600460205260409020600281015473ffffffffffffffffffffffffffffffffffffffff16611b70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20646f6573206e6f742065786973740000000000000000604482015260640161090c565b600881015473ffffffffffffffffffffffffffffffffffffffff1615611bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f417373657274696f6e20616c7265616479206469737075746564000000000000604482015260640161090c565b42600382015474010000000000000000000000000000000000000000900467ffffffffffffffff1611611c81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f417373657274696f6e2069732065787069726564000000000000000000000000604482015260640161090c565b611c8a83612f4b565b611cf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f44697370757465206e6f7420616c6c6f77656400000000000000000000000000604482015260640161090c565b6008810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8481169190911790915560068201546003830154611d5092169033903090612e70565b60058101546002820154611d8791859174010000000000000000000000000000000000000000900467ffffffffffffffff1661303a565b611d90836130be565b8054610100900460ff1615611daa57611daa836000612776565b60405173ffffffffffffffffffffffffffffffffffffffff831690339085907f60133788b013c89f2a3756dbc47e3484997b87bd7e0af98a7d70232032c1ce2b90600090a450611e20600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b5050565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4f7261636c65000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401602060405180830381865afa158015611ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef29190614225565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055611f3f6131e7565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b836040518263ffffffff1660e01b8152600401611f7991815260200190565b602060405180830381865afa158015611f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fba9190614252565b600083815260036020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ffd61327c565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301529190911690633a3ab67290602401602060405180830381865afa15801561206b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208f9190614252565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556120e9612973565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301529190911690635b97aadd90602401602060405180830381865afa158015612157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217b919061426d565b5173ffffffffffffffffffffffffffffffffffffffff90911660009081526002602052604090206001015550565b60608167ffffffffffffffff8111156121c4576121c4613b02565b6040519080825280602002602001820160405280156121f757816020015b60608152602001906001900390816121e25790505b50905060005b82811015612314576000803086868581811061221b5761221b6142af565b905060200281019061222d91906142de565b60405161223b92919061434a565b600060405180830381855af49150503d8060008114612276576040519150601f19603f3d011682016040523d82523d6000602084013e61227b565b606091505b5091509150816122e15760448151101561229457600080fd5b600481019050808060200190518101906122ae919061435a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090c9190613fbc565b808484815181106122f4576122f46142af565b60200260200101819052505050808061230c906143d1565b9150506121fd565b5092915050565b6060611a2982613311565b6000818152600460208181526040808420815161022081018352815460ff80821615156101808401908152610100808404831615156101a0860152620100008404831615156101c086015273ffffffffffffffffffffffffffffffffffffffff630100000090940484166101e08601526001860154841661020086015290845260028501548084169785019790975267ffffffffffffffff740100000000000000000000000000000000000000008089048216978601979097527c010000000000000000000000000000000000000000000000000000000097889004831615156060860152600386015480851660808701529687041660a085015295909404909316151560c08201529381015460e08501526005810154928401929092526006820154610120840152600782015481166101408401526008909101541661016082018190521580159061247b57508051602001515b156124895750600092915050565b80606001516124f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420736574746c65640000000000000000000000604482015260640161090c565b60c0015192915050565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314612585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b73ffffffffffffffffffffffffffffffffffffffff8116612628576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161090c565b610e3e81612ece565b60005460ff16611780576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161090c565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127719084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526133c9565b505050565b6000828152600460205260409020600781015460019091015473ffffffffffffffffffffffffffffffffffffffff91821691168115612838576040517ff1b156b200000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff83169063f1b156b290604401600060405180830381600087803b15801561281f57600080fd5b505af1158015612833573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff8116156128dd576040517ff1b156b200000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff82169063f1b156b290604401600060405180830381600087803b1580156128c457600080fd5b505af11580156128d8573d6000803e3d6000fd5b505050505b50505050565b60006128ee846134d5565b73ffffffffffffffffffffffffffffffffffffffff1663719c6d56848461291488613311565b6040518463ffffffff1660e01b815260040161293293929190614409565b602060405180830381865afa15801561294f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108429190614428565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f53746f726500000000000000000000000000000000000000000000000000000060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063aafd5e40906024015b602060405180830381865afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190614225565b905090565b6000888888888888888833604051602001612a6d99989796959493929190614441565b60405160208183030381529060405280519060200120905098975050505050505050565b60008181526003602052604081205460ff1615612ab057506001919050565b612ab86131e7565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b836040518263ffffffff1660e01b8152600401612af291815260200190565b602060405180830381865afa158015612b0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b339190614252565b60009283526003602052604090922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592831790555060ff1690565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604081205460ff1615612bab57506001919050565b612bb361327c565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529190911690633a3ab67290602401602060405180830381865afa158015612c21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c459190614252565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055612c9f612973565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529190911690635b97aadd90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d31919061426d565b5173ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090206001810192909255505460ff1690565b60408051608081018252600080825260208083018290528284018290526060830182905284825260049052919091206001015473ffffffffffffffffffffffffffffffffffffffff1680612de1575050604080516080810182526000808252602082018190529181018290526060810191909152919050565b6040517fa6b011a70000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff82169063a6b011a790602401608060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084591906144b7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526128dd9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016126ef565b6000805473ffffffffffffffffffffffffffffffffffffffff8381166101008181027fffffffffffffffffffffff0000000000000000000000000000000000000000ff851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b60008181526004602052604081205462010000900460ff16612f6f57506001919050565b60008281526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff1680612fa55750600192915050565b6040517f6b915d910000000000000000000000000000000000000000000000000000000081526004810184905233602482015273ffffffffffffffffffffffffffffffffffffffff821690636b915d9190604401602060405180830381865afa158015613016573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190614252565b613043836134d5565b73ffffffffffffffffffffffffffffffffffffffff1663216666a4838361306987613311565b6040518463ffffffff1660e01b815260040161308793929190614409565b600060405180830381600087803b1580156130a157600080fd5b505af11580156130b5573d6000803e3d6000fd5b50505050505050565b6000818152600460205260409020600781015460019091015473ffffffffffffffffffffffffffffffffffffffff91821691168115613178576040517fd448a4ec0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff83169063d448a4ec90602401600060405180830381600087803b15801561315f57600080fd5b505af1158015613173573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff811615612771576040517fd448a4ec0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff82169063d448a4ec90602401613087565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4964656e74696669657257686974656c6973740000000000000000000000000060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612a04565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f436f6c6c61746572616c57686974656c6973740000000000000000000000000060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612a04565b6060611a29613365604051806020016040528060008152506040518060400160405280600b81526020017f617373657274696f6e496400000000000000000000000000000000000000000081525085613537565b604080518082018252600a81527f6f6f41737365727465720000000000000000000000000000000000000000000060208083019190915260008781526004909152919091206002015473ffffffffffffffffffffffffffffffffffffffff1661357d565b600061342b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166135989092919063ffffffff16565b80519091501561277157808060200190518101906134499190614252565b612771576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161090c565b60008181526004602052604081205460ff16156135195760008281526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff16611a29565b505060015473ffffffffffffffffffffffffffffffffffffffff1690565b6060600061354585856135a7565b90508481613552856135e9565b60405160200161356493929190614534565b6040516020818303038152906040529150509392505050565b6060600061358b85856135a7565b905084816135528561362a565b606061084284846000856136a2565b8151606090156135d857816040516020016135c29190614577565b6040516020818303038152906040529050611a29565b816040516020016135c291906145e3565b60606135f8608083901c613822565b61360183613822565b6040805160208101939093528201526060015b6040516020818303038152906040529050919050565b606061364b6fffffffffffffffffffffffffffffffff602084901c16613822565b6136668360601b6bffffffffffffffffffffffff1916613822565b6040516020016136149291909182527fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b606082471015613734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161090c565b843b61379c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161090c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516137c59190614624565b60006040518083038185875af1925050503d8060008114613802576040519150601f19603f3d011682016040523d82523d6000602084013e613807565b606091505b50915091506138178282866139c4565b979650505050505050565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f0808080808080808080808080808080808080808080808080808080808080808168161394657613946614117565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b606083156139d3575081610845565b8251156139e35782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090c9190613fbc565b73ffffffffffffffffffffffffffffffffffffffff81168114610e3e57600080fd5b8035613a4481613a17565b919050565b600080600060408486031215613a5e57600080fd5b833567ffffffffffffffff80821115613a7657600080fd5b818601915086601f830112613a8a57600080fd5b813581811115613a9957600080fd5b876020828501011115613aab57600080fd5b60209283019550935050840135613ac181613a17565b809150509250925092565b600060208284031215613ade57600080fd5b5035919050565b600060208284031215613af757600080fd5b813561084581613a17565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613b7857613b78613b02565b604052919050565b600067ffffffffffffffff821115613b9a57613b9a613b02565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b803567ffffffffffffffff81168114613a4457600080fd5b60008060008060008060008060006101208a8c031215613bfd57600080fd5b893567ffffffffffffffff811115613c1457600080fd5b8a01601f81018c13613c2557600080fd5b8035613c38613c3382613b80565b613b31565b8181528d6020838501011115613c4d57600080fd5b81602084016020830137600060208383010152809b50505050613c7260208b01613a39565b9750613c8060408b01613a39565b9650613c8e60608b01613a39565b9550613c9c60808b01613bc6565b9450613caa60a08b01613a39565b935060c08a0135925060e08a013591506101008a013590509295985092959850929598565b600080600060608486031215613ce457600080fd5b8335613cef81613a17565b9250613cfd60208501613bc6565b9150604084013590509250925092565b815180511515825260208082015115158184015260408083015115158185015260608084015173ffffffffffffffffffffffffffffffffffffffff9081168287015260809485015181168587015292860151831660a08601529085015167ffffffffffffffff1660c0850152840151151560e084015290830151908116610100808401919091526102008301919060a08501519150610120613dba8186018467ffffffffffffffff169052565b60c08601519250610140613dd18187018515159052565b60e08701516101608781019190915292870151610180870152908601516101a086015285015173ffffffffffffffffffffffffffffffffffffffff9081166101c0860152908501519081166101e08501529050612314565b60008060408385031215613e3c57600080fd5b823591506020830135613e4e81613a17565b809150509250929050565b60008060208385031215613e6c57600080fd5b823567ffffffffffffffff80821115613e8457600080fd5b818501915085601f830112613e9857600080fd5b813581811115613ea757600080fd5b8660208260051b8501011115613ebc57600080fd5b60209290920196919550909350505050565b60005b83811015613ee9578181015183820152602001613ed1565b50506000910152565b60008151808452613f0a816020860160208601613ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613faf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613f9d858351613ef2565b94509285019290850190600101613f63565b5092979650505050505050565b6020815260006108456020830184613ef2565b610200810161402b828f805115158252602081015115156020830152604081015115156040830152606081015173ffffffffffffffffffffffffffffffffffffffff808216606085015280608084015116608085015250505050565b73ffffffffffffffffffffffffffffffffffffffff9c8d1660a083015267ffffffffffffffff9b8c1660c083015299151560e0820152978b16610100890152959098166101208701529215156101408601526101608501919091526101808401526101a08301529284166101c0820152919092166101e090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614112576141126140ab565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261417c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611a2957611a296140ab565b67ffffffffffffffff818116838216019080821115612314576123146140ab565b60006101008a83528060208401526141cf8184018b613ef2565b73ffffffffffffffffffffffffffffffffffffffff998a16604085015297891660608401525050938616608085015267ffffffffffffffff9290921660a084015290931660c082015260e0019190915292915050565b60006020828403121561423757600080fd5b815161084581613a17565b80518015158114613a4457600080fd5b60006020828403121561426457600080fd5b61084582614242565b60006020828403121561427f57600080fd5b6040516020810181811067ffffffffffffffff821117156142a2576142a2613b02565b6040529151825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261431357600080fd5b83018035915067ffffffffffffffff82111561432e57600080fd5b60200191503681900382131561434357600080fd5b9250929050565b8183823760009101908152919050565b60006020828403121561436c57600080fd5b815167ffffffffffffffff81111561438357600080fd5b8201601f8101841361439457600080fd5b80516143a2613c3382613b80565b8181528560208385010111156143b757600080fd5b6143c8826020830160208601613ece565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614402576144026140ab565b5060010190565b8381528260208201526060604082015260006143c86060830184613ef2565b60006020828403121561443a57600080fd5b5051919050565b60006101208083526144558184018d613ef2565b602084019b909b525050604081019790975267ffffffffffffffff95909516606087015273ffffffffffffffffffffffffffffffffffffffff938416608087015291831660a0860152821660c085015260e08401521661010090910152919050565b6000608082840312156144c957600080fd5b6040516080810181811067ffffffffffffffff821117156144ec576144ec613b02565b6040526144f883614242565b815261450660208401614242565b602082015261451760408401614242565b604082015261452860608401614242565b60608201529392505050565b60008451614546818460208901613ece565b84519083019061455a818360208901613ece565b845191019061456d818360208801613ece565b0195945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000008152600082516145af816001850160208701613ece565b7f3a000000000000000000000000000000000000000000000000000000000000006001939091019283015250600201919050565b600082516145f5818460208701613ece565b7f3a00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008251614636818460208701613ece565b919091019291505056fea2646970667358221220f03b241d1c61d5494f1c346bd67521c49226c51304400e4ef1a5a988d347aaf364736f6c63430008100033000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd4000000000000000000000000ddafbb505ad214d7b80b1f830fccc89b60fb7a830000000000000000000000000000000000000000000000000000000000001c20
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c80638ea2f2ab116100ee578063b9a3c84c11610097578063da03b36e11610071578063da03b36e1461071b578063e39dfd7f1461072a578063f2fde38b1461073d578063fe4e19831461075057600080fd5b8063b9a3c84c146105a1578063d509b017146105c8578063d60715b5146105ef57600080fd5b8063a8655785116100c8578063a86557851461054e578063ac9650d814610561578063afedba4f1461058157600080fd5b80638ea2f2ab14610508578063a6a22b431461051b578063a7af2d0f1461052e57600080fd5b8063530dd3921161015b578063715018a611610135578063715018a6146102df57806382762520146102e757806388302884146102fa5780638da5cb5b146104e557600080fd5b8063530dd392146102555780636457c97914610288578063707621571461029b57600080fd5b806336b13af41161018c57806336b13af41461021a5780634124beef1461022d5780634360af3d1461024257600080fd5b806308e7c3e6146101b357806320402e1d146101cf57806329cb924d14610214575b600080fd5b6101bc60055481565b6040519081526020015b60405180910390f35b6006546101ef9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c6565b426101bc565b6101bc610228366004613a49565b610795565b61024061023b366004613acc565b61084c565b005b6101bc610250366004613ae5565b610e41565b610278610263366004613acc565b60036020526000908152604090205460ff1681565b60405190151581526020016101c6565b6101bc610296366004613bde565b610e89565b6102c86102a9366004613ae5565b6002602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016101c6565b6102406116ef565b6102406102f5366004613ccf565b611782565b6104d8610308366004613acc565b6040805161022081018252600061018082018181526101a083018290526101c083018290526101e083018290526102008301829052825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915250600090815260046020818152604092839020835161022081018552815460ff80821615156101808401908152610100808404831615156101a0860152620100008404831615156101c086015273ffffffffffffffffffffffffffffffffffffffff630100000090940484166101e08601526001860154841661020086015290845260028501548084169685019690965267ffffffffffffffff740100000000000000000000000000000000000000008088048216998601999099527c010000000000000000000000000000000000000000000000000000000096879004831615156060860152600386015480851660808701529889041660a085015294909604909516151560c08201529281015460e08401526005810154918301919091526006810154610120830152600781015483166101408301526008015490911661016082015290565b6040516101c69190613d0d565b600054610100900473ffffffffffffffffffffffffffffffffffffffff166101ef565b610278610516366004613acc565b6119de565b610240610529366004613e29565b611a2f565b6001546101ef9073ffffffffffffffffffffffffffffffffffffffff1681565b61024061055c366004613e29565b611e24565b61057461056f366004613e59565b6121a9565b6040516101c69190613f3c565b61059461058f366004613acc565b61231b565b6040516101c69190613fbc565b6101ef7f000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd481565b6101bc7f4153534552545f5452555448000000000000000000000000000000000000000081565b6107036105fd366004613acc565b600460208181526000928352604092839020835160a081018552815460ff8082161515835261010082048116151594830194909452620100008104841615159582019590955273ffffffffffffffffffffffffffffffffffffffff630100000090950485166060820152600182015485166080820152600282015460038301549483015460058401546006850154600786015460089096015494988481169867ffffffffffffffff7401000000000000000000000000000000000000000080880482169a7c01000000000000000000000000000000000000000000000000000000009889900481169a8486169a928504909316989093049092169594939290811691168c565b6040516101c69c9b9a99989796959493929190613fcf565b6101bc670de0b6b3a764000081565b610278610738366004613acc565b612326565b61024061074b366004613ae5565b6124fe565b60065461077c9074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101c6565b600061084284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060065488945090925082915067ffffffffffffffff740100000000000000000000000000000000000000008204169073ffffffffffffffffffffffffffffffffffffffff1661081a81610e41565b7f4153534552545f545255544800000000000000000000000000000000000000006000610e89565b90505b9392505050565b610854612631565b610881600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6000818152600460205260409020600281015473ffffffffffffffffffffffffffffffffffffffff16610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20646f6573206e6f74206578697374000000000000000060448201526064015b60405180910390fd5b60028101547c0100000000000000000000000000000000000000000000000000000000900460ff16156109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f417373657274696f6e20616c726561647920736574746c656400000000000000604482015260640161090c565b6002810180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000179055600881015473ffffffffffffffffffffffffffffffffffffffff16610b865742600382015474010000000000000000000000000000000000000000900467ffffffffffffffff161115610a9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420657870697265640000000000000000000000604482015260640161090c565b6003810180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81167c01000000000000000000000000000000000000000000000000000000001790915560028201546006830154610b159273ffffffffffffffffffffffffffffffffffffffff90811692169061269d565b610b20826001612776565b60028101546040805160008152600160208201523381830152905173ffffffffffffffffffffffffffffffffffffffff9092169184917ff4fa324b13daeb4e1aae736c2553632ae0fb16fb31f2d4da8ac99fd056313a13919081900360600190a3610e0d565b60058101546002820154600091610bc19185919074010000000000000000000000000000000000000000900467ffffffffffffffff166128e3565b8254909150610100900460ff1615610c02576003820180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff169055610c58565b6003820180547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16670de0b6b3a764000083147c0100000000000000000000000000000000000000000000000000000000021790555b6000670de0b6b3a76400008214610c8957600883015473ffffffffffffffffffffffffffffffffffffffff16610ca5565b600283015473ffffffffffffffffffffffffffffffffffffffff165b90506000670de0b6b3a76400008460060154600554610cc491906140da565b610cce9190614146565b905060008185600601546002610ce491906140da565b610cee9190614181565b9050610d1d610cfb612973565b600387015473ffffffffffffffffffffffffffffffffffffffff16908461269d565b6003850154610d439073ffffffffffffffffffffffffffffffffffffffff16848361269d565b8454610100900460ff16610d84576003850154610d849087907c0100000000000000000000000000000000000000000000000000000000900460ff16612776565b600385015460408051600181527c010000000000000000000000000000000000000000000000000000000090920460ff1615156020830152339082015273ffffffffffffffffffffffffffffffffffffffff84169087907ff4fa324b13daeb4e1aae736c2553632ae0fb16fb31f2d4da8ac99fd056313a139060600160405180910390a3505050505b50610e3e600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812060010154600554610e7f82670de0b6b3a76400006140da565b6108459190614146565b6000610e93612631565b610ec0600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b42610edb8b8667ffffffffffffffff84168a8a8e8e8b612a4a565b915073ffffffffffffffffffffffffffffffffffffffff8a16610f5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f41737365727465722063616e7420626520300000000000000000000000000000604482015260640161090c565b60008281526004602052604090206002015473ffffffffffffffffffffffffffffffffffffffff1615610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20616c7265616479206578697374730000000000000000604482015260640161090c565b610ff284612a91565b611058576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e737570706f72746564206964656e74696669657200000000000000000000604482015260640161090c565b61106186612b75565b6110c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e737570706f727465642063757272656e6379000000000000000000000000604482015260640161090c565b6110d086610e41565b851015611139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f426f6e6420616d6f756e7420746f6f206c6f7700000000000000000000000000604482015260640161090c565b6040805161022081018252600061018082018181526101a083018290526101c08301829052336101e084015273ffffffffffffffffffffffffffffffffffffffff8c81166102008501529083528d8116602084015267ffffffffffffffff8516938301939093526060820152908716608082015260a081016111bb8984614194565b67ffffffffffffffff1681526020016000151581526020018481526020018581526020018681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152506004600084815260200190815260200160002060008201518160000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548160ff02191690831515021790555060608201518160000160036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505060208201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550606082015181600201601c6101000a81548160ff02191690831515021790555060808201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160030160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060c082015181600301601c6101000a81548160ff02191690831515021790555060e08201518160040155610100820151816005015561012082015181600601556101408201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101608201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050600061151283612d68565b80519091501561157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420616c6c6f7765640000000000000000000000604482015260640161090c565b600083815260046020908152604091829020908301519183015160609093015181547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1662010000911515919091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010093151593909302929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690151517905561164873ffffffffffffffffffffffffffffffffffffffff8716333088612e70565b838a73ffffffffffffffffffffffffffffffffffffffff16837fdb1513f0abeb57a364db56aa3eb52015cca5268f00fd67bc73aaf22bccab02b7868f8e8e338f8a6116939190614194565b8f8f6040516116a99897969594939291906141b5565b60405180910390a4506116e2600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b9998505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314611776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b6117806000612ece565b565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314611809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b670de0b6b3a764000081111561187b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4275726e656420626f6e642070657263656e74616765203e2031303000000000604482015260640161090c565b600081116118e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4275726e656420626f6e642070657263656e7461676520697320300000000000604482015260640161090c565b60058190556006805467ffffffffffffffff841674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8616171790556119797f4153534552545f5452555448000000000000000000000000000000000000000084611e24565b6040805173ffffffffffffffffffffffffffffffffffffffff8516815267ffffffffffffffff841660208201529081018290527fd0f09246d369018534c67fec6a6c3259c6f962ef82c5521c337ae0ccc104e4bd9060600160405180910390a1505050565b6000818152600460205260408120600201547c0100000000000000000000000000000000000000000000000000000000900460ff16611a2057611a208261084c565b611a2982612326565b92915050565b611a37612631565b611a64600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8116611ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f44697370757465722063616e2774206265203000000000000000000000000000604482015260640161090c565b6000828152600460205260409020600281015473ffffffffffffffffffffffffffffffffffffffff16611b70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f417373657274696f6e20646f6573206e6f742065786973740000000000000000604482015260640161090c565b600881015473ffffffffffffffffffffffffffffffffffffffff1615611bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f417373657274696f6e20616c7265616479206469737075746564000000000000604482015260640161090c565b42600382015474010000000000000000000000000000000000000000900467ffffffffffffffff1611611c81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f417373657274696f6e2069732065787069726564000000000000000000000000604482015260640161090c565b611c8a83612f4b565b611cf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f44697370757465206e6f7420616c6c6f77656400000000000000000000000000604482015260640161090c565b6008810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8481169190911790915560068201546003830154611d5092169033903090612e70565b60058101546002820154611d8791859174010000000000000000000000000000000000000000900467ffffffffffffffff1661303a565b611d90836130be565b8054610100900460ff1615611daa57611daa836000612776565b60405173ffffffffffffffffffffffffffffffffffffffff831690339085907f60133788b013c89f2a3756dbc47e3484997b87bd7e0af98a7d70232032c1ce2b90600090a450611e20600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b5050565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4f7261636c65000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd473ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401602060405180830381865afa158015611ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef29190614225565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055611f3f6131e7565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b836040518263ffffffff1660e01b8152600401611f7991815260200190565b602060405180830381865afa158015611f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fba9190614252565b600083815260036020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ffd61327c565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301529190911690633a3ab67290602401602060405180830381865afa15801561206b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208f9190614252565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556120e9612973565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301529190911690635b97aadd90602401602060405180830381865afa158015612157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217b919061426d565b5173ffffffffffffffffffffffffffffffffffffffff90911660009081526002602052604090206001015550565b60608167ffffffffffffffff8111156121c4576121c4613b02565b6040519080825280602002602001820160405280156121f757816020015b60608152602001906001900390816121e25790505b50905060005b82811015612314576000803086868581811061221b5761221b6142af565b905060200281019061222d91906142de565b60405161223b92919061434a565b600060405180830381855af49150503d8060008114612276576040519150601f19603f3d011682016040523d82523d6000602084013e61227b565b606091505b5091509150816122e15760448151101561229457600080fd5b600481019050808060200190518101906122ae919061435a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090c9190613fbc565b808484815181106122f4576122f46142af565b60200260200101819052505050808061230c906143d1565b9150506121fd565b5092915050565b6060611a2982613311565b6000818152600460208181526040808420815161022081018352815460ff80821615156101808401908152610100808404831615156101a0860152620100008404831615156101c086015273ffffffffffffffffffffffffffffffffffffffff630100000090940484166101e08601526001860154841661020086015290845260028501548084169785019790975267ffffffffffffffff740100000000000000000000000000000000000000008089048216978601979097527c010000000000000000000000000000000000000000000000000000000097889004831615156060860152600386015480851660808701529687041660a085015295909404909316151560c08201529381015460e08501526005810154928401929092526006820154610120840152600782015481166101408401526008909101541661016082018190521580159061247b57508051602001515b156124895750600092915050565b80606001516124f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f417373657274696f6e206e6f7420736574746c65640000000000000000000000604482015260640161090c565b60c0015192915050565b60005473ffffffffffffffffffffffffffffffffffffffff610100909104163314612585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161090c565b73ffffffffffffffffffffffffffffffffffffffff8116612628576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161090c565b610e3e81612ece565b60005460ff16611780576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161090c565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127719084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526133c9565b505050565b6000828152600460205260409020600781015460019091015473ffffffffffffffffffffffffffffffffffffffff91821691168115612838576040517ff1b156b200000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff83169063f1b156b290604401600060405180830381600087803b15801561281f57600080fd5b505af1158015612833573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff8116156128dd576040517ff1b156b200000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff82169063f1b156b290604401600060405180830381600087803b1580156128c457600080fd5b505af11580156128d8573d6000803e3d6000fd5b505050505b50505050565b60006128ee846134d5565b73ffffffffffffffffffffffffffffffffffffffff1663719c6d56848461291488613311565b6040518463ffffffff1660e01b815260040161293293929190614409565b602060405180830381865afa15801561294f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108429190614428565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f53746f726500000000000000000000000000000000000000000000000000000060048201526000907f000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd473ffffffffffffffffffffffffffffffffffffffff169063aafd5e40906024015b602060405180830381865afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190614225565b905090565b6000888888888888888833604051602001612a6d99989796959493929190614441565b60405160208183030381529060405280519060200120905098975050505050505050565b60008181526003602052604081205460ff1615612ab057506001919050565b612ab86131e7565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b836040518263ffffffff1660e01b8152600401612af291815260200190565b602060405180830381865afa158015612b0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b339190614252565b60009283526003602052604090922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592831790555060ff1690565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604081205460ff1615612bab57506001919050565b612bb361327c565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529190911690633a3ab67290602401602060405180830381865afa158015612c21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c459190614252565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055612c9f612973565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529190911690635b97aadd90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d31919061426d565b5173ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090206001810192909255505460ff1690565b60408051608081018252600080825260208083018290528284018290526060830182905284825260049052919091206001015473ffffffffffffffffffffffffffffffffffffffff1680612de1575050604080516080810182526000808252602082018190529181018290526060810191909152919050565b6040517fa6b011a70000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff82169063a6b011a790602401608060405180830381865afa158015612e4c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084591906144b7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526128dd9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016126ef565b6000805473ffffffffffffffffffffffffffffffffffffffff8381166101008181027fffffffffffffffffffffff0000000000000000000000000000000000000000ff851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b60008181526004602052604081205462010000900460ff16612f6f57506001919050565b60008281526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff1680612fa55750600192915050565b6040517f6b915d910000000000000000000000000000000000000000000000000000000081526004810184905233602482015273ffffffffffffffffffffffffffffffffffffffff821690636b915d9190604401602060405180830381865afa158015613016573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190614252565b613043836134d5565b73ffffffffffffffffffffffffffffffffffffffff1663216666a4838361306987613311565b6040518463ffffffff1660e01b815260040161308793929190614409565b600060405180830381600087803b1580156130a157600080fd5b505af11580156130b5573d6000803e3d6000fd5b50505050505050565b6000818152600460205260409020600781015460019091015473ffffffffffffffffffffffffffffffffffffffff91821691168115613178576040517fd448a4ec0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff83169063d448a4ec90602401600060405180830381600087803b15801561315f57600080fd5b505af1158015613173573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff811615612771576040517fd448a4ec0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff82169063d448a4ec90602401613087565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4964656e74696669657257686974656c6973740000000000000000000000000060048201526000907f000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd473ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612a04565b6040517faafd5e400000000000000000000000000000000000000000000000000000000081527f436f6c6c61746572616c57686974656c6973740000000000000000000000000060048201526000907f000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd473ffffffffffffffffffffffffffffffffffffffff169063aafd5e4090602401612a04565b6060611a29613365604051806020016040528060008152506040518060400160405280600b81526020017f617373657274696f6e496400000000000000000000000000000000000000000081525085613537565b604080518082018252600a81527f6f6f41737365727465720000000000000000000000000000000000000000000060208083019190915260008781526004909152919091206002015473ffffffffffffffffffffffffffffffffffffffff1661357d565b600061342b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166135989092919063ffffffff16565b80519091501561277157808060200190518101906134499190614252565b612771576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161090c565b60008181526004602052604081205460ff16156135195760008281526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff16611a29565b505060015473ffffffffffffffffffffffffffffffffffffffff1690565b6060600061354585856135a7565b90508481613552856135e9565b60405160200161356493929190614534565b6040516020818303038152906040529150509392505050565b6060600061358b85856135a7565b905084816135528561362a565b606061084284846000856136a2565b8151606090156135d857816040516020016135c29190614577565b6040516020818303038152906040529050611a29565b816040516020016135c291906145e3565b60606135f8608083901c613822565b61360183613822565b6040805160208101939093528201526060015b6040516020818303038152906040529050919050565b606061364b6fffffffffffffffffffffffffffffffff602084901c16613822565b6136668360601b6bffffffffffffffffffffffff1916613822565b6040516020016136149291909182527fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b606082471015613734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161090c565b843b61379c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161090c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516137c59190614624565b60006040518083038185875af1925050503d8060008114613802576040519150601f19603f3d011682016040523d82523d6000602084013e613807565b606091505b50915091506138178282866139c4565b979650505050505050565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f0808080808080808080808080808080808080808080808080808080808080808168161394657613946614117565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b606083156139d3575081610845565b8251156139e35782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090c9190613fbc565b73ffffffffffffffffffffffffffffffffffffffff81168114610e3e57600080fd5b8035613a4481613a17565b919050565b600080600060408486031215613a5e57600080fd5b833567ffffffffffffffff80821115613a7657600080fd5b818601915086601f830112613a8a57600080fd5b813581811115613a9957600080fd5b876020828501011115613aab57600080fd5b60209283019550935050840135613ac181613a17565b809150509250925092565b600060208284031215613ade57600080fd5b5035919050565b600060208284031215613af757600080fd5b813561084581613a17565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613b7857613b78613b02565b604052919050565b600067ffffffffffffffff821115613b9a57613b9a613b02565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b803567ffffffffffffffff81168114613a4457600080fd5b60008060008060008060008060006101208a8c031215613bfd57600080fd5b893567ffffffffffffffff811115613c1457600080fd5b8a01601f81018c13613c2557600080fd5b8035613c38613c3382613b80565b613b31565b8181528d6020838501011115613c4d57600080fd5b81602084016020830137600060208383010152809b50505050613c7260208b01613a39565b9750613c8060408b01613a39565b9650613c8e60608b01613a39565b9550613c9c60808b01613bc6565b9450613caa60a08b01613a39565b935060c08a0135925060e08a013591506101008a013590509295985092959850929598565b600080600060608486031215613ce457600080fd5b8335613cef81613a17565b9250613cfd60208501613bc6565b9150604084013590509250925092565b815180511515825260208082015115158184015260408083015115158185015260608084015173ffffffffffffffffffffffffffffffffffffffff9081168287015260809485015181168587015292860151831660a08601529085015167ffffffffffffffff1660c0850152840151151560e084015290830151908116610100808401919091526102008301919060a08501519150610120613dba8186018467ffffffffffffffff169052565b60c08601519250610140613dd18187018515159052565b60e08701516101608781019190915292870151610180870152908601516101a086015285015173ffffffffffffffffffffffffffffffffffffffff9081166101c0860152908501519081166101e08501529050612314565b60008060408385031215613e3c57600080fd5b823591506020830135613e4e81613a17565b809150509250929050565b60008060208385031215613e6c57600080fd5b823567ffffffffffffffff80821115613e8457600080fd5b818501915085601f830112613e9857600080fd5b813581811115613ea757600080fd5b8660208260051b8501011115613ebc57600080fd5b60209290920196919550909350505050565b60005b83811015613ee9578181015183820152602001613ed1565b50506000910152565b60008151808452613f0a816020860160208601613ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613faf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613f9d858351613ef2565b94509285019290850190600101613f63565b5092979650505050505050565b6020815260006108456020830184613ef2565b610200810161402b828f805115158252602081015115156020830152604081015115156040830152606081015173ffffffffffffffffffffffffffffffffffffffff808216606085015280608084015116608085015250505050565b73ffffffffffffffffffffffffffffffffffffffff9c8d1660a083015267ffffffffffffffff9b8c1660c083015299151560e0820152978b16610100890152959098166101208701529215156101408601526101608501919091526101808401526101a08301529284166101c0820152919092166101e090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614112576141126140ab565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261417c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611a2957611a296140ab565b67ffffffffffffffff818116838216019080821115612314576123146140ab565b60006101008a83528060208401526141cf8184018b613ef2565b73ffffffffffffffffffffffffffffffffffffffff998a16604085015297891660608401525050938616608085015267ffffffffffffffff9290921660a084015290931660c082015260e0019190915292915050565b60006020828403121561423757600080fd5b815161084581613a17565b80518015158114613a4457600080fd5b60006020828403121561426457600080fd5b61084582614242565b60006020828403121561427f57600080fd5b6040516020810181811067ffffffffffffffff821117156142a2576142a2613b02565b6040529151825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261431357600080fd5b83018035915067ffffffffffffffff82111561432e57600080fd5b60200191503681900382131561434357600080fd5b9250929050565b8183823760009101908152919050565b60006020828403121561436c57600080fd5b815167ffffffffffffffff81111561438357600080fd5b8201601f8101841361439457600080fd5b80516143a2613c3382613b80565b8181528560208385010111156143b757600080fd5b6143c8826020830160208601613ece565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614402576144026140ab565b5060010190565b8381528260208201526060604082015260006143c86060830184613ef2565b60006020828403121561443a57600080fd5b5051919050565b60006101208083526144558184018d613ef2565b602084019b909b525050604081019790975267ffffffffffffffff95909516606087015273ffffffffffffffffffffffffffffffffffffffff938416608087015291831660a0860152821660c085015260e08401521661010090910152919050565b6000608082840312156144c957600080fd5b6040516080810181811067ffffffffffffffff821117156144ec576144ec613b02565b6040526144f883614242565b815261450660208401614242565b602082015261451760408401614242565b604082015261452860608401614242565b60608201529392505050565b60008451614546818460208901613ece565b84519083019061455a818360208901613ece565b845191019061456d818360208801613ece565b0195945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000008152600082516145af816001850160208701613ece565b7f3a000000000000000000000000000000000000000000000000000000000000006001939091019283015250600201919050565b600082516145f5818460208701613ece565b7f3a00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b60008251614636818460208701613ece565b919091019291505056fea2646970667358221220f03b241d1c61d5494f1c346bd67521c49226c51304400e4ef1a5a988d347aaf364736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd4000000000000000000000000ddafbb505ad214d7b80b1f830fccc89b60fb7a830000000000000000000000000000000000000000000000000000000000001c20
-----Decoded View---------------
Arg [0] : _finder (address): 0xef684c38f94f48775959ecf2012d7e864ffb9dd4
Arg [1] : _defaultCurrency (address): 0xddafbb505ad214d7b80b1f830fccc89b60fb7a83
Arg [2] : _defaultLiveness (uint64): 7200
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ef684c38f94f48775959ecf2012d7e864ffb9dd4
Arg [1] : 000000000000000000000000ddafbb505ad214d7b80b1f830fccc89b60fb7a83
Arg [2] : 0000000000000000000000000000000000000000000000000000000000001c20
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.