Overview
ETH Balance
0.2 ETH
Eth Value
$532.99 (@ $2,664.96/ETH)More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Submit Answer By... | 6109437 | 2378 days ago | IN | 0 ETH | 0.00210397 | ||||
Request Arbitrat... | 6109104 | 2378 days ago | IN | 0.2 ETH | 0.00304392 | ||||
Set Dispute Fee | 6109026 | 2378 days ago | IN | 0 ETH | 0.00085122 | ||||
Transfer Ownersh... | 6108408 | 2378 days ago | IN | 0 ETH | 0.00057628 | ||||
Set Dispute Fee | 5936201 | 2407 days ago | IN | 0 ETH | 0.00038979 | ||||
Set Reality Chec... | 5936175 | 2407 days ago | IN | 0 ETH | 0.0004032 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Arbitrator
Compiler Version
v0.4.18+commit.9cf6e910
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2018-07-09 */ pragma solidity 0.4.18; library SafeMath32 { function add(uint32 a, uint32 b) internal pure returns (uint32) { uint32 c = a + b; assert(c >= a); return c; } } library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } contract Owned { address public owner; function Owned() public { owner = msg.sender; } modifier onlyOwner { require(msg.sender == owner); _; } function transferOwnership(address newOwner) onlyOwner public { owner = newOwner; } } contract BalanceHolder { mapping(address => uint256) public balanceOf; event LogWithdraw( address indexed user, uint256 amount ); function withdraw() public { uint256 bal = balanceOf[msg.sender]; balanceOf[msg.sender] = 0; msg.sender.transfer(bal); LogWithdraw(msg.sender, bal); } } contract RealityCheck is BalanceHolder { using SafeMath for uint256; using SafeMath32 for uint32; address constant NULL_ADDRESS = address(0); // History hash when no history is created, or history has been cleared bytes32 constant NULL_HASH = bytes32(0); // An unitinalized finalize_ts for a question will indicate an unanswered question. uint32 constant UNANSWERED = 0; // An unanswered reveal_ts for a commitment will indicate that it does not exist. uint256 constant COMMITMENT_NON_EXISTENT = 0; // Commit->reveal timeout is 1/8 of the question timeout (rounded down). uint32 constant COMMITMENT_TIMEOUT_RATIO = 8; event LogSetQuestionFee( address arbitrator, uint256 amount ); event LogNewTemplate( uint256 indexed template_id, address indexed user, string question_text ); event LogNewQuestion( bytes32 indexed question_id, address indexed user, uint256 template_id, string question, bytes32 indexed content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 created ); event LogFundAnswerBounty( bytes32 indexed question_id, uint256 bounty_added, uint256 bounty, address indexed user ); event LogNewAnswer( bytes32 answer, bytes32 indexed question_id, bytes32 history_hash, address indexed user, uint256 bond, uint256 ts, bool is_commitment ); event LogAnswerReveal( bytes32 indexed question_id, address indexed user, bytes32 indexed answer_hash, bytes32 answer, uint256 nonce, uint256 bond ); event LogNotifyOfArbitrationRequest( bytes32 indexed question_id, address indexed user ); event LogFinalize( bytes32 indexed question_id, bytes32 indexed answer ); event LogClaim( bytes32 indexed question_id, address indexed user, uint256 amount ); struct Question { bytes32 content_hash; address arbitrator; uint32 opening_ts; uint32 timeout; uint32 finalize_ts; bool is_pending_arbitration; uint256 bounty; bytes32 best_answer; bytes32 history_hash; uint256 bond; } // Stored in a mapping indexed by commitment_id, a hash of commitment hash, question, bond. struct Commitment { uint32 reveal_ts; bool is_revealed; bytes32 revealed_answer; } // Only used when claiming more bonds than fits into a transaction // Stored in a mapping indexed by question_id. struct Claim { address payee; uint256 last_bond; uint256 queued_funds; } uint256 nextTemplateID = 0; mapping(uint256 => uint256) public templates; mapping(uint256 => bytes32) public template_hashes; mapping(bytes32 => Question) public questions; mapping(bytes32 => Claim) question_claims; mapping(bytes32 => Commitment) public commitments; mapping(address => uint256) public arbitrator_question_fees; modifier onlyArbitrator(bytes32 question_id) { require(msg.sender == questions[question_id].arbitrator); _; } modifier stateAny() { _; } modifier stateNotCreated(bytes32 question_id) { require(questions[question_id].timeout == 0); _; } modifier stateOpen(bytes32 question_id) { require(questions[question_id].timeout > 0); // Check existence require(!questions[question_id].is_pending_arbitration); uint32 finalize_ts = questions[question_id].finalize_ts; require(finalize_ts == UNANSWERED || finalize_ts > uint32(now)); uint32 opening_ts = questions[question_id].opening_ts; require(opening_ts == 0 || opening_ts <= uint32(now)); _; } modifier statePendingArbitration(bytes32 question_id) { require(questions[question_id].is_pending_arbitration); _; } modifier stateOpenOrPendingArbitration(bytes32 question_id) { require(questions[question_id].timeout > 0); // Check existence uint32 finalize_ts = questions[question_id].finalize_ts; require(finalize_ts == UNANSWERED || finalize_ts > uint32(now)); uint32 opening_ts = questions[question_id].opening_ts; require(opening_ts == 0 || opening_ts <= uint32(now)); _; } modifier stateFinalized(bytes32 question_id) { require(isFinalized(question_id)); _; } modifier bondMustBeZero() { require(msg.value == 0); _; } modifier bondMustDouble(bytes32 question_id) { require(msg.value > 0); require(msg.value >= (questions[question_id].bond.mul(2))); _; } modifier previousBondMustNotBeatMaxPrevious(bytes32 question_id, uint256 max_previous) { if (max_previous > 0) { require(questions[question_id].bond <= max_previous); } _; } /// @notice Constructor, sets up some initial templates /// @dev Creates some generalized templates for different question types used in the DApp. function RealityCheck() public { createTemplate('{"title": "%s", "type": "bool", "category": "%s"}'); createTemplate('{"title": "%s", "type": "uint", "decimals": 18, "category": "%s"}'); createTemplate('{"title": "%s", "type": "single-select", "outcomes": [%s], "category": "%s"}'); createTemplate('{"title": "%s", "type": "multiple-select", "outcomes": [%s], "category": "%s"}'); createTemplate('{"title": "%s", "type": "datetime", "category": "%s"}'); } /// @notice Function for arbitrator to set an optional per-question fee. /// @dev The per-question fee, charged when a question is asked, is intended as an anti-spam measure. /// @param fee The fee to be charged by the arbitrator when a question is asked function setQuestionFee(uint256 fee) stateAny() external { arbitrator_question_fees[msg.sender] = fee; LogSetQuestionFee(msg.sender, fee); } /// @notice Create a reusable template, which should be a JSON document. /// Placeholders should use gettext() syntax, eg %s. /// @dev Template data is only stored in the event logs, but its block number is kept in contract storage. /// @param content The template content /// @return The ID of the newly-created template, which is created sequentially. function createTemplate(string content) stateAny() public returns (uint256) { uint256 id = nextTemplateID; templates[id] = block.number; template_hashes[id] = keccak256(content); LogNewTemplate(id, msg.sender, content); nextTemplateID = id.add(1); return id; } /// @notice Create a new reusable template and use it to ask a question /// @dev Template data is only stored in the event logs, but its block number is kept in contract storage. /// @param content The template content /// @param question A string containing the parameters that will be passed into the template to make the question /// @param arbitrator The arbitration contract that will have the final word on the answer if there is a dispute /// @param timeout How long the contract should wait after the answer is changed before finalizing on that answer /// @param opening_ts If set, the earliest time it should be possible to answer the question. /// @param nonce A user-specified nonce used in the question ID. Change it to repeat a question. /// @return The ID of the newly-created template, which is created sequentially. function createTemplateAndAskQuestion( string content, string question, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce ) // stateNotCreated is enforced by the internal _askQuestion public payable returns (bytes32) { uint256 template_id = createTemplate(content); return askQuestion(template_id, question, arbitrator, timeout, opening_ts, nonce); } /// @notice Ask a new question and return the ID /// @dev Template data is only stored in the event logs, but its block number is kept in contract storage. /// @param template_id The ID number of the template the question will use /// @param question A string containing the parameters that will be passed into the template to make the question /// @param arbitrator The arbitration contract that will have the final word on the answer if there is a dispute /// @param timeout How long the contract should wait after the answer is changed before finalizing on that answer /// @param opening_ts If set, the earliest time it should be possible to answer the question. /// @param nonce A user-specified nonce used in the question ID. Change it to repeat a question. /// @return The ID of the newly-created question, created deterministically. function askQuestion(uint256 template_id, string question, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce) // stateNotCreated is enforced by the internal _askQuestion public payable returns (bytes32) { require(templates[template_id] > 0); // Template must exist bytes32 content_hash = keccak256(template_id, opening_ts, question); bytes32 question_id = keccak256(content_hash, arbitrator, timeout, msg.sender, nonce); _askQuestion(question_id, content_hash, arbitrator, timeout, opening_ts); LogNewQuestion(question_id, msg.sender, template_id, question, content_hash, arbitrator, timeout, opening_ts, nonce, now); return question_id; } function _askQuestion(bytes32 question_id, bytes32 content_hash, address arbitrator, uint32 timeout, uint32 opening_ts) stateNotCreated(question_id) internal { // A timeout of 0 makes no sense, and we will use this to check existence require(timeout > 0); require(timeout < 365 days); require(arbitrator != NULL_ADDRESS); uint256 bounty = msg.value; // The arbitrator can set a fee for asking a question. // This is intended as an anti-spam defence. // The fee is waived if the arbitrator is asking the question. // This allows them to set an impossibly high fee and make users proxy the question through them. // This would allow more sophisticated pricing, question whitelisting etc. if (msg.sender != arbitrator) { uint256 question_fee = arbitrator_question_fees[arbitrator]; require(bounty >= question_fee); bounty = bounty.sub(question_fee); balanceOf[arbitrator] = balanceOf[arbitrator].add(question_fee); } questions[question_id].content_hash = content_hash; questions[question_id].arbitrator = arbitrator; questions[question_id].opening_ts = opening_ts; questions[question_id].timeout = timeout; questions[question_id].bounty = bounty; } /// @notice Add funds to the bounty for a question /// @dev Add bounty funds after the initial question creation. Can be done any time until the question is finalized. /// @param question_id The ID of the question you wish to fund function fundAnswerBounty(bytes32 question_id) stateOpen(question_id) external payable { questions[question_id].bounty = questions[question_id].bounty.add(msg.value); LogFundAnswerBounty(question_id, msg.value, questions[question_id].bounty, msg.sender); } /// @notice Submit an answer for a question. /// @dev Adds the answer to the history and updates the current "best" answer. /// May be subject to front-running attacks; Substitute submitAnswerCommitment()->submitAnswerReveal() to prevent them. /// @param question_id The ID of the question /// @param answer The answer, encoded into bytes32 /// @param max_previous If specified, reverts if a bond higher than this was submitted after you sent your transaction. function submitAnswer(bytes32 question_id, bytes32 answer, uint256 max_previous) stateOpen(question_id) bondMustDouble(question_id) previousBondMustNotBeatMaxPrevious(question_id, max_previous) external payable { _addAnswerToHistory(question_id, answer, msg.sender, msg.value, false); _updateCurrentAnswer(question_id, answer, questions[question_id].timeout); } /// @notice Submit the hash of an answer, laying your claim to that answer if you reveal it in a subsequent transaction. /// @dev Creates a hash, commitment_id, uniquely identifying this answer, to this question, with this bond. /// The commitment_id is stored in the answer history where the answer would normally go. /// Does not update the current best answer - this is left to the later submitAnswerReveal() transaction. /// @param question_id The ID of the question /// @param answer_hash The hash of your answer, plus a nonce that you will later reveal /// @param max_previous If specified, reverts if a bond higher than this was submitted after you sent your transaction. /// @param _answerer If specified, the address to be given as the question answerer. Defaults to the sender. /// @dev Specifying the answerer is useful if you want to delegate the commit-and-reveal to a third-party. function submitAnswerCommitment(bytes32 question_id, bytes32 answer_hash, uint256 max_previous, address _answerer) stateOpen(question_id) bondMustDouble(question_id) previousBondMustNotBeatMaxPrevious(question_id, max_previous) external payable { bytes32 commitment_id = keccak256(question_id, answer_hash, msg.value); address answerer = (_answerer == NULL_ADDRESS) ? msg.sender : _answerer; require(commitments[commitment_id].reveal_ts == COMMITMENT_NON_EXISTENT); uint32 commitment_timeout = questions[question_id].timeout / COMMITMENT_TIMEOUT_RATIO; commitments[commitment_id].reveal_ts = uint32(now).add(commitment_timeout); _addAnswerToHistory(question_id, commitment_id, answerer, msg.value, true); } /// @notice Submit the answer whose hash you sent in a previous submitAnswerCommitment() transaction /// @dev Checks the parameters supplied recreate an existing commitment, and stores the revealed answer /// Updates the current answer unless someone has since supplied a new answer with a higher bond /// msg.sender is intentionally not restricted to the user who originally sent the commitment; /// For example, the user may want to provide the answer+nonce to a third-party service and let them send the tx /// NB If we are pending arbitration, it will be up to the arbitrator to wait and see any outstanding reveal is sent /// @param question_id The ID of the question /// @param answer The answer, encoded as bytes32 /// @param nonce The nonce that, combined with the answer, recreates the answer_hash you gave in submitAnswerCommitment() /// @param bond The bond that you paid in your submitAnswerCommitment() transaction function submitAnswerReveal(bytes32 question_id, bytes32 answer, uint256 nonce, uint256 bond) stateOpenOrPendingArbitration(question_id) external { bytes32 answer_hash = keccak256(answer, nonce); bytes32 commitment_id = keccak256(question_id, answer_hash, bond); require(!commitments[commitment_id].is_revealed); require(commitments[commitment_id].reveal_ts > uint32(now)); // Reveal deadline must not have passed commitments[commitment_id].revealed_answer = answer; commitments[commitment_id].is_revealed = true; if (bond == questions[question_id].bond) { _updateCurrentAnswer(question_id, answer, questions[question_id].timeout); } LogAnswerReveal(question_id, msg.sender, answer_hash, answer, nonce, bond); } function _addAnswerToHistory(bytes32 question_id, bytes32 answer_or_commitment_id, address answerer, uint256 bond, bool is_commitment) internal { bytes32 new_history_hash = keccak256(questions[question_id].history_hash, answer_or_commitment_id, bond, answerer, is_commitment); questions[question_id].bond = bond; questions[question_id].history_hash = new_history_hash; LogNewAnswer(answer_or_commitment_id, question_id, new_history_hash, answerer, bond, now, is_commitment); } function _updateCurrentAnswer(bytes32 question_id, bytes32 answer, uint32 timeout_secs) internal { questions[question_id].best_answer = answer; questions[question_id].finalize_ts = uint32(now).add(timeout_secs); } /// @notice Notify the contract that the arbitrator has been paid for a question, freezing it pending their decision. /// @dev The arbitrator contract is trusted to only call this if they've been paid, and tell us who paid them. /// @param question_id The ID of the question /// @param requester The account that requested arbitration /// @param max_previous If specified, reverts if a bond higher than this was submitted after you sent your transaction. function notifyOfArbitrationRequest(bytes32 question_id, address requester, uint256 max_previous) onlyArbitrator(question_id) stateOpen(question_id) previousBondMustNotBeatMaxPrevious(question_id, max_previous) external { questions[question_id].is_pending_arbitration = true; LogNotifyOfArbitrationRequest(question_id, requester); } /// @notice Submit the answer for a question, for use by the arbitrator. /// @dev Doesn't require (or allow) a bond. /// If the current final answer is correct, the account should be whoever submitted it. /// If the current final answer is wrong, the account should be whoever paid for arbitration. /// However, the answerer stipulations are not enforced by the contract. /// @param question_id The ID of the question /// @param answer The answer, encoded into bytes32 /// @param answerer The account credited with this answer for the purpose of bond claims function submitAnswerByArbitrator(bytes32 question_id, bytes32 answer, address answerer) onlyArbitrator(question_id) statePendingArbitration(question_id) bondMustBeZero external { require(answerer != NULL_ADDRESS); LogFinalize(question_id, answer); questions[question_id].is_pending_arbitration = false; _addAnswerToHistory(question_id, answer, answerer, 0, false); _updateCurrentAnswer(question_id, answer, 0); } /// @notice Report whether the answer to the specified question is finalized /// @param question_id The ID of the question /// @return Return true if finalized function isFinalized(bytes32 question_id) constant public returns (bool) { uint32 finalize_ts = questions[question_id].finalize_ts; return ( !questions[question_id].is_pending_arbitration && (finalize_ts > UNANSWERED) && (finalize_ts <= uint32(now)) ); } /// @notice Return the final answer to the specified question, or revert if there isn't one /// @param question_id The ID of the question /// @return The answer formatted as a bytes32 function getFinalAnswer(bytes32 question_id) stateFinalized(question_id) external constant returns (bytes32) { return questions[question_id].best_answer; } /// @notice Return the final answer to the specified question, provided it matches the specified criteria. /// @dev Reverts if the question is not finalized, or if it does not match the specified criteria. /// @param question_id The ID of the question /// @param content_hash The hash of the question content (template ID + opening time + question parameter string) /// @param arbitrator The arbitrator chosen for the question (regardless of whether they are asked to arbitrate) /// @param min_timeout The timeout set in the initial question settings must be this high or higher /// @param min_bond The bond sent with the final answer must be this high or higher /// @return The answer formatted as a bytes32 function getFinalAnswerIfMatches( bytes32 question_id, bytes32 content_hash, address arbitrator, uint32 min_timeout, uint256 min_bond ) stateFinalized(question_id) external constant returns (bytes32) { require(content_hash == questions[question_id].content_hash); require(arbitrator == questions[question_id].arbitrator); require(min_timeout <= questions[question_id].timeout); require(min_bond <= questions[question_id].bond); return questions[question_id].best_answer; } /// @notice Assigns the winnings (bounty and bonds) to everyone who gave the accepted answer /// Caller must provide the answer history, in reverse order /// @dev Works up the chain and assign bonds to the person who gave the right answer /// If someone gave the winning answer earlier, they must get paid from the higher bond /// That means we can't pay out the bond added at n until we have looked at n-1 /// The first answer is authenticated by checking against the stored history_hash. /// One of the inputs to history_hash is the history_hash before it, so we use that to authenticate the next entry, etc /// Once we get to a null hash we'll know we're done and there are no more answers. /// Usually you would call the whole thing in a single transaction, but if not then the data is persisted to pick up later. /// @param question_id The ID of the question /// @param history_hashes Second-last-to-first, the hash of each history entry. (Final one should be empty). /// @param addrs Last-to-first, the address of each answerer or commitment sender /// @param bonds Last-to-first, the bond supplied with each answer or commitment /// @param answers Last-to-first, each answer supplied, or commitment ID if the answer was supplied with commit->reveal function claimWinnings( bytes32 question_id, bytes32[] history_hashes, address[] addrs, uint256[] bonds, bytes32[] answers ) stateFinalized(question_id) public { require(history_hashes.length > 0); // These are only set if we split our claim over multiple transactions. address payee = question_claims[question_id].payee; uint256 last_bond = question_claims[question_id].last_bond; uint256 queued_funds = question_claims[question_id].queued_funds; // Starts as the hash of the final answer submitted. It'll be cleared when we're done. // If we're splitting the claim over multiple transactions, it'll be the hash where we left off last time bytes32 last_history_hash = questions[question_id].history_hash; bytes32 best_answer = questions[question_id].best_answer; uint256 i; for (i = 0; i < history_hashes.length; i++) { // Check input against the history hash, and see which of 2 possible values of is_commitment fits. bool is_commitment = _verifyHistoryInputOrRevert(last_history_hash, history_hashes[i], answers[i], bonds[i], addrs[i]); queued_funds = queued_funds.add(last_bond); (queued_funds, payee) = _processHistoryItem( question_id, best_answer, queued_funds, payee, addrs[i], bonds[i], answers[i], is_commitment); // Line the bond up for next time, when it will be added to somebody's queued_funds last_bond = bonds[i]; last_history_hash = history_hashes[i]; } if (last_history_hash != NULL_HASH) { // We haven't yet got to the null hash (1st answer), ie the caller didn't supply the full answer chain. // Persist the details so we can pick up later where we left off later. // If we know who to pay we can go ahead and pay them out, only keeping back last_bond // (We always know who to pay unless all we saw were unrevealed commits) if (payee != NULL_ADDRESS) { _payPayee(question_id, payee, queued_funds); queued_funds = 0; } question_claims[question_id].payee = payee; question_claims[question_id].last_bond = last_bond; question_claims[question_id].queued_funds = queued_funds; } else { // There is nothing left below us so the payee can keep what remains _payPayee(question_id, payee, queued_funds.add(last_bond)); delete question_claims[question_id]; } questions[question_id].history_hash = last_history_hash; } function _payPayee(bytes32 question_id, address payee, uint256 value) internal { balanceOf[payee] = balanceOf[payee].add(value); LogClaim(question_id, payee, value); } function _verifyHistoryInputOrRevert( bytes32 last_history_hash, bytes32 history_hash, bytes32 answer, uint256 bond, address addr ) internal pure returns (bool) { if (last_history_hash == keccak256(history_hash, answer, bond, addr, true) ) { return true; } if (last_history_hash == keccak256(history_hash, answer, bond, addr, false) ) { return false; } revert(); } function _processHistoryItem( bytes32 question_id, bytes32 best_answer, uint256 queued_funds, address payee, address addr, uint256 bond, bytes32 answer, bool is_commitment ) internal returns (uint256, address) { // For commit-and-reveal, the answer history holds the commitment ID instead of the answer. // We look at the referenced commitment ID and switch in the actual answer. if (is_commitment) { bytes32 commitment_id = answer; // If it's a commit but it hasn't been revealed, it will always be considered wrong. if (!commitments[commitment_id].is_revealed) { delete commitments[commitment_id]; return (queued_funds, payee); } else { answer = commitments[commitment_id].revealed_answer; delete commitments[commitment_id]; } } if (answer == best_answer) { if (payee == NULL_ADDRESS) { // The entry is for the first payee we come to, ie the winner. // They get the question bounty. payee = addr; queued_funds = queued_funds.add(questions[question_id].bounty); questions[question_id].bounty = 0; } else if (addr != payee) { // Answerer has changed, ie we found someone lower down who needs to be paid // The lower answerer will take over receiving bonds from higher answerer. // They should also be paid the takeover fee, which is set at a rate equivalent to their bond. // (This is our arbitrary rule, to give consistent right-answerers a defence against high-rollers.) // There should be enough for the fee, but if not, take what we have. // There's an edge case involving weird arbitrator behaviour where we may be short. uint256 answer_takeover_fee = (queued_funds >= bond) ? bond : queued_funds; // Settle up with the old (higher-bonded) payee _payPayee(question_id, payee, queued_funds.sub(answer_takeover_fee)); // Now start queued_funds again for the new (lower-bonded) payee payee = addr; queued_funds = answer_takeover_fee; } } return (queued_funds, payee); } /// @notice Convenience function to assign bounties/bonds for multiple questions in one go, then withdraw all your funds. /// Caller must provide the answer history for each question, in reverse order /// @dev Can be called by anyone to assign bonds/bounties, but funds are only withdrawn for the user making the call. /// @param question_ids The IDs of the questions you want to claim for /// @param lengths The number of history entries you will supply for each question ID /// @param hist_hashes In a single list for all supplied questions, the hash of each history entry. /// @param addrs In a single list for all supplied questions, the address of each answerer or commitment sender /// @param bonds In a single list for all supplied questions, the bond supplied with each answer or commitment /// @param answers In a single list for all supplied questions, each answer supplied, or commitment ID function claimMultipleAndWithdrawBalance( bytes32[] question_ids, uint256[] lengths, bytes32[] hist_hashes, address[] addrs, uint256[] bonds, bytes32[] answers ) stateAny() // The finalization checks are done in the claimWinnings function public { uint256 qi; uint256 i; for (qi = 0; qi < question_ids.length; qi++) { bytes32 qid = question_ids[qi]; uint256 ln = lengths[qi]; bytes32[] memory hh = new bytes32[](ln); address[] memory ad = new address[](ln); uint256[] memory bo = new uint256[](ln); bytes32[] memory an = new bytes32[](ln); uint256 j; for (j = 0; j < ln; j++) { hh[j] = hist_hashes[i]; ad[j] = addrs[i]; bo[j] = bonds[i]; an[j] = answers[i]; i++; } claimWinnings(qid, hh, ad, bo, an); } withdraw(); } } contract Arbitrator is Owned { RealityCheck public realitycheck; mapping(bytes32 => uint256) public arbitration_bounties; uint256 dispute_fee; mapping(bytes32 => uint256) custom_dispute_fees; event LogRequestArbitration( bytes32 indexed question_id, uint256 fee_paid, address requester, uint256 remaining ); event LogSetRealityCheck( address realitycheck ); event LogSetQuestionFee( uint256 fee ); event LogSetDisputeFee( uint256 fee ); event LogSetCustomDisputeFee( bytes32 indexed question_id, uint256 fee ); /// @notice Constructor. Sets the deploying address as owner. function Arbitrator() public { owner = msg.sender; } /// @notice Set the Reality Check contract address /// @param addr The address of the Reality Check contract function setRealityCheck(address addr) onlyOwner public { realitycheck = RealityCheck(addr); LogSetRealityCheck(addr); } /// @notice Set the default fee /// @param fee The default fee amount function setDisputeFee(uint256 fee) onlyOwner public { dispute_fee = fee; LogSetDisputeFee(fee); } /// @notice Set a custom fee for this particular question /// @param question_id The question in question /// @param fee The fee amount function setCustomDisputeFee(bytes32 question_id, uint256 fee) onlyOwner public { custom_dispute_fees[question_id] = fee; LogSetCustomDisputeFee(question_id, fee); } /// @notice Return the dispute fee for the specified question. 0 indicates that we won't arbitrate it. /// @param question_id The question in question /// @dev Uses a general default, but can be over-ridden on a question-by-question basis. function getDisputeFee(bytes32 question_id) public constant returns (uint256) { return (custom_dispute_fees[question_id] > 0) ? custom_dispute_fees[question_id] : dispute_fee; } /// @notice Set a fee for asking a question with us as the arbitrator /// @param fee The fee amount /// @dev Default is no fee. Unlike the dispute fee, 0 is an acceptable setting. /// You could set an impossibly high fee if you want to prevent us being used as arbitrator unless we submit the question. /// (Submitting the question ourselves is not implemented here.) /// This fee can be used as a revenue source, an anti-spam measure, or both. function setQuestionFee(uint256 fee) onlyOwner public { realitycheck.setQuestionFee(fee); LogSetQuestionFee(fee); } /// @notice Submit the arbitrator's answer to a question. /// @param question_id The question in question /// @param answer The answer /// @param answerer The answerer. If arbitration changed the answer, it should be the payer. If not, the old answerer. function submitAnswerByArbitrator(bytes32 question_id, bytes32 answer, address answerer) onlyOwner public { delete arbitration_bounties[question_id]; realitycheck.submitAnswerByArbitrator(question_id, answer, answerer); } /// @notice Request arbitration, freezing the question until we send submitAnswerByArbitrator /// @dev The bounty can be paid only in part, in which case the last person to pay will be considered the payer /// Will trigger an error if the notification fails, eg because the question has already been finalized /// @param question_id The question in question /// @param max_previous If specified, reverts if a bond higher than this was submitted after you sent your transaction. function requestArbitration(bytes32 question_id, uint256 max_previous) external payable returns (bool) { uint256 arbitration_fee = getDisputeFee(question_id); require(arbitration_fee > 0); arbitration_bounties[question_id] += msg.value; uint256 paid = arbitration_bounties[question_id]; if (paid >= arbitration_fee) { realitycheck.notifyOfArbitrationRequest(question_id, msg.sender, max_previous); LogRequestArbitration(question_id, msg.value, msg.sender, 0); return true; } else { require(!realitycheck.isFinalized(question_id)); LogRequestArbitration(question_id, msg.value, msg.sender, arbitration_fee - paid); return false; } } /// @notice Withdraw any accumulated fees to the specified address /// @param addr The address to which the balance should be sent function withdraw(address addr) onlyOwner public { addr.transfer(this.balance); } function() public payable { } /// @notice Withdraw any accumulated question fees from the specified address into this contract /// @dev Funds can then be liberated from this contract with our withdraw() function function callWithdraw() onlyOwner public { realitycheck.withdraw(); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[],"name":"realitycheck","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fee","type":"uint256"}],"name":"setDisputeFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"question_id","type":"bytes32"},{"name":"fee","type":"uint256"}],"name":"setCustomDisputeFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fee","type":"uint256"}],"name":"setQuestionFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"setRealityCheck","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"arbitration_bounties","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"question_id","type":"bytes32"}],"name":"getDisputeFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"question_id","type":"bytes32"},{"name":"max_previous","type":"uint256"}],"name":"requestArbitration","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"callWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"question_id","type":"bytes32"},{"name":"answer","type":"bytes32"},{"name":"answerer","type":"address"}],"name":"submitAnswerByArbitrator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"question_id","type":"bytes32"},{"indexed":false,"name":"fee_paid","type":"uint256"},{"indexed":false,"name":"requester","type":"address"},{"indexed":false,"name":"remaining","type":"uint256"}],"name":"LogRequestArbitration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"realitycheck","type":"address"}],"name":"LogSetRealityCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fee","type":"uint256"}],"name":"LogSetQuestionFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fee","type":"uint256"}],"name":"LogSetDisputeFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"question_id","type":"bytes32"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"LogSetCustomDisputeFee","type":"event"}]
Contract Creation Code
6060604052341561000f57600080fd5b60008054600160a060020a033316600160a060020a03199182168117909116179055610844806100406000396000f3006060604052600436106100ab5763ffffffff60e060020a6000350416630c2a48e281146100ad57806317299c04146100dc5780634381a07b146100f25780634df6ca2a1461010b57806351cff8d9146101215780637003433a146101405780638da5cb5b1461015f578063a20dd43b14610172578063a22352e21461019a578063a829c3d1146101b0578063dad901be146101d2578063f2fde38b146101e5578063fe92049d14610204575b005b34156100b857600080fd5b6100c0610229565b604051600160a060020a03909116815260200160405180910390f35b34156100e757600080fd5b6100ab600435610238565b34156100fd57600080fd5b6100ab60043560243561028e565b341561011657600080fd5b6100ab6004356102f5565b341561012c57600080fd5b6100ab600160a060020a03600435166103a2565b341561014b57600080fd5b6100ab600160a060020a03600435166103fd565b341561016a57600080fd5b6100c0610480565b341561017d57600080fd5b61018860043561048f565b60405190815260200160405180910390f35b34156101a557600080fd5b6101886004356104a1565b6101be6004356024356104d5565b604051901515815260200160405180910390f35b34156101dd57600080fd5b6100ab6106b4565b34156101f057600080fd5b6100ab600160a060020a0360043516610724565b341561020f57600080fd5b6100ab600435602435600160a060020a036044351661076e565b600154600160a060020a031681565b60005433600160a060020a0390811691161461025357600080fd5b60038190557fbc1292d8ca346c1397b1176ce2935afd34c4365fece415b14e3a9242eae388f58160405190815260200160405180910390a150565b60005433600160a060020a039081169116146102a957600080fd5b6000828152600460205260409081902082905582907fe4887440991624b147d2129ab0befa8c1df4cff87b22513c8eea7cb16ed2aaf29083905190815260200160405180910390a25050565b60005433600160a060020a0390811691161461031057600080fd5b600154600160a060020a0316634df6ca2a8260405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b151561035857600080fd5b6102c65a03f1151561036957600080fd5b5050507f173ec7037500587e8ac3402cac8426c5c2bac605eabd93f790422e621633d7118160405190815260200160405180910390a150565b60005433600160a060020a039081169116146103bd57600080fd5b80600160a060020a03166108fc30600160a060020a0316319081150290604051600060405180830381858888f1935050505015156103fa57600080fd5b50565b60005433600160a060020a0390811691161461041857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557ffeeb7f05475883d926f248a427675698eff53e2a93fade3a9e902d0e59cf380381604051600160a060020a03909116815260200160405180910390a150565b600054600160a060020a031681565b60026020526000908152604090205481565b6000818152600460205260408120548190116104bf576003546104cf565b6000828152600460205260409020545b92915050565b60008060006104e3856104a1565b9150600082116104f257600080fd5b50600084815260026020526040902080543401908190558181106105df57600154600160a060020a031663f6a94ecb86338760405160e060020a63ffffffff86160281526004810193909352600160a060020a0390911660248301526044820152606401600060405180830381600087803b151561056f57600080fd5b6102c65a03f1151561058057600080fd5b508691507fdf8a830581aa05b0b824a0c184007c33a1ad9100a41751c9ded9f2b4fefb16ba905034336000604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a2600192506106ac565b600154600160a060020a0316637f8d429e8660006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561063057600080fd5b6102c65a03f1151561064157600080fd5b505050604051805115905061065557600080fd5b847fdf8a830581aa05b0b824a0c184007c33a1ad9100a41751c9ded9f2b4fefb16ba3433848603604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a2600092505b505092915050565b60005433600160a060020a039081169116146106cf57600080fd5b600154600160a060020a0316633ccfd60b6040518163ffffffff1660e060020a028152600401600060405180830381600087803b151561070e57600080fd5b6102c65a03f1151561071f57600080fd5b505050565b60005433600160a060020a0390811691161461073f57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60005433600160a060020a0390811691161461078957600080fd5b60008381526002602052604080822091909155600154600160a060020a03169063fe92049d908590859085905160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b15156107ff57600080fd5b6102c65a03f1151561081057600080fd5b5050505050505600a165627a7a7230582050fc45fc126aa9a60eeb5a564c737780602944a3da92d0c38eb4beeac65e54490029
Deployed Bytecode
0x6060604052600436106100ab5763ffffffff60e060020a6000350416630c2a48e281146100ad57806317299c04146100dc5780634381a07b146100f25780634df6ca2a1461010b57806351cff8d9146101215780637003433a146101405780638da5cb5b1461015f578063a20dd43b14610172578063a22352e21461019a578063a829c3d1146101b0578063dad901be146101d2578063f2fde38b146101e5578063fe92049d14610204575b005b34156100b857600080fd5b6100c0610229565b604051600160a060020a03909116815260200160405180910390f35b34156100e757600080fd5b6100ab600435610238565b34156100fd57600080fd5b6100ab60043560243561028e565b341561011657600080fd5b6100ab6004356102f5565b341561012c57600080fd5b6100ab600160a060020a03600435166103a2565b341561014b57600080fd5b6100ab600160a060020a03600435166103fd565b341561016a57600080fd5b6100c0610480565b341561017d57600080fd5b61018860043561048f565b60405190815260200160405180910390f35b34156101a557600080fd5b6101886004356104a1565b6101be6004356024356104d5565b604051901515815260200160405180910390f35b34156101dd57600080fd5b6100ab6106b4565b34156101f057600080fd5b6100ab600160a060020a0360043516610724565b341561020f57600080fd5b6100ab600435602435600160a060020a036044351661076e565b600154600160a060020a031681565b60005433600160a060020a0390811691161461025357600080fd5b60038190557fbc1292d8ca346c1397b1176ce2935afd34c4365fece415b14e3a9242eae388f58160405190815260200160405180910390a150565b60005433600160a060020a039081169116146102a957600080fd5b6000828152600460205260409081902082905582907fe4887440991624b147d2129ab0befa8c1df4cff87b22513c8eea7cb16ed2aaf29083905190815260200160405180910390a25050565b60005433600160a060020a0390811691161461031057600080fd5b600154600160a060020a0316634df6ca2a8260405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b151561035857600080fd5b6102c65a03f1151561036957600080fd5b5050507f173ec7037500587e8ac3402cac8426c5c2bac605eabd93f790422e621633d7118160405190815260200160405180910390a150565b60005433600160a060020a039081169116146103bd57600080fd5b80600160a060020a03166108fc30600160a060020a0316319081150290604051600060405180830381858888f1935050505015156103fa57600080fd5b50565b60005433600160a060020a0390811691161461041857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557ffeeb7f05475883d926f248a427675698eff53e2a93fade3a9e902d0e59cf380381604051600160a060020a03909116815260200160405180910390a150565b600054600160a060020a031681565b60026020526000908152604090205481565b6000818152600460205260408120548190116104bf576003546104cf565b6000828152600460205260409020545b92915050565b60008060006104e3856104a1565b9150600082116104f257600080fd5b50600084815260026020526040902080543401908190558181106105df57600154600160a060020a031663f6a94ecb86338760405160e060020a63ffffffff86160281526004810193909352600160a060020a0390911660248301526044820152606401600060405180830381600087803b151561056f57600080fd5b6102c65a03f1151561058057600080fd5b508691507fdf8a830581aa05b0b824a0c184007c33a1ad9100a41751c9ded9f2b4fefb16ba905034336000604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a2600192506106ac565b600154600160a060020a0316637f8d429e8660006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561063057600080fd5b6102c65a03f1151561064157600080fd5b505050604051805115905061065557600080fd5b847fdf8a830581aa05b0b824a0c184007c33a1ad9100a41751c9ded9f2b4fefb16ba3433848603604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a2600092505b505092915050565b60005433600160a060020a039081169116146106cf57600080fd5b600154600160a060020a0316633ccfd60b6040518163ffffffff1660e060020a028152600401600060405180830381600087803b151561070e57600080fd5b6102c65a03f1151561071f57600080fd5b505050565b60005433600160a060020a0390811691161461073f57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60005433600160a060020a0390811691161461078957600080fd5b60008381526002602052604080822091909155600154600160a060020a03169063fe92049d908590859085905160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b15156107ff57600080fd5b6102c65a03f1151561081057600080fd5b5050505050505600a165627a7a7230582050fc45fc126aa9a60eeb5a564c737780602944a3da92d0c38eb4beeac65e54490029
Swarm Source
bzzr://50fc45fc126aa9a60eeb5a564c737780602944a3da92d0c38eb4beeac65e5449
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,664.96 | 0.2 | $532.99 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.