Polygon Sponsored slots available. Book your slot here!
Contract Overview
Balance:
0 MATIC
MATIC Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash |
Method
|
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xc4368eba35f9ef8b294cd4cc5ef91ec8f4a9058f0e5a1b4b03689195a9210726 | 0x60e06040 | 39013883 | 119 days 32 mins ago | 0x0cda2396c6edc69fe7d47afacac81ce5594640d8 | IN | Create: UmaCtfAdapter | 0 MATIC | 0.465288172 |
[ Download CSV Export ]
Contract Name:
UmaCtfAdapter
Compiler Version
v0.8.15+commit.e14f2714
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 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being 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. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @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 work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/security/ReentrancyGuard.sol"; import { Auth } from "./mixins/Auth.sol"; import { BulletinBoard } from "./mixins/BulletinBoard.sol"; import { TransferHelper } from "./libraries/TransferHelper.sol"; import { AncillaryDataLib } from "./libraries/AncillaryDataLib.sol"; import { IFinder } from "./interfaces/IFinder.sol"; import { IAddressWhitelist } from "./interfaces/IAddressWhitelist.sol"; import { IConditionalTokens } from "./interfaces/IConditionalTokens.sol"; import { IOptimisticOracleV2 } from "./interfaces/IOptimisticOracleV2.sol"; import { IOptimisticRequester } from "./interfaces/IOptimisticRequester.sol"; import { QuestionData, IUmaCtfAdapter } from "./interfaces/IUmaCtfAdapter.sol"; /// @title UmaCtfAdapter /// @notice Enables resolution of Polymarket CTF markets via UMA's Optimistic Oracle contract UmaCtfAdapter is IUmaCtfAdapter, Auth, BulletinBoard, IOptimisticRequester, ReentrancyGuard { /*/////////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////////*/ /// @notice Conditional Tokens Framework IConditionalTokens public immutable ctf; /// @notice Optimistic Oracle IOptimisticOracleV2 public immutable optimisticOracle; /// @notice Collateral Whitelist IAddressWhitelist public immutable collateralWhitelist; /// @notice Time period after which an admin can emergency resolve a condition uint256 public constant emergencySafetyPeriod = 2 days; /// @notice Unique query identifier for the Optimistic Oracle bytes32 public constant yesOrNoIdentifier = "YES_OR_NO_QUERY"; /// @notice Maximum ancillary data length uint256 public constant maxAncillaryData = 8139; /// @notice Mapping of questionID to QuestionData mapping(bytes32 => QuestionData) public questions; modifier onlyOptimisticOracle() { if (msg.sender != address(optimisticOracle)) revert NotOptimisticOracle(); _; } constructor(address _ctf, address _finder) { ctf = IConditionalTokens(_ctf); IFinder finder = IFinder(_finder); optimisticOracle = IOptimisticOracleV2(finder.getImplementationAddress("OptimisticOracleV2")); collateralWhitelist = IAddressWhitelist(finder.getImplementationAddress("CollateralWhitelist")); } /*/////////////////////////////////////////////////////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////*/ /// @notice Initializes a question /// Atomically adds the question to the Adapter, prepares it on the ConditionalTokens Framework and requests a price from the OO. /// If a reward is provided, the caller must have approved the Adapter as spender and have enough rewardToken /// to pay for the price request. /// Prepares the condition using the Adapter as the oracle and a fixed outcome slot count = 2. /// @param ancillaryData - Data used to resolve a question /// @param rewardToken - ERC20 token address used for payment of rewards and fees /// @param reward - Reward offered to a successful proposer /// @param proposalBond - Bond required to be posted by OO proposers/disputers. If 0, the default OO bond is used. function initialize(bytes memory ancillaryData, address rewardToken, uint256 reward, uint256 proposalBond) external returns (bytes32 questionID) { if (!collateralWhitelist.isOnWhitelist(rewardToken)) revert UnsupportedToken(); bytes memory data = AncillaryDataLib._appendAncillaryData(msg.sender, ancillaryData); if (ancillaryData.length == 0 || data.length > maxAncillaryData) revert InvalidAncillaryData(); questionID = keccak256(data); if (_isInitialized(questions[questionID])) revert Initialized(); uint256 timestamp = block.timestamp; // Persist the question parameters in storage _saveQuestion(msg.sender, questionID, data, timestamp, rewardToken, reward, proposalBond); // Prepare the question on the CTF ctf.prepareCondition(address(this), questionID, 2); // Request a price for the question from the OO _requestPrice(msg.sender, timestamp, data, rewardToken, reward, proposalBond); emit QuestionInitialized(questionID, timestamp, msg.sender, data, rewardToken, reward, proposalBond); } /// @notice Checks whether a questionID is ready to be resolved /// @param questionID - The unique questionID function ready(bytes32 questionID) public view returns (bool) { return _ready(questions[questionID]); } /// @notice Resolves a question /// Pulls price information from the OO and resolves the underlying CTF market. /// Reverts if price is not available on the OO /// Resets the question if the price returned by the OO is the Ignore price /// @param questionID - The unique questionID of the question function resolve(bytes32 questionID) external { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); if (questionData.paused) revert Paused(); if (questionData.resolved) revert Resolved(); if (!_hasPrice(questionData)) revert NotReadyToResolve(); // Resolve the underlying market return _resolve(questionID, questionData); } /// @notice Retrieves the expected payout array of the question /// @param questionID - The unique questionID of the question function getExpectedPayouts(bytes32 questionID) public view returns (uint256[] memory) { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); if (!_hasPrice(questionData)) revert PriceNotAvailable(); // Fetches price from OO int256 price = optimisticOracle.getRequest( address(this), yesOrNoIdentifier, questionData.requestTimestamp, questionData.ancillaryData ).resolvedPrice; return _constructPayouts(price); } /// @notice Callback which is executed on dispute /// Resets the question and sends out a new price request to the OO /// @param ancillaryData - Ancillary data of the request function priceDisputed(bytes32, uint256, bytes memory ancillaryData, uint256) external onlyOptimisticOracle { bytes32 questionID = keccak256(ancillaryData); QuestionData storage questionData = questions[questionID]; if (questionData.reset) return; // If the question has not been reset previously, reset the question // Ensures that there are at most 2 OO Requests at a time for a question _reset(address(this), questionID, questionData); } /// @notice Checks if a question is initialized /// @param questionID - The unique questionID function isInitialized(bytes32 questionID) public view returns (bool) { return _isInitialized(questions[questionID]); } /// @notice Checks if a question has been flagged for emergency resolution /// @param questionID - The unique questionID function isFlagged(bytes32 questionID) public view returns (bool) { return _isFlagged(questions[questionID]); } /// @notice Gets the QuestionData for the given questionID /// @param questionID - The unique questionID function getQuestion(bytes32 questionID) external view returns (QuestionData memory) { return questions[questionID]; } /*//////////////////////////////////////////////////////////////////// ADMIN ONLY FUNCTIONS ///////////////////////////////////////////////////////////////////*/ /// @notice Flags a market for emergency resolution /// @param questionID - The unique questionID of the question function flag(bytes32 questionID) external onlyAdmin { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); if (_isFlagged(questionData)) revert Flagged(); questionData.emergencyResolutionTimestamp = block.timestamp + emergencySafetyPeriod; questionData.paused = true; emit QuestionFlagged(questionID); } /// @notice Allows an admin to reset a question, sending out a new price request to the OO. /// Failsafe to be used if the priceDisputed callback reverts during execution. /// @param questionID - The unique questionID function reset(bytes32 questionID) external onlyAdmin { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); if (questionData.resolved) revert Resolved(); // Reset the question, paying for the price request from the caller _reset(msg.sender, questionID, questionData); } /// @notice Allows an admin to resolve a CTF market in an emergency /// @param questionID - The unique questionID of the question /// @param payouts - Array of position payouts for the referenced question function emergencyResolve(bytes32 questionID, uint256[] calldata payouts) external onlyAdmin { QuestionData storage questionData = questions[questionID]; if (payouts.length != 2) revert InvalidPayouts(); if (!_isInitialized(questionData)) revert NotInitialized(); if (!_isFlagged(questionData)) revert NotFlagged(); if (block.timestamp < questionData.emergencyResolutionTimestamp) revert SafetyPeriodNotPassed(); questionData.resolved = true; ctf.reportPayouts(questionID, payouts); emit QuestionEmergencyResolved(questionID, payouts); } /// @notice Allows an admin to pause market resolution in an emergency /// @param questionID - The unique questionID of the question function pause(bytes32 questionID) external onlyAdmin { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); questionData.paused = true; emit QuestionPaused(questionID); } /// @notice Allows an admin to unpause market resolution in an emergency /// @param questionID - The unique questionID of the question function unpause(bytes32 questionID) external onlyAdmin { QuestionData storage questionData = questions[questionID]; if (!_isInitialized(questionData)) revert NotInitialized(); questionData.paused = false; emit QuestionUnpaused(questionID); } /*/////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////*/ function _ready(QuestionData storage questionData) internal view returns (bool) { if (!_isInitialized(questionData)) return false; if (questionData.paused) return false; if (questionData.resolved) return false; return _hasPrice(questionData); } function _saveQuestion( address creator, bytes32 questionID, bytes memory ancillaryData, uint256 requestTimestamp, address rewardToken, uint256 reward, uint256 proposalBond ) internal { questions[questionID] = QuestionData({ requestTimestamp: requestTimestamp, reward: reward, proposalBond: proposalBond, emergencyResolutionTimestamp: 0, resolved: false, paused: false, reset: false, rewardToken: rewardToken, creator: creator, ancillaryData: ancillaryData }); } /// @notice Request a price from the Optimistic Oracle /// Transfers reward token from the requestor if non-zero reward is specified /// @param requestor - Address of the requestor /// @param requestTimestamp - Timestamp used in the OO request /// @param ancillaryData - Data used to resolve a question /// @param rewardToken - Address of the reward token /// @param reward - Reward amount, denominated in rewardToken /// @param bond - Bond amount used, denominated in rewardToken function _requestPrice( address requestor, uint256 requestTimestamp, bytes memory ancillaryData, address rewardToken, uint256 reward, uint256 bond ) internal { if (reward > 0) { // If the requestor is not the Adapter, the requestor pays for the price request // If not, the Adapter pays for the price request if (requestor != address(this)) { TransferHelper._transferFromERC20(rewardToken, requestor, address(this), reward); } // Approve the OO as spender on the reward token from the Adapter if (IERC20(rewardToken).allowance(address(this), address(optimisticOracle)) < reward) { IERC20(rewardToken).approve(address(optimisticOracle), type(uint256).max); } } // Send a price request to the Optimistic oracle optimisticOracle.requestPrice(yesOrNoIdentifier, requestTimestamp, ancillaryData, IERC20(rewardToken), reward); // Ensure the price request is event based optimisticOracle.setEventBased(yesOrNoIdentifier, requestTimestamp, ancillaryData); // Ensure that the dispute callback flag is set optimisticOracle.setCallbacks( yesOrNoIdentifier, requestTimestamp, ancillaryData, false, // DO NOT set callback on priceProposed true, // DO set callback on priceDisputed false // DO NOT set callback on priceSettled ); // Update the proposal bond on the Optimistic oracle if necessary if (bond > 0) optimisticOracle.setBond(yesOrNoIdentifier, requestTimestamp, ancillaryData, bond); } /// @notice Reset the question by updating the requestTimestamp field and sending a new price request to the OO /// @param questionID - The unique questionID function _reset(address requestor, bytes32 questionID, QuestionData storage questionData) internal { uint256 requestTimestamp = block.timestamp; // Update the question parameters in storage questionData.requestTimestamp = requestTimestamp; questionData.reset = true; // Send out a new price request with the new timestamp _requestPrice( requestor, requestTimestamp, questionData.ancillaryData, questionData.rewardToken, questionData.reward, questionData.proposalBond ); emit QuestionReset(questionID); } /// @notice Resolves the underlying CTF market /// @param questionID - The unique questionID of the question /// @param questionData - The question data parameters function _resolve(bytes32 questionID, QuestionData storage questionData) internal { // Get the price from the OO int256 price = optimisticOracle.settleAndGetPrice( yesOrNoIdentifier, questionData.requestTimestamp, questionData.ancillaryData ); // If the OO returns the ignore price, reset the question if (price == _ignorePrice()) return _reset(address(this), questionID, questionData); // Construct the payout array for the question uint256[] memory payouts = _constructPayouts(price); // Set resolved flag questionData.resolved = true; // Resolve the underlying CTF market ctf.reportPayouts(questionID, payouts); emit QuestionResolved(questionID, price, payouts); } function _hasPrice(QuestionData storage questionData) internal view returns (bool) { return optimisticOracle.hasPrice( address(this), yesOrNoIdentifier, questionData.requestTimestamp, questionData.ancillaryData ); } function _isFlagged(QuestionData storage questionData) internal view returns (bool) { return questionData.emergencyResolutionTimestamp > 0; } function _isInitialized(QuestionData storage questionData) internal view returns (bool) { return questionData.ancillaryData.length > 0; } /// @notice Construct the payout array given the price /// @param price - The price retrieved from the OO function _constructPayouts(int256 price) internal pure returns (uint256[] memory) { // Payouts: [YES, NO] uint256[] memory payouts = new uint256[](2); // Valid prices are 0, 0.5 and 1 if (price != 0 && price != 0.5 ether && price != 1 ether) revert InvalidOOPrice(); if (price == 0) { // NO: Report [Yes, No] as [0, 1] payouts[0] = 0; payouts[1] = 1; } else if (price == 0.5 ether) { // UNKNOWN: Report [Yes, No] as [1, 1], 50/50 payouts[0] = 1; payouts[1] = 1; } else { // YES: Report [Yes, No] as [1, 0] payouts[0] = 1; payouts[1] = 0; } return payouts; } function _ignorePrice() internal pure returns (int256) { return type(int256).min; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.15; interface IAddressWhitelist { function addToWhitelist(address) external; function removeFromWhitelist(address) external; function isOnWhitelist(address) external view returns (bool); function getWhitelist() external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IAuthEE { error NotAdmin(); /// @notice Emitted when a new admin is added event NewAdmin(address indexed admin, address indexed newAdminAddress); /// @notice Emitted when an admin is removed event RemovedAdmin(address indexed admin, address indexed removedAdmin); } interface IAuth is IAuthEE { function isAdmin(address) external view returns (bool); function addAdmin(address) external; function removeAdmin(address) external; function renounceAdmin() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; interface IConditionalTokens { /// Mapping key is an condition ID. Value represents numerators of the payout vector associated with the condition. This array is initialized with a length equal to the outcome slot count. E.g. Condition with 3 outcomes [A, B, C] and two of those correct [0.5, 0.5, 0]. In Ethereum there are no decimal values, so here, 0.5 is represented by fractions like 1/2 == 0.5. That's why we need numerator and denominator values. Payout numerators are also used as a check of initialization. If the numerators array is empty (has length zero), the condition was not created/prepared. See getOutcomeSlotCount. function payoutNumerators(bytes32) external returns (uint256[] memory); /// Denominator is also used for checking if the condition has been resolved. If the denominator is non-zero, then the condition has been resolved. function payoutDenominator(bytes32) external returns (uint256); /// @dev This function prepares a condition by initializing a payout vector associated with the condition. /// @param oracle The account assigned to report the result for the prepared condition. /// @param questionId An identifier for the question to be answered by the oracle. /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256. function prepareCondition(address oracle, bytes32 questionId, uint256 outcomeSlotCount) external; /// @dev Called by the oracle for reporting results of conditions. Will set the payout vector for the condition with the ID ``keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount))``, where oracle is the message sender, questionId is one of the parameters of this function, and outcomeSlotCount is the length of the payouts parameter, which contains the payoutNumerators for each outcome slot of the condition. /// @param questionId The question ID the oracle is answering for /// @param payouts The oracle's answer function reportPayouts(bytes32 questionId, uint256[] calldata payouts) external; /// @dev This function splits a position. If splitting from the collateral, this contract will attempt to transfer `amount` collateral from the message sender to itself. Otherwise, this contract will burn `amount` stake held by the message sender in the position being split worth of EIP 1155 tokens. Regardless, if successful, `amount` stake will be minted in the split target positions. If any of the transfers, mints, or burns fail, the transaction will revert. The transaction will also revert if the given partition is trivial, invalid, or refers to more slots than the condition is prepared with. /// @param collateralToken The address of the positions' backing collateral token. /// @param parentCollectionId The ID of the outcome collections common to the position being split and the split target positions. May be null, in which only the collateral is shared. /// @param conditionId The ID of the condition to split on. /// @param partition An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.g. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.g. 0b110 is A|B, 0b010 is B, etc. /// @param amount The amount of collateral or stake to split. function splitPosition( IERC20 collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata partition, uint256 amount ) external; function mergePositions( IERC20 collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata partition, uint256 amount ) external; function redeemPositions( IERC20 collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata indexSets ) external; /// @dev Gets the outcome slot count of a condition. /// @param conditionId ID of the condition. /// @return Number of outcome slots associated with a condition, or zero if condition has not been prepared yet. function getOutcomeSlotCount(bytes32 conditionId) external view returns (uint256); /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for the question. /// @param oracle The account assigned to report the result for the prepared condition. /// @param questionId An identifier for the question to be answered by the oracle. /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256. function getConditionId(address oracle, bytes32 questionId, uint256 outcomeSlotCount) external pure returns (bytes32); /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection. /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if there's no parent. /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome collection. /// @param indexSet Index set of the outcome collection to combine with the parent outcome collection. function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint256 indexSet) external view returns (bytes32); /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs are used as the ERC-1155 ID for this contract. /// @param collateralToken Collateral token which backs the position. /// @param collectionId ID of the outcome collection associated with this position. function getPositionId(IERC20 collateralToken, bytes32 collectionId) external pure returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.15; /** * @title Provides addresses of the live contracts implementing certain interfaces. * @dev Examples are the Oracle or Store interfaces. */ interface IFinder { /** * @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: MIT pragma solidity 0.8.15; import "openzeppelin-contracts/token/ERC20/IERC20.sol"; struct RequestSettings { bool eventBased; // True if the request is set to be event-based. bool refundOnDispute; // True if the requester should be refunded their reward on dispute. bool callbackOnPriceProposed; // True if callbackOnPriceProposed callback is required. bool callbackOnPriceDisputed; // True if callbackOnPriceDisputed callback is required. bool callbackOnPriceSettled; // True if callbackOnPriceSettled callback is required. uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee. uint256 customLiveness; // Custom liveness value set by the requester. } // Struct representing a price request. struct Request { address proposer; // Address of the proposer. address disputer; // Address of the disputer. IERC20 currency; // ERC20 token used to pay rewards and fees. bool settled; // True if the request is settled. RequestSettings requestSettings; // Custom settings associated with a request. int256 proposedPrice; // Price that the proposer submitted. int256 resolvedPrice; // Price resolved once the request is settled. uint256 expirationTime; // Time at which the request auto-settles without a dispute. uint256 reward; // Amount of the currency to pay to the proposer on settlement. uint256 finalFee; // Final fee to pay to the Store upon request to the DVM. } /// @title Optimistic Oracle V2 Interface interface IOptimisticOracleV2 { /// @notice Requests a new price. /// @param identifier price identifier being requested. /// @param timestamp timestamp of the price being requested. /// @param ancillaryData ancillary data representing additional args being passed with the price request. /// @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM. /// @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0, /// which could make sense if the contract requests and proposes the value in the same call or /// provides its own reward system. /// @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay. /// This can be changed with a subsequent call to setBond(). function requestPrice( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, IERC20 currency, uint256 reward ) external returns (uint256 totalBond); /** * @notice Proposes a price value for an existing price request. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @param proposedPrice price being proposed. * @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to * the proposer once settled if the proposal is correct. */ function proposePrice( address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, int256 proposedPrice ) external returns (uint256 totalBond); /** * @notice Disputes a price value for an existing price request with an active proposal. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to * the disputer once settled if the dispute was valid (the proposal was incorrect). */ function disputePrice(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external returns (uint256 totalBond); /// @notice Set the proposal bond associated with a price request. /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. /// @param bond custom bond amount to set. /// @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be /// changed again with a subsequent call to setBond(). function setBond(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 bond) external returns (uint256 totalBond); /// @notice Sets the request to be an "event-based" request. /// @dev Calling this method has a few impacts on the request: /// /// 1. The timestamp at which the request is evaluated is the time of the proposal, not the timestamp associated /// with the request. /// /// 2. The proposer cannot propose the "too early" value (TOO_EARLY_RESPONSE). This is to ensure that a proposer who /// prematurely proposes a response loses their bond. /// /// 3. RefundoOnDispute is automatically set, meaning disputes trigger the reward to be automatically refunded to /// the requesting contract. /// /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. function setEventBased(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external; /// @notice Sets which callbacks should be enabled for the request. /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. /// @param callbackOnPriceProposed whether to enable the callback onPriceProposed. /// @param callbackOnPriceDisputed whether to enable the callback onPriceDisputed. /// @param callbackOnPriceSettled whether to enable the callback onPriceSettled. function setCallbacks( bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, bool callbackOnPriceProposed, bool callbackOnPriceDisputed, bool callbackOnPriceSettled ) external; /** * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable. * @param requester sender of the initial price request. * @param identifier price identifier to identify the existing request. * @param timestamp timestamp to identify the existing request. * @param ancillaryData ancillary data of the price being requested. * @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes * the returned bonds as well as additional rewards. */ function settle(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external returns (uint256 payout); /// @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled /// or settleable. Note: this method is not view so that this call may actually settle the price request if it /// hasn't been settled. /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. /// @return resolved price. //// function settleAndGetPrice(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external returns (int256); /// @notice Gets the current data structure containing all information about a price request. /// @param requester sender of the initial price request. /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. /// @return the Request data structure. //// function getRequest(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external view returns (Request memory); /// @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price). /// @param requester sender of the initial price request. /// @param identifier price identifier to identify the existing request. /// @param timestamp timestamp to identify the existing request. /// @param ancillaryData ancillary data of the price being requested. /// @return true if price has resolved or settled, false otherwise. function hasPrice(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title Optimistic Requester interface IOptimisticRequester { /// @notice Callback for disputes. /// @param identifier price identifier being requested. /// @param timestamp timestamp of the price being requested. /// @param ancillaryData ancillary data of the price being requested. /// @param refund refund received in the case that refundOnDispute was enabled. function priceDisputed(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 refund) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; struct QuestionData { /// @notice Request timestamp, set when a request is made to the Optimistic Oracle /// @dev Used to identify the request and NOT used by the DVM to determine validity uint256 requestTimestamp; /// @notice Reward offered to a successful proposer uint256 reward; /// @notice Additional bond required by Optimistic oracle proposers/disputers uint256 proposalBond; /// @notice Emergency resolution timestamp, set when a market is flagged for emergency resolution uint256 emergencyResolutionTimestamp; /// @notice Flag marking whether a question is resolved bool resolved; /// @notice Flag marking whether a question is paused bool paused; /// @notice Flag marking whether a question has been reset. A question can only be reset once bool reset; /// @notice ERC20 token address used for payment of rewards, proposal bonds and fees address rewardToken; /// @notice The address of the question creator address creator; /// @notice Data used to resolve a condition bytes ancillaryData; } interface IUmaCtfAdapterEE { error NotInitialized(); error NotFlagged(); error NotReadyToResolve(); error Resolved(); error Initialized(); error UnsupportedToken(); error Flagged(); error Paused(); error SafetyPeriodNotPassed(); error PriceNotAvailable(); error InvalidAncillaryData(); error NotOptimisticOracle(); error InvalidOOPrice(); error InvalidPayouts(); /// @notice Emitted when a questionID is initialized event QuestionInitialized( bytes32 indexed questionID, uint256 indexed requestTimestamp, address indexed creator, bytes ancillaryData, address rewardToken, uint256 reward, uint256 proposalBond ); /// @notice Emitted when a question is paused by an authorized user event QuestionPaused(bytes32 indexed questionID); /// @notice Emitted when a question is unpaused by an authorized user event QuestionUnpaused(bytes32 indexed questionID); /// @notice Emitted when a question is flagged by an admin for emergency resolution event QuestionFlagged(bytes32 indexed questionID); /// @notice Emitted when a question is reset event QuestionReset(bytes32 indexed questionID); /// @notice Emitted when a question is resolved event QuestionResolved(bytes32 indexed questionID, int256 indexed settledPrice, uint256[] payouts); /// @notice Emitted when a question is emergency resolved event QuestionEmergencyResolved(bytes32 indexed questionID, uint256[] payouts); } interface IUmaCtfAdapter is IUmaCtfAdapterEE { function initialize(bytes memory, address, uint256, uint256) external returns (bytes32); function resolve(bytes32) external; function flag(bytes32) external; function reset(bytes32) external; function pause(bytes32) external; function unpause(bytes32) external; function getQuestion(bytes32) external returns (QuestionData memory); function ready(bytes32) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; library AncillaryDataLib { string private constant initializerPrefix = ",initializer:"; /// @notice Appends the initializer address to the ancillaryData /// @param initializer - The initializer address /// @param ancillaryData - The ancillary data function _appendAncillaryData(address initializer, bytes memory ancillaryData) internal pure returns (bytes memory) { return abi.encodePacked(ancillaryData, initializerPrefix, _toUtf8BytesAddress(initializer)); } /// @notice Returns a UTF8-encoded address /// Source: UMA Protocol's AncillaryDataLib /// https://github.com/UMAprotocol/protocol/blob/9967e70e7db3f262fde0dc9d89ea04d4cd11ed97/packages/core/contracts/common/implementation/AncillaryData.sol /// Will return address in all lower case characters and without the leading 0x. /// @param addr - The address to encode. function _toUtf8BytesAddress(address addr) internal pure returns (bytes memory) { return abi.encodePacked( _toUtf8Bytes32Bottom(bytes32(bytes20(addr)) >> 128), bytes8(_toUtf8Bytes32Bottom(bytes20(addr))) ); } /// @notice 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); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { SafeTransferLib, ERC20 } from "solmate/utils/SafeTransferLib.sol"; /// @title TransferHelper /// @notice Helper library to transfer tokens library TransferHelper { /// @notice Transfers tokens from the targeted address to the given destination /// @param token - The contract address of the token to be transferred /// @param from - The originating address from which the tokens will be transferred /// @param to - The destination address of the transfer /// @param amount - The amount to be transferred function _transferFromERC20(address token, address from, address to, uint256 amount) internal { SafeTransferLib.safeTransferFrom(ERC20(token), from, to, amount); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { IAuth } from "../interfaces/IAuth.sol"; /// @title Auth /// @notice Provides access control modifiers abstract contract Auth is IAuth { /// @notice Auth mapping(address => uint256) public admins; modifier onlyAdmin() { if (admins[msg.sender] != 1) revert NotAdmin(); _; } constructor() { admins[msg.sender] = 1; } /// @notice Adds an Admin /// @param admin - The address of the admin function addAdmin(address admin) external onlyAdmin { admins[admin] = 1; emit NewAdmin(msg.sender, admin); } /// @notice Removes an admin /// @param admin - The address of the admin to be removed function removeAdmin(address admin) external onlyAdmin { admins[admin] = 0; emit RemovedAdmin(msg.sender, admin); } /// @notice Renounces Admin privileges from the caller function renounceAdmin() external onlyAdmin { admins[msg.sender] = 0; emit RemovedAdmin(msg.sender, msg.sender); } /// @notice Checks if an address is an admin /// @param addr - The address to be checked function isAdmin(address addr) external view returns (bool) { return admins[addr] == 1; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title Bulletin Board /// @notice A registry containing ancillary data updates abstract contract BulletinBoard { struct AncillaryDataUpdate { uint256 timestamp; bytes update; } /// @notice Mapping to an array of Ancillary data updates for questions mapping(bytes32 => AncillaryDataUpdate[]) public updates; /// @notice Emitted when an ancillary data update is posted event AncillaryDataUpdated(bytes32 indexed questionID, address indexed owner, bytes update); /// @notice Post an update for the question /// Anyone can post an update for any questionID, but users should only consider updates posted by the question creator /// @param questionID - The unique questionID /// @param update - The update for the question function postUpdate(bytes32 questionID, bytes memory update) external { bytes32 id = keccak256(abi.encode(questionID, msg.sender)); updates[id].push(AncillaryDataUpdate({timestamp: block.timestamp, update: update})); } /// @notice Gets all updates for a questionID and owner /// @param questionID - The unique questionID /// @param owner - The address of the question initializer function getUpdates(bytes32 questionID, address owner) public view returns (AncillaryDataUpdate[] memory) { return updates[keccak256(abi.encode(questionID, owner))]; } /// @notice Gets the latest update for a questionID and owner /// @param questionID - The unique questionID /// @param owner - The address of the question initializer function getLatestUpdate(bytes32 questionID, address owner) external view returns (AncillaryDataUpdate memory) { AncillaryDataUpdate[] memory currentUpdates = getUpdates(questionID, owner); if (currentUpdates.length == 0) return AncillaryDataUpdate({timestamp: 0, update: ""}); return currentUpdates[currentUpdates.length - 1]; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_ctf","type":"address"},{"internalType":"address","name":"_finder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Flagged","type":"error"},{"inputs":[],"name":"Initialized","type":"error"},{"inputs":[],"name":"InvalidAncillaryData","type":"error"},{"inputs":[],"name":"InvalidOOPrice","type":"error"},{"inputs":[],"name":"InvalidPayouts","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotFlagged","type":"error"},{"inputs":[],"name":"NotInitialized","type":"error"},{"inputs":[],"name":"NotOptimisticOracle","type":"error"},{"inputs":[],"name":"NotReadyToResolve","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"PriceNotAvailable","type":"error"},{"inputs":[],"name":"Resolved","type":"error"},{"inputs":[],"name":"SafetyPeriodNotPassed","type":"error"},{"inputs":[],"name":"UnsupportedToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"update","type":"bytes"}],"name":"AncillaryDataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdminAddress","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"},{"indexed":false,"internalType":"uint256[]","name":"payouts","type":"uint256[]"}],"name":"QuestionEmergencyResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"QuestionFlagged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"requestTimestamp","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"proposalBond","type":"uint256"}],"name":"QuestionInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"QuestionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"QuestionReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"},{"indexed":true,"internalType":"int256","name":"settledPrice","type":"int256"},{"indexed":false,"internalType":"uint256[]","name":"payouts","type":"uint256[]"}],"name":"QuestionResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"QuestionUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"removedAdmin","type":"address"}],"name":"RemovedAdmin","type":"event"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralWhitelist","outputs":[{"internalType":"contract IAddressWhitelist","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ctf","outputs":[{"internalType":"contract IConditionalTokens","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"},{"internalType":"uint256[]","name":"payouts","type":"uint256[]"}],"name":"emergencyResolve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencySafetyPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"flag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"getExpectedPayouts","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"getLatestUpdate","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"update","type":"bytes"}],"internalType":"struct BulletinBoard.AncillaryDataUpdate","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"getQuestion","outputs":[{"components":[{"internalType":"uint256","name":"requestTimestamp","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"proposalBond","type":"uint256"},{"internalType":"uint256","name":"emergencyResolutionTimestamp","type":"uint256"},{"internalType":"bool","name":"resolved","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reset","type":"bool"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"internalType":"struct QuestionData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"getUpdates","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"update","type":"bytes"}],"internalType":"struct BulletinBoard.AncillaryDataUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"proposalBond","type":"uint256"}],"name":"initialize","outputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"isFlagged","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAncillaryData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimisticOracle","outputs":[{"internalType":"contract IOptimisticOracleV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"},{"internalType":"bytes","name":"update","type":"bytes"}],"name":"postUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"priceDisputed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"questions","outputs":[{"internalType":"uint256","name":"requestTimestamp","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"proposalBond","type":"uint256"},{"internalType":"uint256","name":"emergencyResolutionTimestamp","type":"uint256"},{"internalType":"bool","name":"resolved","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reset","type":"bool"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"ready","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"reset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"resolve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"questionID","type":"bytes32"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"updates","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"update","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yesOrNoIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b50604051620039c4380380620039c483398101604081905262000034916200019a565b33600090815260208190526040908190206001908190556002556001600160a01b0383811660805290516302abf57960e61b81527127b83a34b6b4b9ba34b1a7b930b1b632ab1960711b6004820152829182169063aafd5e4090602401602060405180830381865afa158015620000af573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d59190620001d2565b6001600160a01b0390811660a0526040516302abf57960e61b81527f436f6c6c61746572616c57686974656c6973740000000000000000000000000060048201529082169063aafd5e4090602401602060405180830381865afa15801562000141573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001679190620001d2565b6001600160a01b031660c05250620001f7915050565b80516001600160a01b03811681146200019557600080fd5b919050565b60008060408385031215620001ae57600080fd5b620001b9836200017d565b9150620001c9602084016200017d565b90509250929050565b600060208284031215620001e557600080fd5b620001f0826200017d565b9392505050565b60805160a05160c05161373b620002896000396000818161048101526116ff015260008181610214015281816105b9015281816108b001528181611b2301528181611d44015281816121df0152818161229801528181612372015281816124500152818161251601526125f101526000818161026501528181611382015281816118a10152611e94015261373b6000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806378165a4811610104578063c66d4c6c116100a2578063ed56531a11610071578063ed56531a146104b6578063f7b637bb146104c9578063f8063207146104dc578063fcac49a2146104ef57600080fd5b8063c66d4c6c1461044b578063dddb468014610455578063e4ee614a1461047c578063ed3c7d40146104a357600080fd5b806395addb90116100de57806395addb90146103dc5780639ce7c0e014610405578063bf2dde3814610418578063c0cab0a21461042b57600080fd5b806378165a48146103a057806389ab0871146103b35780638bad0c0a146103d457600080fd5b806334e5e28e1161017157806358c039cd1161014b57806358c039cd146103515780635c23bdf5146103715780636b5acc6314610384578063704802751461038d57600080fd5b806334e5e28e146102e3578063429b62e514610303578063555c56fc1461033157600080fd5b806322302922116101ad578063223029221461020f57806322a9339f1461026057806324d7806c146102875780632f4dae9f146102d057600080fd5b8063072d1259146101d45780630d8f2372146101e95780631785f53c146101fc575b600080fd5b6101e76101e2366004612af1565b610502565b005b6101e76101f7366004612b38565b6105a1565b6101e761020a366004612bb5565b610655565b6102367f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6102367f000000000000000000000000000000000000000000000000000000000000000081565b6102c0610295366004612bb5565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460011490565b6040519015158152602001610257565b6101e76102de366004612bd9565b6106f0565b6102f66102f1366004612bd9565b6107df565b6040516102579190612c2d565b610323610311366004612bb5565b60006020819052908152604090205481565b604051908152602001610257565b61034461033f366004612c40565b610965565b6040516102579190612d05565b61036461035f366004612bd9565b610abc565b6040516102579190612d85565b6101e761037f366004612bd9565b610c85565b610323611fcb81565b6101e761039b366004612bb5565b610da2565b6101e76103ae366004612bd9565b610e3e565b6103c66103c1366004612e4c565b610f7f565b604051610257929190612e6e565b6101e7611048565b6103ef6103ea366004612bd9565b6110cc565b6040516102579a99989796959493929190612e87565b6101e7610413366004612f04565b6111ce565b6102c0610426366004612bd9565b61142b565b61043e610439366004612c40565b611444565b6040516102579190612f83565b6103236202a30081565b6103237f5945535f4f525f4e4f5f5155455259000000000000000000000000000000000081565b6102367f000000000000000000000000000000000000000000000000000000000000000081565b6101e76104b1366004612bd9565b6114cd565b6101e76104c4366004612bd9565b6115ad565b6102c06104d7366004612bd9565b6116a0565b6103236104ea366004612f96565b6116b7565b6102c06104fd366004612bd9565b611980565b60408051602081018490523391810191909152600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000818152600180845284822086860190955242865285840188815285548083018755958352939091208551600290950201938455915190945090820190610599908261308e565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610610576040517f05cef85500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151602080840191909120600081815260039092526040909120600481015462010000900460ff161561064457505061064f565b610599308383611997565b50505050565b3360009081526020819052604090205460011461069e576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152602081905260408082208290555133917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a350565b33600090815260208190526040902054600114610739576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260036020526040902061075081611ac5565b610786576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405182907f92d28918c5574e7fc0f4f948c39502682c81cfb4089b07b83f95b3264e5e5e0690600090a25050565b60008181526003602052604090206060906107f981611ac5565b61082f576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083881611ae1565b61086e576040517f579a480100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80546040517fa9904f9b00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163a9904f9b9161090c9130917f5945535f4f525f4e4f5f51554552590000000000000000000000000000000000916006890190600401613243565b61020060405180830381865afa15801561092a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094e919061334d565b60c00151905061095d81611bc0565b949350505050565b606060016000848460405160200161099d92919091825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b604051602081830303815290604052805190602001208152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610aaf578382906000526020600020906002020160405180604001604052908160008201548152602001600182018054610a1e90612ff5565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4a90612ff5565b8015610a975780601f10610a6c57610100808354040283529160200191610a97565b820191906000526020600020905b815481529060010190602001808311610a7a57829003601f168201915b505050505081525050815260200190600101906109e1565b5050505090505b92915050565b610b4460405180610140016040528060008152602001600081526020016000815260200160008152602001600015158152602001600015158152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b60008281526003602081815260409283902083516101408101855281548152600182015492810192909252600281015493820193909352908201546060820152600482015460ff808216151560808401526101008083048216151560a0850152620100008304909116151560c0840152630100000090910473ffffffffffffffffffffffffffffffffffffffff90811660e08401526005840154169082015260068201805491929161012084019190610bfc90612ff5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2890612ff5565b8015610c755780601f10610c4a57610100808354040283529160200191610c75565b820191906000526020600020905b815481529060010190602001808311610c5857829003601f168201915b5050505050815250509050919050565b6000818152600360205260409020610c9c81611ac5565b610cd2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004810154610100900460ff1615610d16576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600481015460ff1615610d55576040517fea00f1a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d5e81611ae1565b610d94576040517fb488fe4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d9e8282611d02565b5050565b33600090815260208190526040902054600114610deb576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040808220600190555133917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc91a350565b33600090815260208190526040902054600114610e87576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600360205260409020610e9e81611ac5565b610ed4576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600381015415610f10576040517fe8e3a25900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1d6202a30042613427565b60038201556004810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905560405182907f2435a0347185933b12027c6f394a5fd9c03646dba233e956f50658719dfc0b3590600090a25050565b60016020528160005260406000208181548110610f9b57600080fd5b906000526020600020906002020160009150915050806000015490806001018054610fc590612ff5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff190612ff5565b801561103e5780601f106110135761010080835404028352916020019161103e565b820191906000526020600020905b81548152906001019060200180831161102157829003601f168201915b5050505050905082565b33600090815260208190526040902054600114611091576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152602081905260408082208290555182917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a3565b60036020819052600091825260409091208054600182015460028301549383015460048401546005850154600686018054959794969495939460ff8085169561010086048216956201000081049092169473ffffffffffffffffffffffffffffffffffffffff6301000000909304831694921692919061114b90612ff5565b80601f016020809104026020016040519081016040528092919081815260200182805461117790612ff5565b80156111c45780601f10611199576101008083540402835291602001916111c4565b820191906000526020600020905b8154815290600101906020018083116111a757829003601f168201915b505050505090508a565b33600090815260208190526040902054600114611217576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526003602052604090206002821461125f576040517f663493a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61126881611ac5565b61129e576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038101546112d9576040517fbb825d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060030154421015611317576040517f2a2c257c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517fc49298ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163c49298ac916113b9918891889188910161348e565b600060405180830381600087803b1580156113d357600080fd5b505af11580156113e7573d6000803e3d6000fd5b50505050837f6edb5841a476c9c29c34a652d1a44f785fe71a6157a3da9a6a6a589a1bd2945a848460405161141d9291906134b1565b60405180910390a250505050565b6000818152600360208190526040822001541515610ab6565b60408051808201909152600081526060602082015260006114658484610965565b9050805160000361149d5760405180604001604052806000815260200160405180602001604052806000815250815250915050610ab6565b80600182516114ac91906134c5565b815181106114bc576114bc6134dc565b602002602001015191505092915050565b33600090815260208190526040902054600114611516576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260036020526040902061152d81611ac5565b611563576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600481015460ff16156115a2576040517fea00f1a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d9e338383611997565b336000908152602081905260409020546001146115f6576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260036020526040902061160d81611ac5565b611643576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905560405182907f6ded7250a9d5f79aef5add44600fc20a74a0af6f4730baa4fc4ab87bf484b81290600090a25050565b6000818152600360205260408120610ab690611ac5565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a3ab67290602401602060405180830381865afa158015611748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176c919061350b565b6117a2576040517f6a17288200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006117ae3387611f3a565b90508551600014806117c25750611fcb8151115b156117f9576040517f9702d51200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8080519060200120915061181e60036000848152602001908152602001600020611ac5565b15611855576040517f5daa87a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42611865338484848a8a8a611fa5565b6040517fd96ee75400000000000000000000000000000000000000000000000000000000815230600482015260248101849052600260448201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063d96ee75490606401600060405180830381600087803b1580156118fa57600080fd5b505af115801561190e573d6000803e3d6000fd5b5050505061192033828489898961216d565b3373ffffffffffffffffffffffffffffffffffffffff1681847feee0897acd6893adcaf2ba5158191b3601098ab6bece35c5d57874340b64c5b7858a8a8a60405161196e9493929190613526565b60405180910390a45050949350505050565b6000818152600360205260408120610ab690612698565b428082556004820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055600682018054611a949186918491906119e290612ff5565b80601f0160208091040260200160405190810160405280929190818152602001828054611a0e90612ff5565b8015611a5b5780601f10611a3057610100808354040283529160200191611a5b565b820191906000526020600020905b815481529060010190602001808311611a3e57829003601f168201915b50505050508560040160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff168660010154876002015461216d565b60405183907f7981b5832932948db4e32a4a16a0f44b2ce7ff088574afb9364b313f70f82e8f90600090a250505050565b600080826006018054611ad790612ff5565b9050119050919050565b80546040517fbc58ccaa00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163bc58ccaa91611b7f9130917f5945535f4f525f4e4f5f51554552590000000000000000000000000000000000916006890190600401613243565b602060405180830381865afa158015611b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab6919061350b565b604080516002808252606080830184529260009291906020830190803683370190505090508215801590611bfc5750826706f05b59d3b2000014155b8015611c10575082670de0b6b3a764000014155b15611c47576040517f86c9649e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611c9657600081600081518110611c6457611c646134dc565b602002602001018181525050600181600181518110611c8557611c856134dc565b602002602001018181525050610ab6565b826706f05b59d3b2000003611cba57600181600081518110611c6457611c646134dc565b600181600081518110611ccf57611ccf6134dc565b602002602001018181525050600081600181518110611cf057611cf06134dc565b60200260200101818152505092915050565b80546040517f53b5923900000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916353b5923991611d9f917f5945535f4f525f4e4f5f515545525900000000000000000000000000000000009190600688019060040161356b565b6020604051808303816000875af1158015611dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de2919061358a565b90507f80000000000000000000000000000000000000000000000000000000000000008103611e1b57611e16308484611997565b505050565b6000611e2682611bc0565b600480850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517fc49298ac00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163c49298ac91611ec99188918691016135a3565b600060405180830381600087803b158015611ee357600080fd5b505af1158015611ef7573d6000803e3d6000fd5b5050505081847f566c3fbdd12dd86bb341787f6d531f79fd7ad4ce7e3ae2d15ac0ca1b601af9df83604051611f2c9190612c2d565b60405180910390a350505050565b6060816040518060400160405280600d81526020017f2c696e697469616c697a65723a00000000000000000000000000000000000000815250611f7c856126e7565b604051602001611f8e939291906135bc565b604051602081830303815290604052905092915050565b604051806101400160405280858152602001838152602001828152602001600081526020016000151581526020016000151581526020016000151581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff16815260200186815250600360008881526020019081526020016000206000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a81548160ff02191690831515021790555060e08201518160040160036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610120820151816006019081612161919061308e565b50505050505050505050565b81156123355773ffffffffffffffffffffffffffffffffffffffff8616301461219c5761219c83873085612775565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602483015283919085169063dd62ed3e90604401602060405180830381865afa158015612231573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612255919061358a565b1015612335576040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602483015284169063095ea7b3906044016020604051808303816000875af115801561230f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612333919061350b565b505b6040517f11df92f100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906311df92f1906123cf907f5945535f4f525f4e4f5f515545525900000000000000000000000000000000009089908990899089906004016135ff565b6020604051808303816000875af11580156123ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612412919061358a565b506040517f120698af00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063120698af906124a9907f5945535f4f525f4e4f5f515545525900000000000000000000000000000000009089908990600401613648565b600060405180830381600087803b1580156124c357600080fd5b505af11580156124d7573d6000803e3d6000fd5b50506040517ff327b07500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016925063f327b0759150612579907f5945535f4f525f4e4f5f5155455259000000000000000000000000000000000090899089906000906001908290600401613667565b600060405180830381600087803b15801561259357600080fd5b505af11580156125a7573d6000803e3d6000fd5b505050506000811115610599576040517fad5a755a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad5a755a9061264c907f5945535f4f525f4e4f5f51554552590000000000000000000000000000000000908990899087906004016136a6565b6020604051808303816000875af115801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f919061358a565b50505050505050565b60006126a382611ac5565b6126af57506000919050565b6004820154610100900460ff16156126c957506000919050565b600482015460ff16156126de57506000919050565b610ab682611ae1565b60606127086fffffffffffffffffffffffffffffffff602084901c16612781565b6127238360601b6bffffffffffffffffffffffff1916612781565b60405160200161275f9291909182527fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040529050919050565b61064f84848484612923565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f080808080808080808080808080808080808080808080808080808080808080816816128a5576128a56136d6565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806129e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640160405180910390fd5b5050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610140810167ffffffffffffffff81118282101715612a4057612a406129ed565b60405290565b600082601f830112612a5757600080fd5b813567ffffffffffffffff80821115612a7257612a726129ed565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612ab857612ab86129ed565b81604052838152866020858801011115612ad157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612b0457600080fd5b82359150602083013567ffffffffffffffff811115612b2257600080fd5b612b2e85828601612a46565b9150509250929050565b60008060008060808587031215612b4e57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612b7357600080fd5b612b7f87828801612a46565b949793965093946060013593505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612bb257600080fd5b50565b600060208284031215612bc757600080fd5b8135612bd281612b90565b9392505050565b600060208284031215612beb57600080fd5b5035919050565b600081518084526020808501945080840160005b83811015612c2257815187529582019590820190600101612c06565b509495945050505050565b602081526000612bd26020830184612bf2565b60008060408385031215612c5357600080fd5b823591506020830135612c6581612b90565b809150509250929050565b60005b83811015612c8b578181015183820152602001612c73565b8381111561064f5750506000910152565b60008151808452612cb4816020860160208601612c70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b80518252600060208201516040602085015261095d6040850182612c9c565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612d78577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612d66858351612ce6565b94509285019290850190600101612d2c565b5092979650505050505050565b602081528151602082015260208201516040820152604082015160608201526060820151608082015260006080830151612dc360a084018215159052565b5060a083015180151560c08401525060c083015180151560e08401525060e0830151610100612e098185018373ffffffffffffffffffffffffffffffffffffffff169052565b8401519050610120612e328482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015161014084810152905061095d610160840182612c9c565b60008060408385031215612e5f57600080fd5b50508035926020909101359150565b82815260406020820152600061095d6040830184612c9c565b60006101408c83528b60208401528a6040840152896060840152881515608084015287151560a084015286151560c084015273ffffffffffffffffffffffffffffffffffffffff80871660e08501528086166101008501525080610120840152612ef381840185612c9c565b9d9c50505050505050505050505050565b600080600060408486031215612f1957600080fd5b83359250602084013567ffffffffffffffff80821115612f3857600080fd5b818601915086601f830112612f4c57600080fd5b813581811115612f5b57600080fd5b8760208260051b8501011115612f7057600080fd5b6020830194508093505050509250925092565b602081526000612bd26020830184612ce6565b60008060008060808587031215612fac57600080fd5b843567ffffffffffffffff811115612fc357600080fd5b612fcf87828801612a46565b9450506020850135612fe081612b90565b93969395505050506040820135916060013590565b600181811c9082168061300957607f821691505b602082108103613042577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115611e1657600081815260208120601f850160051c8101602086101561306f5750805b601f850160051c820191505b818110156105995782815560010161307b565b815167ffffffffffffffff8111156130a8576130a86129ed565b6130bc816130b68454612ff5565b84613048565b602080601f83116001811461310f57600084156130d95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610599565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561315c5788860151825594840194600190910190840161313d565b508582101561319857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600081546131b581612ff5565b8085526020600183811680156131d2576001811461320a57613238565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b8901019550613238565b866000528260002060005b858110156132305781548a8201860152908301908401613215565b890184019650505b505050505092915050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015282604082015260806060820152600061327e60808301846131a8565b9695505050505050565b805161329381612b90565b919050565b8051801515811461329357600080fd5b600060e082840312156132ba57600080fd5b60405160e0810181811067ffffffffffffffff821117156132dd576132dd6129ed565b6040529050806132ec83613298565b81526132fa60208401613298565b602082015261330b60408401613298565b604082015261331c60608401613298565b606082015261332d60808401613298565b608082015260a083015160a082015260c083015160c08201525092915050565b6000610200828403121561336057600080fd5b613368612a1c565b61337183613288565b815261337f60208401613288565b602082015261339060408401613288565b60408201526133a160608401613298565b60608201526133b384608085016132a8565b608082015261016083015160a082015261018083015160c08201526101a083015160e08201526101c08301516101008201526101e09092015161012083015250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561343a5761343a6133f8565b500190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561347157600080fd5b8260051b8083602087013760009401602001938452509192915050565b8381526040602082015260006134a860408301848661343f565b95945050505050565b60208152600061095d60208301848661343f565b6000828210156134d7576134d76133f8565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561351d57600080fd5b612bd282613298565b6080815260006135396080830187612c9c565b73ffffffffffffffffffffffffffffffffffffffff959095166020830152506040810192909252606090910152919050565b8381528260208201526060604082015260006134a860608301846131a8565b60006020828403121561359c57600080fd5b5051919050565b82815260406020820152600061095d6040830184612bf2565b600084516135ce818460208901612c70565b8451908301906135e2818360208901612c70565b84519101906135f5818360208801612c70565b0195945050505050565b85815284602082015260a06040820152600061361e60a0830186612c9c565b73ffffffffffffffffffffffffffffffffffffffff94909416606083015250608001529392505050565b8381528260208201526060604082015260006134a86060830184612c9c565b86815285602082015260c06040820152600061368660c0830187612c9c565b9415156060830152509115156080830152151560a0909101529392505050565b8481528360208201526080604082015260006136c56080830185612c9c565b905082606083015295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220239ab9e8271b3afc9238b83bae1ff4338e1d5deebca724ab3bda8b8bc69fbe7b64736f6c634300080f00330000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604500000000000000000000000009aea4b2242abc8bb4bb78d537a67a245a7bec64
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604500000000000000000000000009aea4b2242abc8bb4bb78d537a67a245a7bec64
-----Decoded View---------------
Arg [0] : _ctf (address): 0x4d97dcd97ec945f40cf65f87097ace5ea0476045
Arg [1] : _finder (address): 0x09aea4b2242abc8bb4bb78d537a67a245a7bec64
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea0476045
Arg [1] : 00000000000000000000000009aea4b2242abc8bb4bb78d537a67a245a7bec64
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.