Contract
0xdcbe79f74c98368141798ea0b7b979b9ba54b026
2
Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
PredictionMarket
Compiler Version
v0.6.2+commit.bacdbe57
Contract Source Code (Solidity)
/** *Submitted for verification at moonriver.moonscan.io on 2021-11-03 */ // File: contracts/RealitioERC20.sol /** *Submitted for verification at Etherscan.io on 2021-06-09 */ pragma solidity >0.4.24; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } pragma solidity >0.4.24; /** * @title ReailtioSafeMath256 * @dev Math operations with safety checks that throw on error */ library RealitioSafeMath256 { 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; } } pragma solidity >0.4.24; /** * @title RealitioSafeMath32 * @dev Math operations with safety checks that throw on error * @dev Copy of SafeMath but for uint32 instead of uint256 * @dev Deleted functions we don't use */ library RealitioSafeMath32 { function add(uint32 a, uint32 b) internal pure returns (uint32) { uint32 c = a + b; assert(c >= a); return c; } } pragma solidity >0.4.18; contract BalanceHolder { IERC20 public token; mapping(address => uint256) public balanceOf; event LogWithdraw( address indexed user, uint256 amount ); function withdraw() public { uint256 bal = balanceOf[msg.sender]; balanceOf[msg.sender] = 0; require(token.transfer(msg.sender, bal)); emit LogWithdraw(msg.sender, bal); } } pragma solidity >0.4.24; contract RealitioERC20 is BalanceHolder { using RealitioSafeMath256 for uint256; using RealitioSafeMath32 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) public 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, "msg.sender must be arbitrator"); _; } modifier stateAny() { _; } modifier stateNotCreated(bytes32 question_id) { require(questions[question_id].timeout == 0, "question must not exist"); _; } modifier stateOpen(bytes32 question_id) { require(questions[question_id].timeout > 0, "question must exist"); require(!questions[question_id].is_pending_arbitration, "question must not be pending arbitration"); uint32 finalize_ts = questions[question_id].finalize_ts; require(finalize_ts == UNANSWERED || finalize_ts > uint32(now), "finalization deadline must not have passed"); uint32 opening_ts = questions[question_id].opening_ts; require(opening_ts == 0 || opening_ts <= uint32(now), "opening date must have passed"); _; } modifier statePendingArbitration(bytes32 question_id) { require(questions[question_id].is_pending_arbitration, "question must be pending arbitration"); _; } modifier stateOpenOrPendingArbitration(bytes32 question_id) { require(questions[question_id].timeout > 0, "question must exist"); uint32 finalize_ts = questions[question_id].finalize_ts; require(finalize_ts == UNANSWERED || finalize_ts > uint32(now), "finalization dealine must not have passed"); uint32 opening_ts = questions[question_id].opening_ts; require(opening_ts == 0 || opening_ts <= uint32(now), "opening date must have passed"); _; } modifier stateFinalized(bytes32 question_id) { require(isFinalized(question_id), "question must be finalized"); _; } modifier bondMustDouble(bytes32 question_id, uint256 tokens) { require(tokens > 0, "bond must be positive"); require(tokens >= (questions[question_id].bond.mul(2)), "bond must be double at least previous bond"); _; } modifier previousBondMustNotBeatMaxPrevious(bytes32 question_id, uint256 max_previous) { if (max_previous > 0) { require(questions[question_id].bond <= max_previous, "bond must exceed max_previous"); } _; } function setToken(IERC20 _token) public { require(token == IERC20(0x0), "Token can only be initialized once"); token = _token; } /// @notice Constructor, sets up some initial templates /// @dev Creates some generalized templates for different question types used in the DApp. constructor() public { createTemplate('{"title": "%s", "type": "bool", "category": "%s", "lang": "%s"}'); createTemplate('{"title": "%s", "type": "uint", "decimals": 18, "category": "%s", "lang": "%s"}'); createTemplate('{"title": "%s", "type": "single-select", "outcomes": [%s], "category": "%s", "lang": "%s"}'); createTemplate('{"title": "%s", "type": "multiple-select", "outcomes": [%s], "category": "%s", "lang": "%s"}'); createTemplate('{"title": "%s", "type": "datetime", "category": "%s", "lang": "%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; emit 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 memory content) stateAny() public returns (uint256) { uint256 id = nextTemplateID; templates[id] = block.number; template_hashes[id] = keccak256(abi.encodePacked(content)); emit 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 memory content, string memory question, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce ) // stateNotCreated is enforced by the internal _askQuestion public returns (bytes32) { uint256 template_id = createTemplate(content); return askQuestion(template_id, question, arbitrator, timeout, opening_ts, nonce); } /// @notice Ask a new question without a bounty and return the ID /// @dev Template data is only stored in the event logs, but its block number is kept in contract storage. /// @dev Calling without the token param will only work if there is no arbitrator-set question fee. /// @dev This has the same function signature as askQuestion() in the non-ERC20 version, which is optionally payable. /// @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 memory question, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce) // stateNotCreated is enforced by the internal _askQuestion public returns (bytes32) { require(templates[template_id] > 0, "template must exist"); bytes32 content_hash = keccak256(abi.encodePacked(template_id, opening_ts, question)); bytes32 question_id = keccak256(abi.encodePacked(content_hash, arbitrator, timeout, msg.sender, nonce)); _askQuestion(question_id, content_hash, arbitrator, timeout, opening_ts, 0); emit LogNewQuestion(question_id, msg.sender, template_id, question, content_hash, arbitrator, timeout, opening_ts, nonce, now); return question_id; } /// @notice Ask a new question with a bounty 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. /// @param tokens The combined initial question bounty and question fee /// @return The ID of the newly-created question, created deterministically. function askQuestionERC20(uint256 template_id, string memory question, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 tokens) // stateNotCreated is enforced by the internal _askQuestion public returns (bytes32) { _deductTokensOrRevert(tokens); require(templates[template_id] > 0, "template must exist"); bytes32 content_hash = keccak256(abi.encodePacked(template_id, opening_ts, question)); bytes32 question_id = keccak256(abi.encodePacked(content_hash, arbitrator, timeout, msg.sender, nonce)); _askQuestion(question_id, content_hash, arbitrator, timeout, opening_ts, tokens); emit LogNewQuestion(question_id, msg.sender, template_id, question, content_hash, arbitrator, timeout, opening_ts, nonce, now); return question_id; } function _deductTokensOrRevert(uint256 tokens) internal { if (tokens == 0) { return; } uint256 bal = balanceOf[msg.sender]; // Deduct any tokens you have in your internal balance first if (bal > 0) { if (bal >= tokens) { balanceOf[msg.sender] = bal.sub(tokens); return; } else { tokens = tokens.sub(bal); balanceOf[msg.sender] = 0; } } // Now we need to charge the rest from require(token.transferFrom(msg.sender, address(this), tokens), "Transfer of tokens failed, insufficient approved balance?"); return; } function _askQuestion(bytes32 question_id, bytes32 content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 tokens) stateNotCreated(question_id) internal { uint256 bounty = tokens; // A timeout of 0 makes no sense, and we will use this to check existence require(timeout > 0, "timeout must be positive"); require(timeout < 365 days, "timeout must be less than 365 days"); require(arbitrator != NULL_ADDRESS, "arbitrator must be set"); // 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, "Tokens provided must cover 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 /// @param tokens The number of tokens to fund function fundAnswerBountyERC20(bytes32 question_id, uint256 tokens) stateOpen(question_id) external { _deductTokensOrRevert(tokens); questions[question_id].bounty = questions[question_id].bounty.add(tokens); emit LogFundAnswerBounty(question_id, tokens, 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. /// @param tokens The amount of tokens to submit function submitAnswerERC20(bytes32 question_id, bytes32 answer, uint256 max_previous, uint256 tokens) stateOpen(question_id) bondMustDouble(question_id, tokens) previousBondMustNotBeatMaxPrevious(question_id, max_previous) external { _deductTokensOrRevert(tokens); _addAnswerToHistory(question_id, answer, msg.sender, tokens, false); _updateCurrentAnswer(question_id, answer, questions[question_id].timeout); } // @notice Verify and store a commitment, including an appropriate timeout // @param question_id The ID of the question to store // @param commitment The ID of the commitment function _storeCommitment(bytes32 question_id, bytes32 commitment_id) internal { require(commitments[commitment_id].reveal_ts == COMMITMENT_NON_EXISTENT, "commitment must not already exist"); uint32 commitment_timeout = questions[question_id].timeout / COMMITMENT_TIMEOUT_RATIO; commitments[commitment_id].reveal_ts = uint32(now).add(commitment_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. /// @param tokens Number of tokens sent /// @dev Specifying the answerer is useful if you want to delegate the commit-and-reveal to a third-party. function submitAnswerCommitmentERC20(bytes32 question_id, bytes32 answer_hash, uint256 max_previous, address _answerer, uint256 tokens) stateOpen(question_id) bondMustDouble(question_id, tokens) previousBondMustNotBeatMaxPrevious(question_id, max_previous) external { _deductTokensOrRevert(tokens); bytes32 commitment_id = keccak256(abi.encodePacked(question_id, answer_hash, tokens)); address answerer = (_answerer == NULL_ADDRESS) ? msg.sender : _answerer; _storeCommitment(question_id, commitment_id); _addAnswerToHistory(question_id, commitment_id, answerer, tokens, 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(abi.encodePacked(answer, nonce)); bytes32 commitment_id = keccak256(abi.encodePacked(question_id, answer_hash, bond)); require(!commitments[commitment_id].is_revealed, "commitment must not have been revealed yet"); 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); } emit 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(abi.encodePacked(questions[question_id].history_hash, answer_or_commitment_id, bond, answerer, is_commitment)); // Update the current bond level, if there's a bond (ie anything except arbitration) if (bond > 0) { questions[question_id].bond = bond; } questions[question_id].history_hash = new_history_hash; emit 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 { require(questions[question_id].bond > 0, "Question must already have an answer when arbitration is requested"); questions[question_id].is_pending_arbitration = true; emit 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) external { require(answerer != NULL_ADDRESS, "answerer must be provided"); emit 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) view 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 (Deprecated) 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 view returns (bytes32) { return questions[question_id].best_answer; } /// @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 resultFor(bytes32 question_id) stateFinalized(question_id) external view 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 view returns (bytes32) { require(content_hash == questions[question_id].content_hash, "content hash must match"); require(arbitrator == questions[question_id].arbitrator, "arbitrator must match"); require(min_timeout <= questions[question_id].timeout, "timeout must be long enough"); require(min_bond <= questions[question_id].bond, "bond must be high enough"); 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[] memory history_hashes, address[] memory addrs, uint256[] memory bonds, bytes32[] memory answers ) stateFinalized(question_id) public { require(history_hashes.length > 0, "at least one history hash entry must be provided"); // 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); emit 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(abi.encodePacked(history_hash, answer, bond, addr, true)) ) { return true; } if (last_history_hash == keccak256(abi.encodePacked(history_hash, answer, bond, addr, false)) ) { return false; } revert("History input provided did not match the expected hash"); } 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[] memory question_ids, uint256[] memory lengths, bytes32[] memory hist_hashes, address[] memory addrs, uint256[] memory bonds, bytes32[] memory 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(); } /// @notice Returns the questions's content hash, identifying the question content /// @param question_id The ID of the question function getContentHash(bytes32 question_id) public view returns(bytes32) { return questions[question_id].content_hash; } /// @notice Returns the arbitrator address for the question /// @param question_id The ID of the question function getArbitrator(bytes32 question_id) public view returns(address) { return questions[question_id].arbitrator; } /// @notice Returns the timestamp when the question can first be answered /// @param question_id The ID of the question function getOpeningTS(bytes32 question_id) public view returns(uint32) { return questions[question_id].opening_ts; } /// @notice Returns the timeout in seconds used after each answer /// @param question_id The ID of the question function getTimeout(bytes32 question_id) public view returns(uint32) { return questions[question_id].timeout; } /// @notice Returns the timestamp at which the question will be/was finalized /// @param question_id The ID of the question function getFinalizeTS(bytes32 question_id) public view returns(uint32) { return questions[question_id].finalize_ts; } /// @notice Returns whether the question is pending arbitration /// @param question_id The ID of the question function isPendingArbitration(bytes32 question_id) public view returns(bool) { return questions[question_id].is_pending_arbitration; } /// @notice Returns the current total unclaimed bounty /// @dev Set back to zero once the bounty has been claimed /// @param question_id The ID of the question function getBounty(bytes32 question_id) public view returns(uint256) { return questions[question_id].bounty; } /// @notice Returns the current best answer /// @param question_id The ID of the question function getBestAnswer(bytes32 question_id) public view returns(bytes32) { return questions[question_id].best_answer; } /// @notice Returns the history hash of the question /// @param question_id The ID of the question /// @dev Updated on each answer, then rewound as each is claimed function getHistoryHash(bytes32 question_id) public view returns(bytes32) { return questions[question_id].history_hash; } /// @notice Returns the highest bond posted so far for a question /// @param question_id The ID of the question function getBond(bytes32 question_id) public view returns(uint256) { return questions[question_id].bond; } } // File: @openzeppelin/contracts/math/SafeMath.sol // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } // File: contracts/PredictionMarket.sol pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; // openzeppelin imports library CeilDiv { // calculates ceil(x/y) function ceildiv(uint256 x, uint256 y) internal pure returns (uint256) { if (x > 0) return ((x - 1) / y) + 1; return x / y; } } /// @title Market Contract Factory contract PredictionMarket { using SafeMath for uint256; using CeilDiv for uint256; // ------ Events ------ event MarketCreated(address indexed user, uint256 indexed marketId, uint256 outcomes, string question, string image); event MarketActionTx( address indexed user, MarketAction indexed action, uint256 indexed marketId, uint256 outcomeId, uint256 shares, uint256 value, uint256 timestamp ); event MarketOutcomePrice(uint256 indexed marketId, uint256 indexed outcomeId, uint256 value, uint256 timestamp); event MarketLiquidity( uint256 indexed marketId, uint256 value, // total liquidity uint256 price, // value of one liquidity share; max: 1 (50-50 situation) uint256 timestamp ); event MarketResolved(address indexed user, uint256 indexed marketId, uint256 outcomeId, uint256 timestamp); // ------ Events End ------ uint256 public constant MAX_UINT_256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; uint256 public constant ONE = 10**18; enum MarketState { open, closed, resolved } enum MarketAction { buy, sell, addLiquidity, removeLiquidity, claimWinnings, claimLiquidity, claimFees, claimVoided } struct Market { // market details uint256 closesAtTimestamp; uint256 balance; // total stake uint256 liquidity; // stake held uint256 sharesAvailable; // shares held (all outcomes) mapping(address => uint256) liquidityShares; mapping(address => bool) liquidityClaims; // wether user has claimed liquidity earnings MarketState state; // resolution variables MarketResolution resolution; // fees MarketFees fees; // market outcomes uint256[] outcomeIds; mapping(uint256 => MarketOutcome) outcomes; } struct MarketFees { uint256 value; // fee % taken from every transaction uint256 poolWeight; // internal var used to ensure pro-rate fee distribution mapping(address => uint256) claimed; } struct MarketResolution { bool resolved; uint256 outcomeId; bytes32 questionId; // realitio questionId } struct MarketOutcome { uint256 marketId; uint256 id; Shares shares; } struct Shares { uint256 total; // number of shares uint256 available; // available shares mapping(address => uint256) holders; mapping(address => bool) claims; // wether user has claimed winnings mapping(address => bool) voidedClaims; // wether user has claimed voided market shares } uint256[] marketIds; mapping(uint256 => Market) markets; uint256 public marketIndex; // governance uint256 public fee; // fee % taken from every transaction, can be updated by contract owner // realitio configs address public realitioAddress; uint256 public realitioTimeout; // market creation IERC20 public token; // token used for rewards / market creation uint256 public requiredBalance; // required balance for market creation // ------ Modifiers ------ modifier isMarket(uint256 marketId) { require(marketId < marketIndex); _; } modifier timeTransitions(uint256 marketId) { if (now > markets[marketId].closesAtTimestamp && markets[marketId].state == MarketState.open) { nextState(marketId); } _; } modifier atState(uint256 marketId, MarketState state) { require(markets[marketId].state == state); _; } modifier notAtState(uint256 marketId, MarketState state) { require(markets[marketId].state != state); _; } modifier transitionNext(uint256 marketId) { _; nextState(marketId); } modifier mustHoldRequiredBalance() { require(token.balanceOf(msg.sender) >= requiredBalance, "msg.sender must hold minimum erc20 balance"); _; } // ------ Modifiers End ------ /// @dev protocol is immutable and has no ownership constructor( uint256 _fee, IERC20 _token, uint256 _requiredBalance, address _realitioAddress, uint256 _realitioTimeout ) public { fee = _fee; token = _token; requiredBalance = _requiredBalance; realitioAddress = _realitioAddress; realitioTimeout = _realitioTimeout; } // ------ Core Functions ------ /// @dev Creates a market, initializes the outcome shares pool and submits a question in Realitio function createMarket( string memory question, string memory image, uint256 closesAt, address arbitrator, uint256 outcomes ) public payable mustHoldRequiredBalance() returns (uint256) { uint256 marketId = marketIndex; marketIds.push(marketId); Market storage market = markets[marketId]; require(msg.value > 0, "stake needs to be > 0"); require(closesAt >= now, "market must resolve after the current date"); require(arbitrator == address(arbitrator), "invalid arbitrator address"); // v1 - only binary markets require(outcomes == 2, "number of outcomes has to be 2"); market.closesAtTimestamp = closesAt; market.state = MarketState.open; market.fees.value = fee; // setting intial value to an integer that does not map to any outcomeId market.resolution.outcomeId = MAX_UINT_256; // creating market outcomes for (uint256 i = 0; i < outcomes; i++) { market.outcomeIds.push(i); MarketOutcome storage outcome = market.outcomes[i]; outcome.marketId = marketId; outcome.id = i; } // creating question in realitio RealitioERC20 realitio = RealitioERC20(realitioAddress); market.resolution.questionId = realitio.askQuestionERC20( 2, question, arbitrator, uint32(realitioTimeout), uint32(closesAt), 0, 0 ); addLiquidity(marketId, msg.value); // emiting initial price events emitMarketOutcomePriceEvents(marketId); emit MarketCreated(msg.sender, marketId, outcomes, question, image); // incrementing market array index marketIndex = marketIndex + 1; return marketId; } /// @dev Calculates the number of shares bought with "amount" balance function calcBuyAmount( uint256 amount, uint256 marketId, uint256 outcomeId ) public view returns (uint256) { Market storage market = markets[marketId]; uint256[] memory outcomesShares = getMarketOutcomesShares(marketId); uint256 amountMinusFees = amount.sub(amount.mul(market.fees.value) / ONE); uint256 buyTokenPoolBalance = outcomesShares[outcomeId]; uint256 endingOutcomeBalance = buyTokenPoolBalance.mul(ONE); for (uint256 i = 0; i < outcomesShares.length; i++) { if (i != outcomeId) { uint256 outcomeShares = outcomesShares[i]; endingOutcomeBalance = endingOutcomeBalance.mul(outcomeShares).ceildiv(outcomeShares.add(amountMinusFees)); } } require(endingOutcomeBalance > 0, "must have non-zero balances"); return buyTokenPoolBalance.add(amountMinusFees).sub(endingOutcomeBalance.ceildiv(ONE)); } /// @dev Calculates the number of shares needed to be sold in order to receive "amount" in balance function calcSellAmount( uint256 amount, uint256 marketId, uint256 outcomeId ) public view returns (uint256 outcomeTokenSellAmount) { Market storage market = markets[marketId]; uint256[] memory outcomesShares = getMarketOutcomesShares(marketId); uint256 amountPlusFees = amount.mul(ONE) / ONE.sub(market.fees.value); uint256 sellTokenPoolBalance = outcomesShares[outcomeId]; uint256 endingOutcomeBalance = sellTokenPoolBalance.mul(ONE); for (uint256 i = 0; i < outcomesShares.length; i++) { if (i != outcomeId) { uint256 outcomeShares = outcomesShares[i]; endingOutcomeBalance = endingOutcomeBalance.mul(outcomeShares).ceildiv(outcomeShares.sub(amountPlusFees)); } } require(endingOutcomeBalance > 0, "must have non-zero balances"); return amountPlusFees.add(endingOutcomeBalance.ceildiv(ONE)).sub(sellTokenPoolBalance); } /// @dev Buy shares of a market outcome function buy( uint256 marketId, uint256 outcomeId, uint256 minOutcomeSharesToBuy ) external payable timeTransitions(marketId) atState(marketId, MarketState.open) { Market storage market = markets[marketId]; uint256 value = msg.value; uint256 shares = calcBuyAmount(value, marketId, outcomeId); require(shares >= minOutcomeSharesToBuy, "minimum buy amount not reached"); // subtracting fee from transaction value uint256 feeAmount = value.mul(market.fees.value) / ONE; market.fees.poolWeight = market.fees.poolWeight.add(feeAmount); uint256 valueMinusFees = value.sub(feeAmount); MarketOutcome storage outcome = market.outcomes[outcomeId]; // Funding market shares with received funds addSharesToMarket(marketId, valueMinusFees); require(outcome.shares.available >= shares, "outcome shares pool balance is too low"); transferOutcomeSharesfromPool(msg.sender, marketId, outcomeId, shares); emit MarketActionTx(msg.sender, MarketAction.buy, marketId, outcomeId, shares, value, now); emitMarketOutcomePriceEvents(marketId); } /// @dev Sell shares of a market outcome function sell( uint256 marketId, uint256 outcomeId, uint256 value, uint256 maxOutcomeSharesToSell ) external payable timeTransitions(marketId) atState(marketId, MarketState.open) { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; uint256 shares = calcSellAmount(value, marketId, outcomeId); require(shares <= maxOutcomeSharesToSell, "maximum sell amount exceeded"); require(outcome.shares.holders[msg.sender] >= shares, "user does not have enough balance"); transferOutcomeSharesToPool(msg.sender, marketId, outcomeId, shares); // adding fee to transaction value uint256 feeAmount = value.mul(market.fees.value) / (ONE.sub(fee)); market.fees.poolWeight = market.fees.poolWeight.add(feeAmount); uint256 valuePlusFees = value.add(feeAmount); require(market.balance >= valuePlusFees, "market does not have enough balance"); // Rebalancing market shares removeSharesFromMarket(marketId, valuePlusFees); // Transferring funds to user msg.sender.transfer(value); emit MarketActionTx(msg.sender, MarketAction.sell, marketId, outcomeId, shares, value, now); emitMarketOutcomePriceEvents(marketId); } /// @dev Adds liquidity to a market - external function addLiquidity(uint256 marketId) external payable timeTransitions(marketId) atState(marketId, MarketState.open) { addLiquidity(marketId, msg.value); } /// @dev Private function, used by addLiquidity and CreateMarket function addLiquidity(uint256 marketId, uint256 value) private timeTransitions(marketId) atState(marketId, MarketState.open) { Market storage market = markets[marketId]; require(value > 0, "stake has to be greater than 0."); uint256 liquidityAmount; uint256[] memory outcomesShares = getMarketOutcomesShares(marketId); uint256[] memory sendBackAmounts = new uint256[](outcomesShares.length); uint256 poolWeight = 0; if (market.liquidity > 0) { // part of the liquidity is exchanged for outcome shares if market is not balanced for (uint256 i = 0; i < outcomesShares.length; i++) { uint256 outcomeShares = outcomesShares[i]; if (poolWeight < outcomeShares) poolWeight = outcomeShares; } for (uint256 i = 0; i < outcomesShares.length; i++) { uint256 remaining = value.mul(outcomesShares[i]) / poolWeight; sendBackAmounts[i] = value.sub(remaining); } liquidityAmount = value.mul(market.liquidity) / poolWeight; // re-balancing fees pool rebalanceFeesPool(marketId, liquidityAmount, MarketAction.addLiquidity); } else { // funding market with no liquidity liquidityAmount = value; } // funding market market.liquidity = market.liquidity.add(liquidityAmount); market.liquidityShares[msg.sender] = market.liquidityShares[msg.sender].add(liquidityAmount); addSharesToMarket(marketId, value); // transform sendBackAmounts to array of amounts added for (uint256 i = 0; i < sendBackAmounts.length; i++) { if (sendBackAmounts[i] > 0) { uint256 marketShares = market.sharesAvailable; uint256 outcomeShares = market.outcomes[i].shares.available; transferOutcomeSharesfromPool(msg.sender, marketId, i, sendBackAmounts[i]); emit MarketActionTx( msg.sender, MarketAction.buy, marketId, i, sendBackAmounts[i], (marketShares.sub(outcomeShares)).mul(sendBackAmounts[i]).div(market.sharesAvailable), // price * shares now ); } } uint256 liquidityPrice = getMarketLiquidityPrice(marketId); uint256 liquidityValue = liquidityPrice.mul(liquidityAmount) / ONE; emit MarketActionTx(msg.sender, MarketAction.addLiquidity, marketId, 0, liquidityAmount, liquidityValue, now); emit MarketLiquidity(marketId, market.liquidity, liquidityPrice, now); } /// @dev Removes liquidity to a market - external function removeLiquidity(uint256 marketId, uint256 shares) external payable timeTransitions(marketId) atState(marketId, MarketState.open) { Market storage market = markets[marketId]; require(market.liquidityShares[msg.sender] >= shares, "user does not have enough balance"); // claiming any pending fees claimFees(marketId); // re-balancing fees pool rebalanceFeesPool(marketId, shares, MarketAction.removeLiquidity); uint256[] memory outcomesShares = getMarketOutcomesShares(marketId); uint256[] memory sendAmounts = new uint256[](outcomesShares.length); uint256 poolWeight = MAX_UINT_256; // part of the liquidity is exchanged for outcome shares if market is not balanced for (uint256 i = 0; i < outcomesShares.length; i++) { uint256 outcomeShares = outcomesShares[i]; if (poolWeight > outcomeShares) poolWeight = outcomeShares; } uint256 liquidityAmount = shares.mul(poolWeight).div(market.liquidity); for (uint256 i = 0; i < outcomesShares.length; i++) { sendAmounts[i] = outcomesShares[i].mul(shares) / market.liquidity; sendAmounts[i] = sendAmounts[i].sub(liquidityAmount); } // removing liquidity from market removeSharesFromMarket(marketId, liquidityAmount); market.liquidity = market.liquidity.sub(shares); // removing liquidity tokens from market creator market.liquidityShares[msg.sender] = market.liquidityShares[msg.sender].sub(shares); for (uint256 i = 0; i < outcomesShares.length; i++) { if (sendAmounts[i] > 0) { uint256 marketShares = market.sharesAvailable; uint256 outcomeShares = market.outcomes[i].shares.available; transferOutcomeSharesfromPool(msg.sender, marketId, i, sendAmounts[i]); emit MarketActionTx( msg.sender, MarketAction.buy, marketId, i, sendAmounts[i], (marketShares.sub(outcomeShares)).mul(sendAmounts[i]).div(market.sharesAvailable), // price * shares now ); } } // transferring user funds from liquidity removed msg.sender.transfer(liquidityAmount); emit MarketActionTx(msg.sender, MarketAction.removeLiquidity, marketId, 0, shares, liquidityAmount, now); emit MarketLiquidity(marketId, market.liquidity, getMarketLiquidityPrice(marketId), now); } /// @dev Fetches winning outcome from Realitio and resolves the market function resolveMarketOutcome(uint256 marketId) public timeTransitions(marketId) atState(marketId, MarketState.closed) transitionNext(marketId) returns (uint256) { Market storage market = markets[marketId]; RealitioERC20 realitio = RealitioERC20(realitioAddress); // will fail if question is not finalized uint256 outcomeId = uint256(realitio.resultFor(market.resolution.questionId)); market.resolution.outcomeId = outcomeId; emit MarketResolved(msg.sender, marketId, outcomeId, now); emitMarketOutcomePriceEvents(marketId); return market.resolution.outcomeId; } /// @dev Allows holders of resolved outcome shares to claim earnings. function claimWinnings(uint256 marketId) public atState(marketId, MarketState.resolved) { Market storage market = markets[marketId]; MarketOutcome storage resolvedOutcome = market.outcomes[market.resolution.outcomeId]; require(resolvedOutcome.shares.holders[msg.sender] > 0, "user does not hold resolved outcome shares"); require(resolvedOutcome.shares.claims[msg.sender] == false, "user already claimed resolved outcome winnings"); // 1 share => price = 1 uint256 value = resolvedOutcome.shares.holders[msg.sender]; // assuring market has enough funds require(market.balance >= value, "Market does not have enough balance"); market.balance = market.balance.sub(value); resolvedOutcome.shares.claims[msg.sender] = true; emit MarketActionTx( msg.sender, MarketAction.claimWinnings, marketId, market.resolution.outcomeId, resolvedOutcome.shares.holders[msg.sender], value, now ); msg.sender.transfer(value); } /// @dev Allows holders of voided outcome shares to claim balance back. function claimVoidedOutcomeShares(uint256 marketId, uint256 outcomeId) public atState(marketId, MarketState.resolved) { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; require(outcome.shares.holders[msg.sender] > 0, "user does not hold outcome shares"); require(outcome.shares.voidedClaims[msg.sender] == false, "user already claimed outcome shares"); // voided market - shares are valued at last market price uint256 price = getMarketOutcomePrice(marketId, outcomeId); uint256 value = price.mul(outcome.shares.holders[msg.sender]).div(ONE); // assuring market has enough funds require(market.balance >= value, "Market does not have enough balance"); market.balance = market.balance.sub(value); outcome.shares.voidedClaims[msg.sender] = true; emit MarketActionTx( msg.sender, MarketAction.claimVoided, marketId, outcomeId, outcome.shares.holders[msg.sender], value, now ); msg.sender.transfer(value); } /// @dev Allows liquidity providers to claim earnings from liquidity providing. function claimLiquidity(uint256 marketId) public atState(marketId, MarketState.resolved) { Market storage market = markets[marketId]; // claiming any pending fees claimFees(marketId); require(market.liquidityShares[msg.sender] > 0, "user does not hold liquidity shares"); require(market.liquidityClaims[msg.sender] == false, "user already claimed liquidity winnings"); // value = total resolved outcome pool shares * pool share (%) uint256 liquidityPrice = getMarketLiquidityPrice(marketId); uint256 value = liquidityPrice.mul(market.liquidityShares[msg.sender]) / ONE; // assuring market has enough funds require(market.balance >= value, "Market does not have enough balance"); market.balance = market.balance.sub(value); market.liquidityClaims[msg.sender] = true; emit MarketActionTx( msg.sender, MarketAction.claimLiquidity, marketId, 0, market.liquidityShares[msg.sender], value, now ); msg.sender.transfer(value); } /// @dev Allows liquidity providers to claim their fees share from fees pool function claimFees(uint256 marketId) public payable { Market storage market = markets[marketId]; uint256 claimableFees = getUserClaimableFees(marketId, msg.sender); if (claimableFees > 0) { market.fees.claimed[msg.sender] = market.fees.claimed[msg.sender].add(claimableFees); msg.sender.transfer(claimableFees); } emit MarketActionTx( msg.sender, MarketAction.claimFees, marketId, 0, market.liquidityShares[msg.sender], claimableFees, now ); } /// @dev Rebalances the fees pool. Needed in every AddLiquidity / RemoveLiquidity call function rebalanceFeesPool( uint256 marketId, uint256 liquidityShares, MarketAction action ) private returns (uint256) { Market storage market = markets[marketId]; uint256 poolWeight = liquidityShares.mul(market.fees.poolWeight).div(market.liquidity); if (action == MarketAction.addLiquidity) { market.fees.poolWeight = market.fees.poolWeight.add(poolWeight); market.fees.claimed[msg.sender] = market.fees.claimed[msg.sender].add(poolWeight); } else { market.fees.poolWeight = market.fees.poolWeight.sub(poolWeight); market.fees.claimed[msg.sender] = market.fees.claimed[msg.sender].sub(poolWeight); } } /// @dev Transitions market to next state function nextState(uint256 marketId) private { Market storage market = markets[marketId]; market.state = MarketState(uint256(market.state) + 1); } /// @dev Emits a outcome price event for every outcome function emitMarketOutcomePriceEvents(uint256 marketId) private { Market storage market = markets[marketId]; for (uint256 i = 0; i < market.outcomeIds.length; i++) { emit MarketOutcomePrice(marketId, i, getMarketOutcomePrice(marketId, i), now); } // liquidity shares also change value emit MarketLiquidity(marketId, market.liquidity, getMarketLiquidityPrice(marketId), now); } /// @dev Adds outcome shares to shares pool function addSharesToMarket(uint256 marketId, uint256 shares) private { Market storage market = markets[marketId]; for (uint256 i = 0; i < market.outcomeIds.length; i++) { MarketOutcome storage outcome = market.outcomes[i]; outcome.shares.available = outcome.shares.available.add(shares); outcome.shares.total = outcome.shares.total.add(shares); // only adding to market total shares, the available remains market.sharesAvailable = market.sharesAvailable.add(shares); } market.balance = market.balance.add(shares); } /// @dev Removes outcome shares from shares pool function removeSharesFromMarket(uint256 marketId, uint256 shares) private { Market storage market = markets[marketId]; for (uint256 i = 0; i < market.outcomeIds.length; i++) { MarketOutcome storage outcome = market.outcomes[i]; outcome.shares.available = outcome.shares.available.sub(shares); outcome.shares.total = outcome.shares.total.sub(shares); // only subtracting from market total shares, the available remains market.sharesAvailable = market.sharesAvailable.sub(shares); } market.balance = market.balance.sub(shares); } /// @dev Transfer outcome shares from pool to user balance function transferOutcomeSharesfromPool( address user, uint256 marketId, uint256 outcomeId, uint256 shares ) private { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; // transfering shares from shares pool to user outcome.shares.holders[user] = outcome.shares.holders[user].add(shares); outcome.shares.available = outcome.shares.available.sub(shares); market.sharesAvailable = market.sharesAvailable.sub(shares); } /// @dev Transfer outcome shares from user balance back to pool function transferOutcomeSharesToPool( address user, uint256 marketId, uint256 outcomeId, uint256 shares ) private { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; // adding shares back to pool outcome.shares.holders[user] = outcome.shares.holders[user].sub(shares); outcome.shares.available = outcome.shares.available.add(shares); market.sharesAvailable = market.sharesAvailable.add(shares); } // ------ Core Functions End ------ // ------ Getters ------ function getUserMarketShares(uint256 marketId, address user) public view returns ( uint256, uint256, uint256 ) { Market storage market = markets[marketId]; return ( market.liquidityShares[user], market.outcomes[0].shares.holders[user], market.outcomes[1].shares.holders[user] ); } function getUserClaimStatus(uint256 marketId, address user) public view returns ( bool, bool, bool, bool, uint256 ) { Market storage market = markets[marketId]; // market still not resolved if (market.state != MarketState.resolved) { return (false, false, false, false, getUserClaimableFees(marketId, user)); } MarketOutcome storage outcome = market.outcomes[market.resolution.outcomeId]; return ( outcome.shares.holders[user] > 0, outcome.shares.claims[user], market.liquidityShares[user] > 0, market.liquidityClaims[user], getUserClaimableFees(marketId, user) ); } function getUserLiquidityPoolShare(uint256 marketId, address user) public view returns (uint256) { Market storage market = markets[marketId]; return market.liquidityShares[user].mul(ONE).div(market.liquidity); } function getUserClaimableFees(uint256 marketId, address user) public view returns (uint256) { Market storage market = markets[marketId]; uint256 rawAmount = market.fees.poolWeight.mul(market.liquidityShares[user]).div(market.liquidity); return rawAmount.sub(market.fees.claimed[user]); } function getMarkets() public view returns (uint256[] memory) { return marketIds; } function getMarketData(uint256 marketId) public view returns ( MarketState, uint256, uint256, uint256, uint256, int256 ) { Market storage market = markets[marketId]; return ( market.state, market.closesAtTimestamp, market.liquidity, market.balance, market.sharesAvailable, getMarketResolvedOutcome(marketId) ); } function getMarketAltData(uint256 marketId) public view returns ( uint256, bytes32, uint256 ) { Market storage market = markets[marketId]; return (market.fees.value, market.resolution.questionId, uint256(market.resolution.questionId)); } function getMarketQuestion(uint256 marketId) public view returns (bytes32) { Market storage market = markets[marketId]; return (market.resolution.questionId); } function getMarketPrices(uint256 marketId) public view returns ( uint256, uint256, uint256 ) { return (getMarketLiquidityPrice(marketId), getMarketOutcomePrice(marketId, 0), getMarketOutcomePrice(marketId, 1)); } function getMarketLiquidityPrice(uint256 marketId) public view returns (uint256) { Market storage market = markets[marketId]; if (market.state == MarketState.resolved && !isMarketVoided(marketId)) { // resolved market, price is either 0 or 1 // final liquidity price = outcome shares / liquidity shares return market.outcomes[market.resolution.outcomeId].shares.available.mul(ONE).div(market.liquidity); } // liquidity price = # liquidity shares / # outcome shares * # outcomes return market.liquidity.mul(ONE * market.outcomeIds.length).div(market.sharesAvailable); } function getMarketResolvedOutcome(uint256 marketId) public view returns (int256) { Market storage market = markets[marketId]; // returning -1 if market still not resolved if (market.state != MarketState.resolved) { return -1; } return int256(market.resolution.outcomeId); } function isMarketVoided(uint256 marketId) public view returns (bool) { Market storage market = markets[marketId]; // market still not resolved, still in valid state if (market.state != MarketState.resolved) { return false; } // resolved market id does not match any of the market ids return market.resolution.outcomeId >= market.outcomeIds.length; } // ------ Outcome Getters ------ function getMarketOutcomeIds(uint256 marketId) public view returns (uint256[] memory) { Market storage market = markets[marketId]; return market.outcomeIds; } function getMarketOutcomePrice(uint256 marketId, uint256 outcomeId) public view returns (uint256) { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; if (market.state == MarketState.resolved && !isMarketVoided(marketId)) { // resolved market, price is either 0 or 1 return outcomeId == market.resolution.outcomeId ? ONE : 0; } return (market.sharesAvailable.sub(outcome.shares.available)).mul(ONE).div(market.sharesAvailable); } function getMarketOutcomeData(uint256 marketId, uint256 outcomeId) public view returns ( uint256, uint256, uint256 ) { Market storage market = markets[marketId]; MarketOutcome storage outcome = market.outcomes[outcomeId]; return (getMarketOutcomePrice(marketId, outcomeId), outcome.shares.available, outcome.shares.total); } function getMarketOutcomesShares(uint256 marketId) private view returns (uint256[] memory) { Market storage market = markets[marketId]; uint256[] memory shares = new uint256[](market.outcomeIds.length); for (uint256 i = 0; i < market.outcomeIds.length; i++) { shares[i] = market.outcomes[i].shares.available; } return shares; } }
[{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_requiredBalance","type":"uint256"},{"internalType":"address","name":"_realitioAddress","type":"address"},{"internalType":"uint256","name":"_realitioTimeout","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"enum PredictionMarket.MarketAction","name":"action","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outcomeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarketActionTx","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outcomes","type":"uint256"},{"indexed":false,"internalType":"string","name":"question","type":"string"},{"indexed":false,"internalType":"string","name":"image","type":"string"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarketLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"outcomeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarketOutcomePrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outcomeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarketResolved","type":"event"},{"inputs":[],"name":"MAX_UINT_256","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"},{"internalType":"uint256","name":"minOutcomeSharesToBuy","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"}],"name":"calcBuyAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"}],"name":"calcSellAmount","outputs":[{"internalType":"uint256","name":"outcomeTokenSellAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"claimFees","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"claimLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"}],"name":"claimVoidedOutcomeShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"claimWinnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"question","type":"string"},{"internalType":"string","name":"image","type":"string"},{"internalType":"uint256","name":"closesAt","type":"uint256"},{"internalType":"address","name":"arbitrator","type":"address"},{"internalType":"uint256","name":"outcomes","type":"uint256"}],"name":"createMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketAltData","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketData","outputs":[{"internalType":"enum PredictionMarket.MarketState","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketLiquidityPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"}],"name":"getMarketOutcomeData","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketOutcomeIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"}],"name":"getMarketOutcomePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketQuestion","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketResolvedOutcome","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserClaimStatus","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserClaimableFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserLiquidityPoolShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserMarketShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"isMarketVoided","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"realitioAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"realitioTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requiredBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"resolveMarketOutcome","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"outcomeId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"maxOutcomeSharesToSell","type":"uint256"}],"name":"sell","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200341b3803806200341b833981016040819052620000349162000075565b600394909455600680546001600160a01b039485166001600160a01b03199182161790915560079290925560048054919093169116179055600555620000e9565b600080600080600060a086880312156200008d578081fd5b855194506020860151620000a181620000d0565b604087015160608801519195509350620000bb81620000d0565b80925050608086015190509295509295909350565b6001600160a01b0381168114620000e657600080fd5b50565b61332280620000f96000396000f3fe6080604052600436106101945760003560e01c806308560ace146101995780631d7920aa146101c457806328747a80146101f35780632c2aa24e1461021357806331877a38146102445780633620875e146102715780633d41a26b146102865780633fe45e3b1461029b57806340993b26146102b0578063429c9dff146102c35780634397c4ce146102e3578063441cf65e1461030357806351c6590a146103305780635e648eff14610343578063677bd9ff146103635780637b34e6e01461038357806385b91d8e146103a55780638c7adc15146103c55780638cd41552146103da5780639d7de6b3146103fa578063aa22a02e1461040d578063ac68a7481461042d578063b31eb89514610440578063bf45572114610460578063bfacba3d14610480578063c2ee3a08146104b2578063c346a9d0146104c7578063c8f70d01146104e7578063ddca3f4314610507578063ec2c90161461051c578063ec93f0f514610531578063efbc47dc14610551578063efce431314610564578063fc0c546a14610584578063fdff808514610599575b600080fd5b3480156101a557600080fd5b506101ae6105b9565b6040516101bb9190612c41565b60405180910390f35b3480156101d057600080fd5b506101e46101df366004612aab565b6105bf565b6040516101bb93929190613253565b3480156101ff57600080fd5b506101ae61020e366004612aab565b6105de565b34801561021f57600080fd5b5061023361022e366004612ac3565b610758565b6040516101bb959493929190612c1a565b34801561025057600080fd5b5061026461025f366004612aab565b610828565b6040516101bb9190612bcb565b61028461027f366004612b3b565b610891565b005b34801561029257600080fd5b506101ae610ab5565b3480156102a757600080fd5b506101ae610abb565b6102846102be366004612b10565b610ac1565b3480156102cf57600080fd5b506101ae6102de366004612b10565b610c4f565b3480156102ef57600080fd5b506101ae6102fe366004612aab565b610daf565b34801561030f57600080fd5b5061032361031e366004612aab565b610dc4565b6040516101bb9190612c0f565b61028461033e366004612aab565b610e09565b34801561034f57600080fd5b5061028461035e366004612aab565b610e91565b34801561036f57600080fd5b5061028461037e366004612aab565b61104b565b34801561038f57600080fd5b506103986111a3565b6040516101bb9190612bb7565b3480156103b157600080fd5b506101e46103c0366004612aab565b6111b2565b3480156103d157600080fd5b506101ae6111e3565b3480156103e657600080fd5b506101ae6103f5366004612aef565b6111e9565b610284610408366004612aef565b6112a9565b34801561041957600080fd5b506101ae610428366004612ac3565b61169b565b61028461043b366004612aab565b6116ee565b34801561044c57600080fd5b506101e461045b366004612ac3565b6117b7565b34801561046c57600080fd5b506101ae61047b366004612aab565b611812565b34801561048c57600080fd5b506104a061049b366004612aab565b61184f565b6040516101bb96959493929190612c4a565b3480156104be57600080fd5b506101ae6118a8565b3480156104d357600080fd5b506101ae6104e2366004612b10565b6118b4565b3480156104f357600080fd5b506101ae610502366004612aab565b6119e4565b34801561051357600080fd5b506101ae611a97565b34801561052857600080fd5b50610264611a9d565b34801561053d57600080fd5b5061028461054c366004612aef565b611af5565b6101ae61055f366004612a28565b611cb5565b34801561057057600080fd5b506101e461057f366004612aef565b611f60565b34801561059057600080fd5b50610398611fa4565b3480156105a557600080fd5b506101ae6105b4366004612ac3565b611fb3565b60075481565b6000908152600160205260409020600a81015460099091015490918190565b60008181526001602052604081205482904211801561061a575060008181526001602052604081206006015460ff16600281111561061857fe5b145b15610628576106288161202c565b8260018060008381526001602052604090206006015460ff16600281111561064c57fe5b1461065657600080fd5b600085815260016020526040808220600480546009830154935163684e62bf60e11b81528a9593946001600160a01b039092169392849263d09cc57e9261069d9201612c41565b60206040518083038186803b1580156106b557600080fd5b505afa1580156106c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106ed9190810190612a10565b60088401819055604051909150899033907f67a6457c8912ae1b7a9fbdfa311cbd016ba606b548bf06bc80bc751072d91bbc9061072d908590429061329e565b60405180910390a361073e8961207c565b505060080154945061074f8161202c565b50505050919050565b600082815260016020526040812081908190819081906002600682015460ff16600281111561078357fe5b146107a8576000806000806107988c8c611fb3565b955095509550955095505061081e565b60088101546000908152600e8201602090815260408083206001600160a01b038b16845260048082018452828520546005808401865284872054928801865284872054908801909552929094205490939115159260ff9283169290151591166108118d8d611fb3565b9650965096509650965050505b9295509295909350565b600081815260016020908152604091829020600d81018054845181850281018501909552808552606094929383018282801561088357602002820191906000526020600020905b81548152602001906001019080831161086f575b50505050509150505b919050565b6000848152600160205260409020548490421180156108cd575060008181526001602052604081206006015460ff1660028111156108cb57fe5b145b156108db576108db8161202c565b8460008060008381526001602052604090206006015460ff1660028111156108ff57fe5b1461090957600080fd5b6000878152600160209081526040808320898452600e810190925282209091610933888b8b6118b4565b90508681111561095e5760405162461bcd60e51b8152600401610955906131da565b60405180910390fd5b33600090815260048301602052604090205481111561098f5760405162461bcd60e51b81526004016109559061311c565b61099b338b8b8461211f565b60006109ba600354670de0b6b3a76400006121be90919063ffffffff16565b600a8501546109d0908b9063ffffffff6121e616565b816109d757fe5b600b86015491900491506109f1908263ffffffff61222016565b600b8501556000610a088a8363ffffffff61222016565b90508085600101541015610a2e5760405162461bcd60e51b8152600401610955906130d9565b610a388c82612245565b60405133908b156108fc02908c906000818181858888f19350505050158015610a65573d6000803e3d6000fd5b508b6001336001600160a01b03166000805160206132ad8339815191528e878f42604051610a969493929190612c81565b60405180910390a4610aa78c61207c565b505050505050505050505050565b60001981565b60055481565b600083815260016020526040902054839042118015610afd575060008181526001602052604081206006015460ff166002811115610afb57fe5b145b15610b0b57610b0b8161202c565b8360008060008381526001602052604090206006015460ff166002811115610b2f57fe5b14610b3957600080fd5b6000868152600160205260408120903490610b55828a8a610c4f565b905086811015610b775760405162461bcd60e51b8152600401610955906131a3565b600a830154600090670de0b6b3a764000090610b9a90859063ffffffff6121e616565b81610ba157fe5b600b8601549190049150610bbb908263ffffffff61222016565b600b8501556000610bd2848363ffffffff6121be16565b60008b8152600e870160205260409020909150610bef8c836122e8565b6003810154841115610c135760405162461bcd60e51b81526004016109559061315d565b610c1f338d8d87612381565b8b6000336001600160a01b03166000805160206132ad8339815191528e888a42604051610a969493929190612c81565b60008281526001602052604081206060610c6885612410565b90506000610ca8670de0b6b3a7640000610c9285600a01600001548a6121e690919063ffffffff16565b81610c9957fe5b8991900463ffffffff6121be16565b90506000828681518110610cb857fe5b602002602001015190506000610cdf670de0b6b3a7640000836121e690919063ffffffff16565b905060005b8451811015610d4a57878114610d42576000858281518110610d0257fe5b60200260200101519050610d3e610d22868361222090919063ffffffff16565b610d32858463ffffffff6121e616565b9063ffffffff6124a316565b9250505b600101610ce4565b5060008111610d6b5760405162461bcd60e51b815260040161095590612cec565b610da2610d8682670de0b6b3a764000063ffffffff6124a316565b610d96848663ffffffff61222016565b9063ffffffff6121be16565b9998505050505050505050565b60009081526001602052604090206009015490565b60008181526001602052604081206002600682015460ff166002811115610de757fe5b14610df657600091505061088c565b600d810154600890910154101592915050565b600081815260016020526040902054819042118015610e45575060008181526001602052604081206006015460ff166002811115610e4357fe5b145b15610e5357610e538161202c565b8160008060008381526001602052604090206006015460ff166002811115610e7757fe5b14610e8157600080fd5b610e8b84346124d3565b50505050565b8060028060008381526001602052604090206006015460ff166002811115610eb557fe5b14610ebf57600080fd5b6000838152600160205260409020610ed6846116ee565b336000908152600482016020526040902054610f045760405162461bcd60e51b815260040161095590613096565b33600090815260058201602052604090205460ff1615610f365760405162461bcd60e51b81526004016109559061304f565b6000610f41856119e4565b33600090815260048401602052604081205491925090670de0b6b3a764000090610f7290849063ffffffff6121e616565b81610f7957fe5b0490508083600101541015610fa05760405162461bcd60e51b815260040161095590612eb5565b6001830154610fb5908263ffffffff6121be16565b600184810191909155336000818152600580870160209081526040808420805460ff19169096179095556004880190528382205493518a949193926000805160206132ad8339815191529261100d9288904290612c81565b60405180910390a4604051339082156108fc029083906000818181858888f19350505050158015611042573d6000803e3d6000fd5b50505050505050565b8060028060008381526001602052604090206006015460ff16600281111561106f57fe5b1461107957600080fd5b600083815260016020908152604080832060088101548452600e81018352818420338552600481019093529220546110c35760405162461bcd60e51b815260040161095590612dc6565b33600090815260058201602052604090205460ff16156110f55760405162461bcd60e51b815260040161095590612f76565b336000908152600482016020526040902054600183015481111561112b5760405162461bcd60e51b815260040161095590612eb5565b6001830154611140908263ffffffff6121be16565b6001808501919091553360009081526005840160205260409020805460ff1916909117905585600460088501543360008181526004870160205260409081902054905191926000805160206132ad8339815191529261100d929088904290612c81565b6004546001600160a01b031681565b60008060006111c0846119e4565b6111cb8560006111e9565b6111d68660016111e9565b9250925092509193909250565b60025481565b6000828152600160209081526040808320848452600e810190925282206002600683015460ff16600281111561121b57fe5b14801561122e575061122c85610dc4565b155b15611258576008820154841461124557600061124f565b670de0b6b3a76400005b925050506112a3565b6003808301549082015461129e919061129290670de0b6b3a76400009061128690849063ffffffff6121be16565b9063ffffffff6121e616565b9063ffffffff61286b16565b925050505b92915050565b6000828152600160205260409020548290421180156112e5575060008181526001602052604081206006015460ff1660028111156112e357fe5b145b156112f3576112f38161202c565b8260008060008381526001602052604090206006015460ff16600281111561131757fe5b1461132157600080fd5b6000858152600160209081526040808320338452600481019092529091205485111561135f5760405162461bcd60e51b81526004016109559061311c565b611368866116ee565b6113748686600361288c565b50606061138087612410565b9050606081516040519080825280602002602001820160405280156113af578160200160208202803883390190505b50905060001960005b83518110156113ee5760008482815181106113cf57fe5b60200260200101519050808311156113e5578092505b506001016113b8565b50600284015460009061140b906112928b8563ffffffff6121e616565b905060005b84518110156114a95785600201546114448b87848151811061142e57fe5b60200260200101516121e690919063ffffffff16565b8161144b57fe5b0484828151811061145857fe5b60200260200101818152505061148a8285838151811061147457fe5b60200260200101516121be90919063ffffffff16565b84828151811061149657fe5b6020908102919091010152600101611410565b506114b48a82612245565b60028501546114c9908a63ffffffff6121be16565b60028601553360009081526004860160205260409020546114f0908a63ffffffff6121be16565b3360009081526004870160205260408120919091555b84518110156115f157600084828151811061151d57fe5b602002602001015111156115e9576003808701546000838152600e89016020526040902090910154855161156a9033908f9086908a908290811061155d57fe5b6020026020010151612381565b8c6000336001600160a01b03166000805160206132ad833981519152868a888151811061159357fe5b60200260200101516115cd8e600301546112928e8c815181106115b257fe5b60200260200101516112868b8d6121be90919063ffffffff16565b426040516115de9493929190612c81565b60405180910390a450505b600101611506565b50604051339082156108fc029083906000818181858888f1935050505015801561161f573d6000803e3d6000fd5b50896003336001600160a01b03166000805160206132ad83398151915260008d86426040516116519493929190612c81565b60405180910390a4896000805160206132cd83398151915286600201546116778d6119e4565b4260405161168793929190613253565b60405180910390a250505050505050505050565b600082815260016020908152604080832060028101546001600160a01b0386168552600482019093529083205490916116e69161129290670de0b6b3a764000063ffffffff6121e616565b949350505050565b6000818152600160205260408120906117078333611fb3565b9050801561177357336000908152600c83016020526040902054611731908263ffffffff61222016565b336000818152600c85016020526040808220939093559151909183156108fc02918491818181858888f19350505050158015611771573d6000803e3d6000fd5b505b8260063360008181526004860160205260408082205490516000805160206132ad833981519152926117aa92909188904290612c81565b60405180910390a4505050565b60009182526001602081815260408085206001600160a01b03949094168086526004808601845282872054878052600e9096018085528388208389528201855283882054958852845282872091875201909152909220549092565b60008181526001602052604081206002600682015460ff16600281111561183557fe5b146118455760001991505061088c565b6008015492915050565b6000818152600160208190526040822060068101548154600283015493830154600384015486958695869586958695929460ff90921693909290916118938d611812565b949d939c50919a509850965090945092505050565b670de0b6b3a764000081565b600082815260016020526040812060606118cd85612410565b600a8301549091506000906118f190670de0b6b3a76400009063ffffffff6121be16565b61190988670de0b6b3a764000063ffffffff6121e616565b8161191057fe5b049050600082868151811061192157fe5b602002602001015190506000611948670de0b6b3a7640000836121e690919063ffffffff16565b905060005b84518110156119975787811461198f57600085828151811061196b57fe5b6020026020010151905061198b610d2286836121be90919063ffffffff16565b9250505b60010161194d565b50600081116119b85760405162461bcd60e51b815260040161095590612cec565b610da282610d966119d784670de0b6b3a764000063ffffffff6124a316565b869063ffffffff61222016565b60008181526001602052604081206002600682015460ff166002811115611a0757fe5b148015611a1a5750611a1883610dc4565b155b15611a6257600281015460088201546000908152600e83016020526040902060030154611a5a919061129290670de0b6b3a764000063ffffffff6121e616565b91505061088c565b6003810154600d8201546002830154611a9092916112929190670de0b6b3a76400000263ffffffff6121e616565b9392505050565b60035481565b60606000805480602002602001604051908101604052809291908181526020018280548015611aeb57602002820191906000526020600020905b815481526020019060010190808311611ad7575b5050505050905090565b8160028060008381526001602052604090206006015460ff166002811115611b1957fe5b14611b2357600080fd5b6000848152600160209081526040808320868452600e8101835281842033855260048101909352922054611b695760405162461bcd60e51b815260040161095590612d50565b33600090815260068201602052604090205460ff1615611b9b5760405162461bcd60e51b815260040161095590613210565b6000611ba787876111e9565b33600090815260048401602052604081205491925090611bdc90670de0b6b3a76400009061129290859063ffffffff6121e616565b90508084600101541015611c025760405162461bcd60e51b815260040161095590612eb5565b6001840154611c17908263ffffffff6121be16565b6001808601919091553360009081526006850160205260409020805460ff19169091179055876007336000818152600487016020526040908190205490516000805160206132ad83398151915291611c75918d919088904290612c81565b60405180910390a4604051339082156108fc029083906000818181858888f19350505050158015611caa573d6000803e3d6000fd5b505050505050505050565b6007546006546040516370a0823160e01b8152600092916001600160a01b0316906370a0823190611cea903390600401612bb7565b60206040518083038186803b158015611d0257600080fd5b505afa158015611d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d3a9190810190612a10565b1015611d585760405162461bcd60e51b815260040161095590612f2c565b60025460008054600181810183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639091018390558282526020526040902034611db45760405162461bcd60e51b815260040161095590612d21565b42861015611dd45760405162461bcd60e51b815260040161095590613005565b83600214611df45760405162461bcd60e51b815260040161095590612e10565b85815560068101805460ff19169055600354600a820155600019600882015560005b84811015611e5857600d820180546001818101835560009283526020808420909201849055838352600e85019091526040909120848155810182905501611e16565b506004805460055460405163d4876b9f60e01b81526001600160a01b0390921692839263d4876b9f92611e9b926002928f928d9290918f91600091829101612c9c565b602060405180830381600087803b158015611eb557600080fd5b505af1158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611eed9190810190612a10565b6009830155611efc83346124d3565b611f058361207c565b82336001600160a01b03167f928446b14f4c661d8499681f1d2eb118eb6e89066877a7d43e0672a27cc63a32878c8c604051611f4393929190613269565b60405180910390a350506002805460010190559695505050505050565b6000828152600160209081526040808320848452600e8101909252822082918291611f8b87876111e9565b6003820154600290920154909891975095509350505050565b6006546001600160a01b031681565b600082815260016020908152604080832060028101546001600160a01b03861685526004820190935290832054600b82015491928492611ffd92611292919063ffffffff6121e616565b6001600160a01b0385166000908152600c8401602052604090205490915061129e90829063ffffffff6121be16565b6000818152600160205260409020600681015460ff16600281111561204d57fe5b600101600281111561205b57fe5b60068201805460ff1916600183600281111561207357fe5b02179055505050565b6000818152600160205260408120905b600d8201548110156120e45780837f8270f0a0534b13b7f92d1dbd58aa75c5207b40c55fefa7a17110c6136ad7270b6120c586856111e9565b426040516120d492919061329e565b60405180910390a360010161208c565b50816000805160206132cd8339815191528260020154612103856119e4565b4260405161211393929190613253565b60405180910390a25050565b6000838152600160209081526040808320858452600e810183528184206001600160a01b038916855260048101909352922054612162908463ffffffff6121be16565b6001600160a01b03871660009081526004830160205260409020556003810154612192908463ffffffff61222016565b6003808301919091558201546121ae908463ffffffff61222016565b8260030181905550505050505050565b6000828211156121e05760405162461bcd60e51b815260040161095590612e7e565b50900390565b6000826121f5575060006112a3565b8282028284828161220257fe5b0414611a905760405162461bcd60e51b815260040161095590612fc4565b600082820183811015611a905760405162461bcd60e51b815260040161095590612d91565b6000828152600160205260408120905b600d8201548110156122c8576000818152600e8301602052604090206003810154612286908563ffffffff6121be16565b600382015560028101546122a0908563ffffffff6121be16565b600282015560038301546122ba908563ffffffff6121be16565b600384015550600101612255565b5060018101546122de908363ffffffff6121be16565b6001909101555050565b6000828152600160205260408120905b600d82015481101561236b576000818152600e8301602052604090206003810154612329908563ffffffff61222016565b60038201556002810154612343908563ffffffff61222016565b6002820155600383015461235d908563ffffffff61222016565b6003840155506001016122f8565b5060018101546122de908363ffffffff61222016565b6000838152600160209081526040808320858452600e810183528184206001600160a01b0389168552600481019093529220546123c4908463ffffffff61222016565b6001600160a01b038716600090815260048301602052604090205560038101546123f4908463ffffffff6121be16565b6003808301919091558201546121ae908463ffffffff6121be16565b600081815260016020908152604091829020600d81015483518181528184028101909301909352606092909183918015612454578160200160208202803883390190505b50905060005b600d83015481101561249b576000818152600e84016020526040902060030154825183908390811061248857fe5b602090810291909101015260010161245a565b509392505050565b600082156124c2578160018403816124b757fe5b0460010190506112a3565b8183816124cb57fe5b049392505050565b60008281526001602052604090205482904211801561250f575060008181526001602052604081206006015460ff16600281111561250d57fe5b145b1561251d5761251d8161202c565b8260008060008381526001602052604090206006015460ff16600281111561254157fe5b1461254b57600080fd5b6000858152600160205260409020846125765760405162461bcd60e51b815260040161095590612e47565b6000606061258388612410565b9050606081516040519080825280602002602001820160405280156125b2578160200160208202803883390190505b506002850154909150600090156126a15760005b83518110156125fc5760008482815181106125dd57fe5b60200260200101519050808310156125f3578092505b506001016125c6565b5060005b835181101561266c5760008261263286848151811061261b57fe5b60200260200101518d6121e690919063ffffffff16565b8161263957fe5b04905061264c8b8263ffffffff6121be16565b84838151811061265857fe5b602090810291909101015250600101612600565b508061268586600201548b6121e690919063ffffffff16565b8161268c57fe5b04935061269b8a85600261288c565b506126a5565b8893505b60028501546126ba908563ffffffff61222016565b60028601553360009081526004860160205260409020546126e1908563ffffffff61222016565b3360009081526004870160205260409020556126fd8a8a6122e8565b60005b82518110156127c357600083828151811061271757fe5b602002602001015111156127bb576003808701546000838152600e8901602052604090209091015484516127579033908f90869089908290811061155d57fe5b8c6000336001600160a01b03166000805160206132ad8339815191528689888151811061278057fe5b602002602001015161279f8e600301546112928d8c815181106115b257fe5b426040516127b09493929190612c81565b60405180910390a450505b600101612700565b5060006127cf8b6119e4565b90506000670de0b6b3a76400006127ec838863ffffffff6121e616565b816127f357fe5b0490508b6002336001600160a01b03166000805160206132ad83398151915260008a86426040516128279493929190612c81565b60405180910390a48b6000805160206132cd8339815191528860020154844260405161285593929190613253565b60405180910390a2505050505050505050505050565b60008082116124c25760405162461bcd60e51b815260040161095590612ef8565b60008381526001602052604081206002810154600b82015483916128bb9161129290889063ffffffff6121e616565b905060028460078111156128cb57fe5b141561292457600b8201546128e6908263ffffffff61222016565b600b830155336000908152600c8301602052604090205461290d908263ffffffff61222016565b336000908152600c84016020526040902055612973565b600b820154612939908263ffffffff6121be16565b600b830155336000908152600c83016020526040902054612960908263ffffffff6121be16565b336000908152600c840160205260409020555b50509392505050565b80356001600160a01b03811681146112a357600080fd5b600082601f8301126129a3578081fd5b81356001600160401b03808211156129b9578283fd5b604051601f8301601f1916810160200182811182821017156129d9578485fd5b6040528281529250828483016020018610156129f457600080fd5b8260208601602083013760006020848301015250505092915050565b600060208284031215612a21578081fd5b5051919050565b600080600080600060a08688031215612a3f578081fd5b85356001600160401b0380821115612a55578283fd5b612a6189838a01612993565b96506020880135915080821115612a76578283fd5b50612a8388828901612993565b94505060408601359250612a9a876060880161297c565b949793965091946080013592915050565b600060208284031215612abc578081fd5b5035919050565b60008060408385031215612ad5578182fd5b82359150612ae6846020850161297c565b90509250929050565b60008060408385031215612b01578182fd5b50508035926020909101359150565b600080600060608486031215612b24578283fd5b505081359360208301359350604090920135919050565b60008060008060808587031215612b50578384fd5b5050823594602084013594506040840135936060013592509050565b60008151808452815b81811015612b9157602081850181015186830182015201612b75565b81811115612ba25782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6020808252825182820181905260009190848201906040850190845b81811015612c0357835183529284019291840191600101612be7565b50909695505050505050565b901515815260200190565b94151585529215156020850152901515604084015215156060830152608082015260a00190565b90815260200190565b60c0810160038810612c5857fe5b968152602081019590955260408501939093526060840191909152608083015260a09091015290565b93845260208401929092526040830152606082015260800190565b600088825260e06020830152612cb560e0830189612b6c565b6001600160a01b039790971660408301525063ffffffff948516606082015292909316608083015260a082015260c0015292915050565b6020808252601b908201527a6d7573742068617665206e6f6e2d7a65726f2062616c616e63657360281b604082015260600190565b60208082526015908201527407374616b65206e6565647320746f206265203e203605c1b604082015260600190565b60208082526021908201527f7573657220646f6573206e6f7420686f6c64206f7574636f6d652073686172656040820152607360f81b606082015260800190565b6020808252601b908201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604082015260600190565b6020808252602a908201527f7573657220646f6573206e6f7420686f6c64207265736f6c766564206f7574636040820152696f6d652073686172657360b01b606082015260800190565b6020808252601e908201527f6e756d626572206f66206f7574636f6d65732068617320746f20626520320000604082015260600190565b6020808252601f908201527f7374616b652068617320746f2062652067726561746572207468616e20302e00604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526023908201527f4d61726b657420646f6573206e6f74206861766520656e6f7567682062616c616040820152626e636560e81b606082015260800190565b6020808252601a9082015279536166654d6174683a206469766973696f6e206279207a65726f60301b604082015260600190565b6020808252602a908201527f6d73672e73656e646572206d75737420686f6c64206d696e696d756d2065726360408201526932302062616c616e636560b01b606082015260800190565b6020808252602e908201527f7573657220616c726561647920636c61696d6564207265736f6c766564206f7560408201526d74636f6d652077696e6e696e677360901b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602a908201527f6d61726b6574206d757374207265736f6c7665206166746572207468652063756040820152697272656e74206461746560b01b606082015260800190565b60208082526027908201527f7573657220616c726561647920636c61696d6564206c69717569646974792077604082015266696e6e696e677360c81b606082015260800190565b60208082526023908201527f7573657220646f6573206e6f7420686f6c64206c69717569646974792073686160408201526272657360e81b606082015260800190565b60208082526023908201527f6d61726b657420646f6573206e6f74206861766520656e6f7567682062616c616040820152626e636560e81b606082015260800190565b60208082526021908201527f7573657220646f6573206e6f74206861766520656e6f7567682062616c616e636040820152606560f81b606082015260800190565b60208082526026908201527f6f7574636f6d652073686172657320706f6f6c2062616c616e636520697320746040820152656f6f206c6f7760d01b606082015260800190565b6020808252601e908201527f6d696e696d756d2062757920616d6f756e74206e6f7420726561636865640000604082015260600190565b6020808252601c908201527b1b585e1a5b5d5b481cd95b1b08185b5bdd5b9d08195e18d95959195960221b604082015260600190565b60208082526023908201527f7573657220616c726561647920636c61696d6564206f7574636f6d652073686160408201526272657360e81b606082015260800190565b9283526020830191909152604082015260600190565b6000848252606060208301526132826060830185612b6c565b82810360408401526132948185612b6c565b9695505050505050565b91825260208201526040019056fe9dcabe311735ed0d65f0c22c5425d1f17331f94c9d0767f59e58473cf95ada611eca98f266e5348ae38d5d057a4d8e451e76672f69ac6ba4b0e3b31ea9c7eb2ba2646970667358221220bb3570dbb9f12939d26e065d1baf2ae8ff33a6895b5447dba96d743778cfc85b64736f6c6343000602003300000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000008b29344f368b5fa35595325903fe0eaab70c8e1f00000000000000000000000000000000000000000000003635c9adc5dea0000000000000000000000000000060d7956805ec5a698173def4d0e1ecdefb06cc57000000000000000000000000000000000000000000000000000000000003f480
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000008b29344f368b5fa35595325903fe0eaab70c8e1f00000000000000000000000000000000000000000000003635c9adc5dea0000000000000000000000000000060d7956805ec5a698173def4d0e1ecdefb06cc57000000000000000000000000000000000000000000000000000000000003f480
-----Decoded View---------------
Arg [0] : _fee (uint256): 20000000000000000
Arg [1] : _token (address): 0x8b29344f368b5fa35595325903fe0eaab70c8e1f
Arg [2] : _requiredBalance (uint256): 1000000000000000000000
Arg [3] : _realitioAddress (address): 0x60d7956805ec5a698173def4d0e1ecdefb06cc57
Arg [4] : _realitioTimeout (uint256): 259200
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000470de4df820000
Arg [1] : 0000000000000000000000008b29344f368b5fa35595325903fe0eaab70c8e1f
Arg [2] : 00000000000000000000000000000000000000000000003635c9adc5dea00000
Arg [3] : 00000000000000000000000060d7956805ec5a698173def4d0e1ecdefb06cc57
Arg [4] : 000000000000000000000000000000000000000000000000000000000003f480
Deployed ByteCode Sourcemap
49503:30633:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52542:30;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52542:30:0;;;:::i;:::-;;;;;;;;;;;;;;;;76528:296;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;76528:296:0;;;;;;;;:::i;:::-;;;;;;;;;;65631:641;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;65631:641:0;;;;;;;;:::i;74726:710::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;74726:710:0;;;;;;;;:::i;:::-;;;;;;;;;;;;78663:171;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78663:171:0;;;;;;;;:::i;:::-;;;;;;;;58968:1272;;;;;;;;;:::i;:::-;;50431:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50431:117:0;;;:::i;52417:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52417:30:0;;;:::i;57787:1131::-;;;;;;;;;:::i;55803:903::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;55803:903:0;;;;;;;;:::i;76830:175::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;76830:175:0;;;;;;;;:::i;78226:393::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78226:393:0;;;;;;;;:::i;:::-;;;;;;;;60296:188;;;;;;;;;:::i;68661:1061::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;68661:1061:0;;;;;;;;:::i;66351:1036::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;66351:1036:0;;;;;;;;:::i;52382:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52382:30:0;;;:::i;:::-;;;;;;;;77011:264;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;77011:264:0;;;;;;;;:::i;52214:26::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52214:26:0;;;:::i;78840:527::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78840:527:0;;;;;;;;:::i;63122:2429::-;;;;;;;;;:::i;75442:226::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;75442:226:0;;;;;;;;:::i;69808:545::-;;;;;;;;;:::i;74355:365::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;74355:365:0;;;;;;;;:::i;77908:312::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;77908:312:0;;;;;;;;:::i;76083:439::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;76083:439:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;50555:36;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50555:36:0;;;:::i;56814:924::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;56814:924:0;;;;;;;;:::i;77281:621::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;77281:621:0;;;;;;;;:::i;52264:18::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52264:18:0;;;:::i;75987:90::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75987:90:0;;;:::i;67468:1104::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;67468:1104:0;;;;;;;;:::i;54000:1724::-;;;;;;;;;:::i;79373:388::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;79373:388:0;;;;;;;;:::i;52474:19::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52474:19:0;;;:::i;75674:307::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;75674:307:0;;;;;;;;:::i;52542:30::-;;;;:::o;76528:296::-;76616:7;76697:17;;;:7;:17;;;;;76731:11;;;:17;76750:28;;;;;76731:17;;76750:28;;76528:296::o;65631:641::-;65809:7;52805:17;;;:7;:17;;;;;:35;65712:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;65735:8;65745:18:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;65828:21:::3;65852:17:::0;;;:7:::3;:17;::::0;;;;;65917:15:::3;::::0;;66034:28;;;;66015:48;;-1:-1:-1;;;66015:48:0;;65785:8;;65852:17;;-1:-1:-1;;;;;65917:15:0;;::::3;::::0;65828:21;65917:15;;66015:18:::3;::::0;:48:::3;::::0;::::3;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::3;5:2;66015:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;66015:48:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;66015:48:0;;;;;;;;;66073:27:::0;;;:39;;;66126:52:::3;::::0;66007:57;;-1:-1:-1;66153:8:0;;66141:10:::3;::::0;66126:52:::3;::::0;::::3;::::0;66007:57;;66174:3:::3;::::0;66126:52:::3;;;;;;;;;;66185:38;66214:8;66185:28;:38::i;:::-;-1:-1:-1::0;;66239:27:0;;;;-1:-1:-1;53248:19:0::2;53258:8;53248:9;:19::i;:::-;53053:1;52931::::1;;65631:641:::0;;;;:::o;74726:710::-;74830:4;74931:17;;;:7;:17;;;;;74830:4;;;;;;;;75011:20;74995:12;;;;;;:36;;;;;;;;;74991:132;;75050:5;75057;75064;75071;75078:36;75099:8;75109:4;75078:20;:36::i;:::-;75042:73;;;;;;;;;;;;;74991:132;75179:27;;;;75131:29;75163:44;;;:15;;;:44;;;;;;;;-1:-1:-1;;;;;75232:28:0;;;;:22;;;;:28;;;;;;75273:21;;;;:27;;;;;;75309:22;;;:28;;;;;;75350:22;;;:28;;;;;;;;75163:44;;75232:32;;;;75273:27;;;;;75309:32;;;;75350:28;75387:36;75408:8;75255:4;75387:20;:36::i;:::-;75216:214;;;;;;;;;;;;74726:710;;;;;;;;;:::o;78663:171::-;78756:21;78780:17;;;:7;:17;;;;;;;;;78811;;;78804:24;;;;;;;;;;;;;;;;;78731:16;;78780:17;;78804:24;;78811:17;78804:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78663:171;;;;:::o;58968:1272::-;52805:17;;;;:7;:17;;;;;:35;59124:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;59142:8;59152:16:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;59177:21:::2;59201:17:::0;;;:7:::2;:17;::::0;;;;;;;59257:26;;;:15:::2;::::0;::::2;:26:::0;;;;;59201:17;;59309:42:::2;59324:5:::0;59209:8;59273:9;59309:14:::2;:42::i;:::-;59292:59;;59378:22;59368:6;:32;;59360:73;;;;-1:-1:-1::0;;;59360:73:0::2;;;;;;;;;;;;;;;;;59471:10;59448:34;::::0;;;:22;;;:34:::2;::::0;;;;;:44;-1:-1:-1;59448:44:0::2;59440:90;;;;-1:-1:-1::0;;;59440:90:0::2;;;;;;;;;59539:68;59567:10;59579:8;59589:9;59600:6;59539:27;:68::i;:::-;59656:17;59708:12;59716:3;;50585:6;59708:7;;:12;;;;:::i;:::-;59686:11;::::0;::::2;:17:::0;59676:28:::2;::::0;:5;;:28:::2;:9;:28;:::i;:::-;:45;;;;;59753:22:::0;;;;59676:45;;::::2;::::0;-1:-1:-1;59753:37:0::2;::::0;59676:45;59753:37:::2;:26;:37;:::i;:::-;59728:22:::0;;;:62;59797:21:::2;59821:20;:5:::0;59831:9;59821:20:::2;:9;:20;:::i;:::-;59797:44;;59876:13;59858:6;:14;;;:31;;59850:79;;;;-1:-1:-1::0;;;59850:79:0::2;;;;;;;;;59972:47;59995:8;60005:13;59972:22;:47::i;:::-;60063:26;::::0;:10:::2;::::0;:26;::::2;;;::::0;60083:5;;60063:26:::2;::::0;;;60083:5;60063:10;:26;::::2;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;60149:8:0;60130:17:::2;60118:10;-1:-1:-1::0;;;;;60103:86:0::2;-1:-1:-1::0;;;;;;;;;;;60159:9:0::2;60170:6;60178:5;60185:3;60103:86;;;;;;;;;;;;;;;;;;60196:38;60225:8;60196:28;:38::i;:::-;53053:1;;;;;52931::::1;;58968:1272:::0;;;;;:::o;50431:117::-;-1:-1:-1;;50431:117:0;:::o;52417:30::-;;;;:::o;57787:1131::-;52805:17;;;;:7;:17;;;;;:35;57921:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;57939:8;57949:16:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;57974:21:::2;57998:17:::0;;;:7:::2;:17;::::0;;;;;58040:9:::2;::::0;58073:41:::2;58040:9:::0;58006:8;58104:9;58073:13:::2;:41::i;:::-;58056:58;;58139:21;58129:6;:31;;58121:74;;;;-1:-1:-1::0;;;58121:74:0::2;;;;;;;;;58281:11;::::0;::::2;:17:::0;58251::::2;::::0;50585:6:::2;::::0;58271:28:::2;::::0;:5;;:28:::2;:9;:28;:::i;:::-;:34;;;;;58337:22:::0;;;;58271:34;;::::2;::::0;-1:-1:-1;58337:37:0::2;::::0;58271:34;58337:37:::2;:26;:37;:::i;:::-;58312:22:::0;;;:62;58381:22:::2;58406:20;:5:::0;58416:9;58406:20:::2;:9;:20;:::i;:::-;58435:29;58467:26:::0;;;:15:::2;::::0;::::2;:26;::::0;;;;58381:45;;-1:-1:-1;58552:43:0::2;58570:8:::0;58381:45;58552:17:::2;:43::i;:::-;58612:24:::0;;;;:34;-1:-1:-1;58612:34:0::2;58604:85;;;;-1:-1:-1::0;;;58604:85:0::2;;;;;;;;;58698:70;58728:10;58740:8;58750:9;58761:6;58698:29;:70::i;:::-;58827:8:::0;58809:16:::2;58797:10;-1:-1:-1::0;;;;;58782:85:0::2;-1:-1:-1::0;;;;;;;;;;;58837:9:0::2;58848:6;58856:5;58863:3;58782:85;;;;;;;;;;55803:903:::0;55920:7;55960:17;;;:7;:17;;;;;55986:31;56020:33;55968:8;56020:23;:33::i;:::-;55986:67;;56060:23;56086:47;50585:6;56097:29;56108:6;:11;;:17;;;56097:6;:10;;:29;;;;:::i;:::-;:35;;;;;56086:6;;56097:35;;56086:47;:10;:47;:::i;:::-;56060:73;;56140:27;56170:14;56185:9;56170:25;;;;;;;;;;;;;;56140:55;;56202:28;56233;50585:6;56233:19;:23;;:28;;;;:::i;:::-;56202:59;-1:-1:-1;56273:9:0;56268:267;56292:14;:21;56288:1;:25;56268:267;;;56338:9;56333:1;:14;56329:199;;56360:21;56384:14;56399:1;56384:17;;;;;;;;;;;;;;56360:41;;56435:83;56483:34;56501:15;56483:13;:17;;:34;;;;:::i;:::-;56435:39;:20;56460:13;56435:39;:24;:39;:::i;:::-;:47;:83;:47;:83;:::i;:::-;56412:106;;56329:199;;56315:3;;56268:267;;;;56572:1;56549:20;:24;56541:64;;;;-1:-1:-1;;;56541:64:0;;;;;;;;;56621:79;56666:33;:20;50585:6;56666:33;:28;:33;:::i;:::-;56621:40;:19;56645:15;56621:40;:23;:40;:::i;:::-;:44;:79;:44;:79;:::i;:::-;56614:86;55803:903;-1:-1:-1;;;;;;;;;55803:903:0:o;76830:175::-;76896:7;76936:17;;;:7;:17;;;;;76970:28;;;;76830:175::o;78226:393::-;78289:4;78326:17;;;:7;:17;;;;;78428:20;78412:12;;;;;;:36;;;;;;;;;78408:71;;78466:5;78459:12;;;;;78408:71;78589:17;;;:24;78558:27;;;;;:55;;;78226:393;-1:-1:-1;;78226:393:0:o;60296:188::-;52805:17;;;;:7;:17;;;;;:35;60384:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;60407:8;60417:16:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;60445:33:::2;60458:8;60468:9;60445:12;:33::i;:::-;52931:1:::1;;60296:188:::0;;:::o;68661:1061::-;68718:8;68728:20;;53013:17;;;;:7;:17;;;;;:23;;;;;:32;;;;;;;;;53005:41;;;;;;68757:21:::1;68781:17:::0;;;:7:::1;:17;::::0;;;;68841:19:::1;68789:8:::0;68841:9:::1;:19::i;:::-;68900:10;68914:1;68877:34:::0;;;:22:::1;::::0;::::1;:34;::::0;;;;;68869:86:::1;;;;-1:-1:-1::0;;;68869:86:0::1;;;;;;;;;68993:10;68970:34;::::0;;;:22:::1;::::0;::::1;:34;::::0;;;;;::::1;;:43;68962:95;;;;-1:-1:-1::0;;;68962:95:0::1;;;;;;;;;69134:22;69159:33;69183:8;69159:23;:33::i;:::-;69257:10;69199:13;69234:34:::0;;;:22:::1;::::0;::::1;:34;::::0;;;;;69134:58;;-1:-1:-1;69199:13:0;50585:6:::1;::::0;69215:54:::1;::::0;69134:58;;69215:54:::1;:18;:54;:::i;:::-;:60;;;;;;69199:76;;69351:5;69333:6;:14;;;:23;;69325:71;;;;-1:-1:-1::0;;;69325:71:0::1;;;;;;;;;69422:14;::::0;::::1;::::0;:25:::1;::::0;69441:5;69422:25:::1;:18;:25;:::i;:::-;69405:14;::::0;;::::1;:42:::0;;;;69477:10:::1;69454:34;::::0;;;:22:::1;::::0;;::::1;:34;::::0;;;;;;;:41;;-1:-1:-1;;69454:41:0::1;::::0;;::::1;::::0;;;69614:22:::1;::::0;::::1;:34:::0;;;;;;69509:172;;69587:8;;69454:22;;69477:10;-1:-1:-1;;;;;;;;;;;69509:172:0;::::1;::::0;69657:5;;69671:3:::1;::::0;69509:172:::1;;;;;;;;;;69690:26;::::0;:10:::1;::::0;:26;::::1;;;::::0;69710:5;;69690:26:::1;::::0;;;69710:5;69690:10;:26;::::1;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;69690:26:0;53053:1;;;68661:1061:::0;;;:::o;66351:1036::-;66407:8;66417:20;;53013:17;;;;:7;:17;;;;;:23;;;;;:32;;;;;;;;;53005:41;;;;;;66446:21:::1;66470:17:::0;;;:7:::1;:17;::::0;;;;;;;66550:27;;;;66534:44;;:15:::1;::::0;::::1;:44:::0;;;;;66626:10:::1;66595:42:::0;;:30;;;:42;;;;;;66587:101:::1;;;;-1:-1:-1::0;;;66587:101:0::1;;;;;;;;;66733:10;66703:41;::::0;;;:29;;;:41:::1;::::0;;;;;::::1;;:50;66695:109;;;;-1:-1:-1::0;;;66695:109:0::1;;;;;;;;;66889:10;66842:13;66858:42:::0;;;:30;;;:42:::1;::::0;;;;;66958:14:::1;::::0;::::1;::::0;:23;-1:-1:-1;66958:23:0::1;66950:71;;;;-1:-1:-1::0;;;66950:71:0::1;;;;;;;;;67047:14;::::0;::::1;::::0;:25:::1;::::0;67066:5;67047:25:::1;:18;:25;:::i;:::-;67030:14;::::0;;::::1;:42:::0;;;;67109:10:::1;67079:41;::::0;;;:29;;;:41:::1;::::0;;;;:48;;-1:-1:-1;;67079:48:0::1;::::0;;::::1;::::0;;67218:8;67183:26:::1;67235:27:::0;;;;67164:10:::1;67271:42;::::0;;;:30;;;:42:::1;::::0;;;;;;;67141:205;;67164:10;;-1:-1:-1;;;;;;;;;;;67141:205:0;::::1;::::0;67271:42;67322:5;;67336:3:::1;::::0;67141:205:::1;;52382:30:::0;;;-1:-1:-1;;;;;52382:30:0;;:::o;77011:264::-;77098:7;77114;77130;77163:33;77187:8;77163:23;:33::i;:::-;77198:34;77220:8;77230:1;77198:21;:34::i;:::-;77234;77256:8;77266:1;77234:21;:34::i;:::-;77155:114;;;;;;77011:264;;;;;:::o;52214:26::-;;;;:::o;78840:527::-;78929:7;78969:17;;;:7;:17;;;;;;;;79025:26;;;:15;;;:26;;;;;79080:20;79064:12;;;;;;:36;;;;;;;;;:65;;;;;79105:24;79120:8;79105:14;:24::i;:::-;79104:25;79064:65;79060:195;;;79210:27;;;;79197:40;;:50;;79246:1;79197:50;;;50585:6;79197:50;79190:57;;;;;;79060:195;79338:22;;;;;79298:24;;;;79270:91;;79338:22;79270:63;;50585:6;;79271:52;;79338:22;;79271:52;:26;:52;:::i;:::-;79270:58;:63;:58;:63;:::i;:::-;:67;:91;:67;:91;:::i;:::-;79263:98;;;;78840:527;;;;;:::o;63122:2429::-;52805:17;;;;:7;:17;;;;;:35;63229:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;63252:8;63262:16:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;63290:21:::2;63314:17:::0;;;:7:::2;:17;::::0;;;;;;;63371:10:::2;63348:34:::0;;:22:::2;::::0;::::2;:34:::0;;;;;;;:44;-1:-1:-1;63348:44:0::2;63340:90;;;;-1:-1:-1::0;;;63340:90:0::2;;;;;;;;;63471:19;63481:8;63471:9;:19::i;:::-;63530:65;63548:8;63558:6;63566:28;63530:17;:65::i;:::-;;63604:31;63638:33;63662:8;63638:23;:33::i;:::-;63604:67;;63678:28;63723:14;:21;63709:36;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;::::0;-1:-1;63709:36:0::2;-1:-1:-1::0;63678:67:0;-1:-1:-1;;;63752:18:0::2;63882:177;63906:14;:21;63902:1;:25;63882:177;;;63943:21;63967:14;63982:1;63967:17;;;;;;;;;;;;;;63943:41;;64010:13;63997:10;:26;63993:58;;;64038:13;64025:26;;63993:58;-1:-1:-1::0;63929:3:0::2;;63882:177;;;-1:-1:-1::0;64120:16:0::2;::::0;::::2;::::0;64067:23:::2;::::0;64093:44:::2;::::0;:22:::2;:6:::0;64104:10;64093:22:::2;:10;:22;:::i;:44::-;64067:70:::0;-1:-1:-1;64151:9:0::2;64146:195;64170:14;:21;64166:1;:25;64146:195;;;64256:6;:16;;;64224:29;64246:6;64224:14;64239:1;64224:17;;;;;;;;;;;;;;:21;;:29;;;;:::i;:::-;:48;;;;;;64207:11;64219:1;64207:14;;;;;;;;;;;;;:65;;;::::0;::::2;64298:35;64317:15;64298:11;64310:1;64298:14;;;;;;;;;;;;;;:18;;:35;;;;:::i;:::-;64281:11;64293:1;64281:14;;;;;;;;;::::0;;::::2;::::0;;;;;:52;64193:3:::2;;64146:195;;;;64388:49;64411:8;64421:15;64388:22;:49::i;:::-;64463:16;::::0;::::2;::::0;:28:::2;::::0;64484:6;64463:28:::2;:20;:28;:::i;:::-;64444:16;::::0;::::2;:47:::0;64612:10:::2;64589:34;::::0;;;:22:::2;::::0;::::2;:34;::::0;;;;;:46:::2;::::0;64628:6;64589:46:::2;:38;:46;:::i;:::-;64575:10;64552:34;::::0;;;:22:::2;::::0;::::2;:34;::::0;;;;:83;;;;64644:594:::2;64668:14;:21;64664:1;:25;64644:594;;;64726:1;64709:11;64721:1;64709:14;;;;;;;;;;;;;;:18;64705:526;;;64763:22;::::0;;::::2;::::0;64740:20:::2;64820:18:::0;;;:15:::2;::::0;::::2;:18;::::0;;;;:35;;;;64923:14;;64868:70:::2;::::0;64898:10:::2;::::0;64910:8;;64836:1;;64923:11;;64836:1;;64923:14;::::2;;;;;;;;;;;64868:29;:70::i;:::-;65033:8:::0;65004:16:::2;64981:10;-1:-1:-1::0;;;;;64954:267:0::2;-1:-1:-1::0;;;;;;;;;;;65054:1:0::2;65068:11;65080:1;65068:14;;;;;;;;;;;;;;65095:81;65153:6;:22;;;65095:53;65133:11;65145:1;65133:14;;;;;;;;;;;;;;65096:31;65113:13;65096:12;:16;;:31;;;;:::i;65095:81::-;65207:3;64954:267;;;;;;;;;;;;;;;;;;64705:526;;;64691:3;;64644:594;;;-1:-1:-1::0;65301:36:0::2;::::0;:10:::2;::::0;:36;::::2;;;::::0;65321:15;;65301:36:::2;::::0;;;65321:15;65301:10;:36;::::2;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;65408:8:0;65378:28:::2;65366:10;-1:-1:-1::0;;;;;65351:99:0::2;-1:-1:-1::0;;;;;;;;;;;65418:1:0::2;65421:6;65429:15;65446:3;65351:99;;;;;;;;;;;;;;;;;;65478:8;-1:-1:-1::0;;;;;;;;;;;65488:6:0::2;:16;;;65506:33;65530:8;65506:23;:33::i;:::-;65541:3;65462:83;;;;;;;;;;;;;;;;;53053:1;;;;;52931::::1;;63122:2429:::0;;;:::o;75442:226::-;75530:7;75570:17;;;:7;:17;;;;;;;;75645:16;;;;-1:-1:-1;;;;;75603:28:0;;;;:22;;;:28;;;;;;;75570:17;;75603:59;;:37;;50585:6;75603:37;:32;:37;:::i;:59::-;75596:66;75442:226;-1:-1:-1;;;;75442:226:0:o;69808:545::-;69867:21;69891:17;;;:7;:17;;;;;;69941:42;69899:8;69972:10;69941:20;:42::i;:::-;69917:66;-1:-1:-1;69996:17:0;;69992:167;;70078:10;70058:31;;;;:19;;;:31;;;;;;:50;;70094:13;70058:50;:35;:50;:::i;:::-;70044:10;70024:31;;;;:19;;;:31;;;;;;:84;;;;70117:34;;70044:10;;70117:34;;;;;70137:13;;70117:34;70024:31;70117:34;70137:13;70044:10;70117:34;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;70117:34:0;69992:167;70245:8;70214:22;70195:10;70262:1;70272:34;;;:22;;;:34;;;;;;;70172:175;;-1:-1:-1;;;;;;;;;;;70172:175:0;;;70262:1;;70315:13;;70337:3;;70172:175;;;;;;;;;;69808:545;;;:::o;74355:365::-;74460:7;74541:17;;;:7;:17;;;;;;;;-1:-1:-1;;;;;74583:28:0;;;;;;;:22;;;;:28;;;;;;74620:18;;;:15;;;;:18;;;;;;:39;;;:33;;:39;;;;;;74668:18;;;;;;;;:39;;;:33;:39;;;;;;;74583:28;;74355:365::o;77908:312::-;77981:6;78020:17;;;:7;:17;;;;;78116:20;78100:12;;;;;;:36;;;;;;;;;78096:68;;-1:-1:-1;;78147:9:0;;;;;78096:68;78186:27;;;;77908:312;-1:-1:-1;;77908:312:0:o;76083:439::-;76168:11;76300:17;;;:7;:17;;;;;;;76342:12;;;;76363:24;;76396:16;;;;76421:14;;;;76444:22;;;;76168:11;;;;;;;;;;76300:17;;76342:12;;;;;76363:24;;76396:16;;76475:34;76308:8;76475:24;:34::i;:::-;76326:190;;;;-1:-1:-1;76326:190:0;;-1:-1:-1;76326:190:0;-1:-1:-1;76326:190:0;-1:-1:-1;76326:190:0;;-1:-1:-1;76083:439:0;-1:-1:-1;;;76083:439:0:o;50555:36::-;50585:6;50555:36;:::o;56814:924::-;56932:30;56995:17;;;:7;:17;;;;;57021:31;57055:33;57003:8;57055:23;:33::i;:::-;57146:11;;;:17;57021:67;;-1:-1:-1;57095:22:0;;57138:26;;50585:6;;57138:26;:7;:26;:::i;:::-;57120:15;:6;50585;57120:15;:10;:15;:::i;:::-;:44;;;;;;57095:69;;57171:28;57202:14;57217:9;57202:25;;;;;;;;;;;;;;57171:56;;57234:28;57265:29;50585:6;57265:20;:24;;:29;;;;:::i;:::-;57234:60;-1:-1:-1;57306:9:0;57301:266;57325:14;:21;57321:1;:25;57301:266;;;57371:9;57366:1;:14;57362:198;;57393:21;57417:14;57432:1;57417:17;;;;;;;;;;;;;;57393:41;;57468:82;57516:33;57534:14;57516:13;:17;;:33;;;;:::i;57468:82::-;57445:105;;57362:198;;57348:3;;57301:266;;;;57604:1;57581:20;:24;57573:64;;;;-1:-1:-1;;;57573:64:0;;;;;;;;;57653:79;57711:20;57653:53;57672:33;:20;50585:6;57672:33;:28;:33;:::i;:::-;57653:14;;:53;:18;:53;:::i;77281:621::-;77353:7;77393:17;;;:7;:17;;;;;77439:20;77423:12;;;;;;:36;;;;;;;;;:65;;;;;77464:24;77479:8;77464:14;:24::i;:::-;77463:25;77423:65;77419:305;;;77699:16;;;;77640:27;;;;77624:44;;;;:15;;;:44;;;;;:61;;;:92;;77699:16;77624:70;;50585:6;77624:70;:65;:70;:::i;:92::-;77617:99;;;;;77419:305;77873:22;;;;77843:17;;;:24;77816:16;;;;:80;;77873:22;77816:52;;:16;50585:6;77837:30;77816:52;:20;:52;:::i;:80::-;77809:87;77281:621;-1:-1:-1;;;77281:621:0:o;52264:18::-;;;;:::o;75987:90::-;76030:16;76062:9;76055:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75987:90;:::o;67468:1104::-;67564:8;67574:20;;53013:17;;;;:7;:17;;;;;:23;;;;;:32;;;;;;;;;53005:41;;;;;;67606:21:::1;67630:17:::0;;;:7:::1;:17;::::0;;;;;;;67686:26;;;:15:::1;::::0;::::1;:26:::0;;;;;67752:10:::1;67729:34:::0;;:22;;;:34;;;;;;67721:84:::1;;;;-1:-1:-1::0;;;67721:84:0::1;;;;;;;;;67848:10;67820:39;::::0;;;:27;;;:39:::1;::::0;;;;;::::1;;:48;67812:96;;;;-1:-1:-1::0;;;67812:96:0::1;;;;;;;;;67980:13;67996:42;68018:8;68028:9;67996:21;:42::i;:::-;68094:10;68045:13;68071:34:::0;;;:22;;;:34:::1;::::0;;;;;67980:58;;-1:-1:-1;68045:13:0;68061:54:::1;::::0;50585:6:::1;::::0;68061:45:::1;::::0;67980:58;;68061:45:::1;:9;:45;:::i;:54::-;68045:70;;68191:5;68173:6;:14;;;:23;;68165:71;;;;-1:-1:-1::0;;;68165:71:0::1;;;;;;;;;68262:14;::::0;::::1;::::0;:25:::1;::::0;68281:5;68262:25:::1;:18;:25;:::i;:::-;68245:14;::::0;;::::1;:42:::0;;;;68322:10:::1;68294:39;::::0;;;:27;;;:39:::1;::::0;;;;:46;;-1:-1:-1;;68294:46:0::1;::::0;;::::1;::::0;;68429:8;68396:24:::1;68377:10;68464:34;::::0;;;:22;;;:34:::1;::::0;;;;;;;68354:177;;-1:-1:-1;;;;;;;;;;;68354:177:0;::::1;::::0;68446:9;;68464:34;68507:5;;68521:3:::1;::::0;68354:177:::1;;;;;;;;;;68540:26;::::0;:10:::1;::::0;:26;::::1;;;::::0;68560:5;;68540:26:::1;::::0;;;68560:5;68540:10;:26;::::1;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;68540:26:0;53053:1;;;;67468:1104:::0;;;;:::o;54000:1724::-;53360:15;;53329:5;;:27;;-1:-1:-1;;;53329:27:0;;54203:7;;53360:15;-1:-1:-1;;;;;53329:5:0;;:15;;:27;;53345:10;;53329:27;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53329:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53329:27:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;53329:27:0;;;;;;;;;:46;;53321:101;;;;-1:-1:-1;;;53321:101:0;;;;;;;;;54238:11:::1;::::0;54219:16:::1;27:10:-1::0;;39:1:::1;23:18:::0;;::::1;45:23:::0;;54256:24:0;;;::::1;::::0;;;54313:17;;;54256:24:::1;54313:17:::0;;;;54347:9:::1;54339:47;;;;-1:-1:-1::0;;;54339:47:0::1;;;;;;;;;54413:3;54401:8;:15;;54393:70;;;;-1:-1:-1::0;;;54393:70:0::1;;;;;;;;;54590:8;54602:1;54590:13;54582:56;;;;-1:-1:-1::0;;;54582:56:0::1;;;;;;;;;54647:35:::0;;;54689:12:::1;::::0;::::1;:31:::0;;-1:-1:-1;;54689:31:0::1;::::0;;54747:3:::1;::::0;54727:11:::1;::::0;::::1;:23:::0;-1:-1:-1;;54835:27:0;;;:42;54647:24:::1;54919:201;54943:8;54939:1;:12;54919:201;;;54967:17;::::0;::::1;27:10:-1::0;;39:1:::1;23:18:::0;;::::1;45:23:::0;;-1:-1;54967:25:0;;;::::1;::::0;;;;;::::1;::::0;;;55033:18;;;:15:::1;::::0;::::1;:18:::0;;;;;;;55062:27;;;55098:10;::::1;:14:::0;;;54953:3:::1;54919:201;;;-1:-1:-1::0;55205:15:0::1;::::0;;55348::::1;::::0;55261:155:::1;::::0;-1:-1:-1;;;55261:155:0;;-1:-1:-1;;;;;55205:15:0;;::::1;::::0;;;55261:25:::1;::::0;:155:::1;::::0;55295:1:::1;::::0;55305:8;;55322:10;;55348:15;;55380:8;;55166:22:::1;::::0;;;55261:155:::1;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::1;5:2;55261:155:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;55261:155:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;55261:155:0;;;;;;;;;55230:28:::0;;;:186;55425:33:::1;55438:8:::0;55448:9:::1;55425:12;:33::i;:::-;55504:38;55533:8;55504:28;:38::i;:::-;55580:8;55568:10;-1:-1:-1::0;;;;;55554:62:0::1;;55590:8;55600;55610:5;55554:62;;;;;;;;;;;;;;;;;-1:-1:-1::0;;55679:11:0::1;::::0;;55693:1:::1;55679:15;55665:29:::0;;55710:8;54000:1724;-1:-1:-1;;;;;;54000:1724:0:o;79373:388::-;79484:7;79565:17;;;:7;:17;;;;;;;;79621:26;;;:15;;;:26;;;;;79484:7;;;;79664:42;79573:8;79637:9;79664:21;:42::i;:::-;79708:24;;;;:14;;;;79734:20;79656:99;;79708:24;;-1:-1:-1;79734:20:0;-1:-1:-1;79373:388:0;-1:-1:-1;;;;79373:388:0:o;52474:19::-;;;-1:-1:-1;;;;;52474:19:0;;:::o;75674:307::-;75757:7;75797:17;;;:7;:17;;;;;;;;75904:16;;;;-1:-1:-1;;;;;75870:28:0;;;;:22;;;:28;;;;;;;75843:22;;;;75797:17;;75757:7;;75843:78;;:56;;:22;:56;:26;:56;:::i;:78::-;-1:-1:-1;;;;;75949:25:0;;;;;;:19;;;:25;;;;;;75823:98;;-1:-1:-1;75935:40:0;;75823:98;;75935:40;:13;:40;:::i;71181:159::-;71233:21;71257:17;;;:7;:17;;;;;71316:12;;;;;;71308:21;;;;;;;;71332:1;71308:25;71296:38;;;;;;;;71281:12;;;:53;;-1:-1:-1;;71281:53:0;;;;;;;;;;;;;;;;71181:159;;:::o;71404:415::-;71475:21;71499:17;;;:7;:17;;;;;;71525:149;71549:17;;;:24;71545:28;;71525:149;;;71623:1;71613:8;71594:72;71626:34;71648:8;71658:1;71626:21;:34::i;:::-;71662:3;71594:72;;;;;;;;;;;;;;;;71575:3;;71525:149;;;;71746:8;-1:-1:-1;;;;;;;;;;;71756:6:0;:16;;;71774:33;71798:8;71774:23;:33::i;:::-;71809:3;71730:83;;;;;;;;;;;;;;;;;71404:415;;:::o;73771:507::-;73915:21;73939:17;;;:7;:17;;;;;;;;73995:26;;;:15;;;:26;;;;;-1:-1:-1;;;;;74096:28:0;;;;:22;;;:28;;;;;;:40;;74129:6;74096:40;:32;:40;:::i;:::-;-1:-1:-1;;;;;74065:28:0;;;;;;:22;;;:28;;;;;:71;74170:24;;;;:36;;74199:6;74170:36;:28;:36;:::i;:::-;74143:24;;;;:63;;;;74238:22;;;:34;;74265:6;74238:34;:26;:34;:::i;:::-;74213:6;:22;;:59;;;;73771:507;;;;;;:::o;44933:158::-;44991:7;45024:1;45019;:6;;45011:49;;;;-1:-1:-1;;;45011:49:0;;;;;;;;;-1:-1:-1;45078:5:0;;;44933:158::o;45350:220::-;45408:7;45432:6;45428:20;;-1:-1:-1;45447:1:0;45440:8;;45428:20;45471:5;;;45475:1;45471;:5;:1;45495:5;;;;;:10;45487:56;;;;-1:-1:-1;;;45487:56:0;;;;;;;;44471:179;44529:7;44561:5;;;44585:6;;;;44577:46;;;;-1:-1:-1;;;44577:46:0;;;;;;;;72511:593;72592:21;72616:17;;;:7;:17;;;;;;72642:405;72666:17;;;:24;72662:28;;72642:405;;;72706:29;72738:18;;;:15;;;:18;;;;;72794:24;;;;:36;;72823:6;72794:36;:28;:36;:::i;:::-;72767:24;;;:63;:14;;;72862:20;:32;;72887:6;72862:32;:24;:32;:::i;:::-;72839:14;;;:55;73005:22;;;;:34;;73032:6;73005:34;:26;:34;:::i;:::-;72980:22;;;:59;-1:-1:-1;72692:3:0;;72642:405;;;-1:-1:-1;73072:14:0;;;;:26;;73091:6;73072:26;:18;:26;:::i;:::-;73055:14;;;;:43;-1:-1:-1;;72511:593:0:o;71872:581::-;71948:21;71972:17;;;:7;:17;;;;;;71998:398;72022:17;;;:24;72018:28;;71998:398;;;72062:29;72094:18;;;:15;;;:18;;;;;72150:24;;;;:36;;72179:6;72150:36;:28;:36;:::i;:::-;72123:24;;;:63;:14;;;72218:20;:32;;72243:6;72218:32;:24;:32;:::i;:::-;72195:14;;;:55;72354:22;;;;:34;;72381:6;72354:34;:26;:34;:::i;:::-;72329:22;;;:59;-1:-1:-1;72048:3:0;;71998:398;;;-1:-1:-1;72421:14:0;;;;:26;;72440:6;72421:26;:18;:26;:::i;73172:526::-;73318:21;73342:17;;;:7;:17;;;;;;;;73398:26;;;:15;;;:26;;;;;-1:-1:-1;;;;;73516:28:0;;;;:22;;;:28;;;;;;:40;;73549:6;73516:40;:32;:40;:::i;:::-;-1:-1:-1;;;;;73485:28:0;;;;;;:22;;;:28;;;;;:71;73590:24;;;;:36;;73619:6;73590:36;:28;:36;:::i;:::-;73563:24;;;;:63;;;;73658:22;;;:34;;73685:6;73658:34;:26;:34;:::i;79767:366::-;79865:21;79889:17;;;:7;:17;;;;;;;;;79955;;;:24;79941:39;;;;;;;;;;;;;;;;79840:16;;79889:17;;79840:16;;79941:39;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;79941:39:0;-1:-1:-1;79915:65:0;-1:-1:-1;79992:9:0;79987:119;80011:17;;;:24;80007:28;;79987:119;;;80063:18;;;;:15;;;:18;;;;;:35;;;80051:9;;:6;;80079:1;;80051:9;;;;;;;;;;;;;;;:47;80037:3;;79987:119;;;-1:-1:-1;80121:6:0;79767:366;-1:-1:-1;;;79767:366:0:o;49322:138::-;49384:7;49404:5;;49400:35;;49429:1;49424;49420;:5;49419:11;;;;;;49434:1;49418:17;49411:24;;;;49400:35;49453:1;49449;:5;;;;;;;49322:138;-1:-1:-1;;;49322:138:0:o;60558:2505::-;52805:17;;;;:7;:17;;;;;:35;60647:8;;52799:3;:41;:88;;;;-1:-1:-1;52871:16:0;52844:17;;;:7;:17;;;;;:23;;;;;:43;;;;;;;;;52799:88;52795:130;;;52898:19;52908:8;52898:9;:19::i;:::-;60670:8;60680:16:::1;::::0;53013:17:::1;::::0;;;:7:::1;:17;::::0;;;;:23:::1;;::::0;::::1;;:32;::::0;::::1;;;;;;;53005:41;;;::::0;::::1;;60708:21:::2;60732:17:::0;;;:7:::2;:17;::::0;;;;60766:9;60758:53:::2;;;;-1:-1:-1::0;;;60758:53:0::2;;;;;;;;;60820:23;60852:31;60886:33;60910:8;60886:23;:33::i;:::-;60852:67;;60926:32;60975:14;:21;60961:36;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;::::0;-1:-1;60961:36:0::2;-1:-1:-1::0;61039:16:0::2;::::0;::::2;::::0;60926:71;;-1:-1:-1;61004:18:0::2;::::0;61039:20;61035:784:::2;;61165:9;61160:183;61184:14;:21;61180:1;:25;61160:183;;;61223:21;61247:14;61262:1;61247:17;;;;;;;;;;;;;;61223:41;;61292:13;61279:10;:26;61275:58;;;61320:13;61307:26;;61275:58;-1:-1:-1::0;61207:3:0::2;;61160:183;;;-1:-1:-1::0;61358:9:0::2;61353:186;61377:14;:21;61373:1;:25;61353:186;;;61416:17;61467:10;61436:28;61446:14;61461:1;61446:17;;;;;;;;;;;;;;61436:5;:9;;:28;;;;:::i;:::-;:41;;;;;;::::0;-1:-1:-1;61509:20:0::2;:5:::0;61436:41;61509:20:::2;:9;:20;:::i;:::-;61488:15;61504:1;61488:18;;;;;;;;;::::0;;::::2;::::0;;;;;:41;-1:-1:-1;61400:3:0::2;;61353:186;;;;61597:10;61567:27;61577:6;:16;;;61567:5;:9;;:27;;;;:::i;:::-;:40;;;;;;61549:58;;61651:71;61669:8;61679:15;61696:25;61651:17;:71::i;:::-;;61035:784;;;61806:5;61788:23;;61035:784;61869:16;::::0;::::2;::::0;:37:::2;::::0;61890:15;61869:37:::2;:20;:37;:::i;:::-;61850:16;::::0;::::2;:56:::0;61973:10:::2;61950:34;::::0;;;:22:::2;::::0;::::2;:34;::::0;;;;;:55:::2;::::0;61989:15;61950:55:::2;:38;:55;:::i;:::-;61936:10;61913:34;::::0;;;:22:::2;::::0;::::2;:34;::::0;;;;:92;62014:34:::2;62032:8:::0;62042:5;62014:17:::2;:34::i;:::-;62122:9;62117:609;62141:15;:22;62137:1;:26;62117:609;;;62204:1;62183:15;62199:1;62183:18;;;;;;;;;;;;;;:22;62179:540;;;62241:22;::::0;;::::2;::::0;62218:20:::2;62298:18:::0;;;:15:::2;::::0;::::2;:18;::::0;;;;:35;;;;62399:18;;62344:74:::2;::::0;62374:10:::2;::::0;62386:8;;62314:1;;62399:15;;62314:1;;62399:18;::::2;;;;62344:74;62513:8:::0;62484:16:::2;62461:10;-1:-1:-1::0;;;;;62434:275:0::2;-1:-1:-1::0;;;;;;;;;;;62534:1:0::2;62548:15;62564:1;62548:18;;;;;;;;;;;;;;62579:85;62641:6;:22;;;62579:57;62617:15;62633:1;62617:18;;;;;;;62579:85;62695:3;62434:275;;;;;;;;;;;;;;;;;;62179:540;;;62165:3;;62117:609;;;;62734:22;62759:33;62783:8;62759:23;:33::i;:::-;62734:58:::0;-1:-1:-1;62799:22:0::2;50585:6;62824:35;62734:58:::0;62843:15;62824:35:::2;:18;:35;:::i;:::-;:41;;;;;;::::0;-1:-1:-1;62931:8:0;62904:25:::2;62892:10;-1:-1:-1::0;;;;;62877:104:0::2;-1:-1:-1::0;;;;;;;;;;;62941:1:0::2;62944:15;62961:14;62977:3;62877:104;;;;;;;;;;;;;;;;;;63009:8;-1:-1:-1::0;;;;;;;;;;;63019:6:0::2;:16;;;63037:14;63053:3;62993:64;;;;;;;;;;;;;;;;;53053:1;;;;;;;52931::::1;;60558:2505:::0;;;:::o;46048:153::-;46106:7;46138:1;46134;:5;46126:44;;;;-1:-1:-1;;;46126:44:0;;;;;;;;70449:681;70577:7;70617:17;;;:7;:17;;;;;70712:16;;;;70684:22;;;;70577:7;;70664:65;;:43;;:15;;:43;:19;:43;:::i;:65::-;70643:86;-1:-1:-1;70752:25:0;70742:6;:35;;;;;;;;;70738:387;;;70813:22;;;;:38;;70840:10;70813:38;:26;:38;:::i;:::-;70788:22;;;:63;70914:10;70894:31;;;;:19;;;:31;;;;;;:47;;70930:10;70894:47;:35;:47;:::i;:::-;70880:10;70860:31;;;;:19;;;:31;;;;;:81;70738:387;;;70989:22;;;;:38;;71016:10;70989:38;:26;:38;:::i;:::-;70964:22;;;:63;71090:10;71070:31;;;;:19;;;:31;;;;;;:47;;71106:10;71070:47;:35;:47;:::i;:::-;71056:10;71036:31;;;;:19;;;:31;;;;;:81;70738:387;70449:681;;;;;;;:::o;5:130:-1:-;72:20;;-1:-1;;;;;34731:54;;36732:35;;36722:2;;36781:1;;36771:12;284:442;;386:3;379:4;371:6;367:17;363:27;353:2;;-1:-1;;394:12;353:2;428:20;;-1:-1;;;;;33076:30;;;33073:2;;;-1:-1;;33109:12;33073:2;32742;32736:9;33182;33163:17;;-1:-1;;33159:33;32768:17;;33250:4;32768:17;32828:34;;;32864:22;;;32825:62;32822:2;;;-1:-1;;32890:12;32822:2;32742;32909:22;534:21;;;454:74;-1:-1;454:74;634:16;;;33250:4;634:16;631:25;-1:-1;628:2;;;669:1;;659:12;628:2;36105:6;33250:4;576:6;572:17;33250:4;610:5;606:16;36082:30;36161:1;33250:4;36152:6;610:5;36143:16;;36136:27;;;;346:380;;;;;1012:263;;1127:2;1115:9;1106:7;1102:23;1098:32;1095:2;;;-1:-1;;1133:12;1095:2;-1:-1;220:13;;1089:186;-1:-1;1089:186;1282:955;;;;;;1474:3;1462:9;1453:7;1449:23;1445:33;1442:2;;;-1:-1;;1481:12;1442:2;1526:31;;-1:-1;;;;;1566:30;;;1563:2;;;-1:-1;;1599:12;1563:2;1629:63;1684:7;1675:6;1664:9;1660:22;1629:63;;;1619:73;;1757:2;1746:9;1742:18;1729:32;1715:46;;1577:18;1773:6;1770:30;1767:2;;;-1:-1;;1803:12;1767:2;;1833:63;1888:7;1879:6;1868:9;1864:22;1833:63;;;1823:73;;;1933:2;1976:9;1972:22;801:20;1941:63;;2059:53;2104:7;2041:2;2084:9;2080:22;2059:53;;;1436:801;;;;-1:-1;1436:801;;2149:3;2189:22;801:20;;1436:801;-1:-1;;1436:801;2244:241;;2348:2;2336:9;2327:7;2323:23;2319:32;2316:2;;;-1:-1;;2354:12;2316:2;-1:-1;801:20;;2310:175;-1:-1;2310:175;2762:366;;;2883:2;2871:9;2862:7;2858:23;2854:32;2851:2;;;-1:-1;;2889:12;2851:2;814:6;801:20;2941:63;;3059:53;3104:7;3041:2;3084:9;3080:22;3059:53;;;3049:63;;2845:283;;;;;;3135:366;;;3256:2;3244:9;3235:7;3231:23;3227:32;3224:2;;;-1:-1;;3262:12;3224:2;-1:-1;;801:20;;;3414:2;3453:22;;;801:20;;-1:-1;3218:283;3508:491;;;;3646:2;3634:9;3625:7;3621:23;3617:32;3614:2;;;-1:-1;;3652:12;3614:2;-1:-1;;801:20;;;3804:2;3843:22;;801:20;;-1:-1;3912:2;3951:22;;;801:20;;3608:391;-1:-1;3608:391;4006:617;;;;;4161:3;4149:9;4140:7;4136:23;4132:33;4129:2;;;-1:-1;;4168:12;4129:2;-1:-1;;801:20;;;4320:2;4359:22;;801:20;;-1:-1;4428:2;4467:22;;801:20;;4536:2;4575:22;801:20;;-1:-1;4123:500;-1:-1;4123:500;6776:347;;6921:5;33533:12;33949:6;33944:3;33937:19;-1:-1;36250:101;36264:6;36261:1;36258:13;36250:101;;;33986:4;36331:11;;;;;36325:18;36312:11;;;;;36305:39;36279:10;36250:101;;;36366:6;36363:1;36360:13;36357:2;;;-1:-1;33986:4;36422:6;33981:3;36413:16;;36406:27;36357:2;-1:-1;33182:9;36522:14;-1:-1;;36518:28;7079:39;;;;33986:4;7079:39;;6868:255;-1:-1;;6868:255;15829:213;-1:-1;;;;;34731:54;;;;5032:37;;15947:2;15932:18;;15918:124;16285:361;16453:2;16467:47;;;33533:12;;16438:18;;;33937:19;;;16285:361;;16453:2;33387:14;;;;33977;;;;16285:361;5520:260;5545:6;5542:1;5539:13;5520:260;;;5606:13;;5992:37;;33792:14;;;;4784;;;;5567:1;5560:9;5520:260;;;-1:-1;16520:116;;16424:222;-1:-1;;;;;;16424:222;16653:201;34341:13;;34334:21;5875:34;;16765:2;16750:18;;16736:118;16861:611;34341:13;;34334:21;5875:34;;34341:13;;34334:21;17220:2;17205:18;;5875:34;34341:13;;34334:21;17297:2;17282:18;;5875:34;34341:13;34334:21;17374:2;17359:18;;5875:34;17457:3;17442:19;;5992:37;17067:3;17052:19;;17038:434;17479:213;5992:37;;;17597:2;17582:18;;17568:124;17945:795;18215:3;18200:19;;36644:1;36634:12;;36624:2;;36650:9;36624:2;6285:64;;;18394:2;18379:18;;5992:37;;;;18477:2;18462:18;;5992:37;;;;18560:2;18545:18;;5992:37;;;;18643:3;18628:19;;5992:37;18725:3;18710:19;;;5992:37;18186:554;;18963:563;6557:58;;;19346:2;19331:18;;5992:37;;;;19429:2;19414:18;;5992:37;19512:2;19497:18;;5992:37;19173:3;19158:19;;19144:382;19533:1011;;35621:24;6564:3;6557:58;19859:3;19986:2;19975:9;19971:18;19964:48;20026:78;19859:3;19848:9;19844:19;20090:6;20026:78;;;-1:-1;;;;;34731:54;;;;20183:2;20168:18;;5032:37;-1:-1;34948:10;34937:22;;;20264:2;20249:18;;15781:36;34937:22;;;;20345:3;20330:19;;15781:36;34742:42;20422:19;;6557:58;20529:3;20514:19;6557:58;20018:86;19830:714;-1:-1;;19830:714;20551:407;20742:2;20756:47;;;7355:2;20727:18;;;33937:19;-1:-1;;;33977:14;;;7371:50;7440:12;;;20713:245;20965:407;21156:2;21170:47;;;7691:2;21141:18;;;33937:19;-1:-1;;;33977:14;;;7707:44;7770:12;;;21127:245;21379:407;21570:2;21584:47;;;8021:2;21555:18;;;33937:19;8057:34;33977:14;;;8037:55;-1:-1;;;8112:12;;;8105:25;8149:12;;;21541:245;21793:407;21984:2;21998:47;;;8400:2;21969:18;;;33937:19;-1:-1;;;33977:14;;;8416:50;8485:12;;;21955:245;22207:407;22398:2;22412:47;;;8736:2;22383:18;;;33937:19;8772:34;33977:14;;;8752:55;-1:-1;;;8827:12;;;8820:34;8873:12;;;22369:245;22621:407;22812:2;22826:47;;;9124:2;22797:18;;;33937:19;9160:32;33977:14;;;9140:53;9212:12;;;22783:245;23035:407;23226:2;23240:47;;;9463:2;23211:18;;;33937:19;9499:33;33977:14;;;9479:54;9552:12;;;23197:245;23449:407;23640:2;23654:47;;;9803:2;23625:18;;;33937:19;9839:32;33977:14;;;9819:53;9891:12;;;23611:245;23863:407;24054:2;24068:47;;;10142:2;24039:18;;;33937:19;10178:34;33977:14;;;10158:55;-1:-1;;;10233:12;;;10226:27;10272:12;;;24025:245;24277:407;24468:2;24482:47;;;10523:2;24453:18;;;33937:19;-1:-1;;;33977:14;;;10539:49;10607:12;;;24439:245;24691:407;24882:2;24896:47;;;10858:2;24867:18;;;33937:19;10894:34;33977:14;;;10874:55;-1:-1;;;10949:12;;;10942:34;10995:12;;;24853:245;25105:407;25296:2;25310:47;;;11246:2;25281:18;;;33937:19;11282:34;33977:14;;;11262:55;-1:-1;;;11337:12;;;11330:38;11387:12;;;25267:245;25519:407;25710:2;25724:47;;;11638:2;25695:18;;;33937:19;11674:34;33977:14;;;11654:55;-1:-1;;;11729:12;;;11722:25;11766:12;;;25681:245;25933:407;26124:2;26138:47;;;12017:2;26109:18;;;33937:19;12053:34;33977:14;;;12033:55;-1:-1;;;12108:12;;;12101:34;12154:12;;;26095:245;26347:407;26538:2;26552:47;;;12405:2;26523:18;;;33937:19;12441:34;33977:14;;;12421:55;-1:-1;;;12496:12;;;12489:31;12539:12;;;26509:245;26761:407;26952:2;26966:47;;;12790:2;26937:18;;;33937:19;12826:34;33977:14;;;12806:55;-1:-1;;;12881:12;;;12874:27;12920:12;;;26923:245;27175:407;27366:2;27380:47;;;13171:2;27351:18;;;33937:19;13207:34;33977:14;;;13187:55;-1:-1;;;13262:12;;;13255:27;13301:12;;;27337:245;27589:407;27780:2;27794:47;;;13552:2;27765:18;;;33937:19;13588:34;33977:14;;;13568:55;-1:-1;;;13643:12;;;13636:25;13680:12;;;27751:245;28003:407;28194:2;28208:47;;;13931:2;28179:18;;;33937:19;13967:34;33977:14;;;13947:55;-1:-1;;;14022:12;;;14015:30;14064:12;;;28165:245;28831:407;29022:2;29036:47;;;14650:2;29007:18;;;33937:19;14686:32;33977:14;;;14666:53;14738:12;;;28993:245;29245:407;29436:2;29450:47;;;14989:2;29421:18;;;33937:19;-1:-1;;;33977:14;;;15005:51;15075:12;;;29407:245;29659:407;29850:2;29864:47;;;15326:2;29835:18;;;33937:19;15362:34;33977:14;;;15342:55;-1:-1;;;15417:12;;;15410:27;15456:12;;;29821:245;30293:435;5992:37;;;30631:2;30616:18;;5992:37;;;;30714:2;30699:18;;5992:37;30467:2;30452:18;;30438:290;30735:611;;6022:5;5999:3;5992:37;30949:2;31067;31056:9;31052:18;31045:48;31107:78;30949:2;30938:9;30934:18;31171:6;31107:78;;;31233:9;31227:4;31223:20;31218:2;31207:9;31203:18;31196:48;31258:78;31331:4;31322:6;31258:78;;;31250:86;30920:426;-1:-1;;;;;;30920:426;31353:324;5992:37;;;31663:2;31648:18;;5992:37;31499:2;31484:18;;31470:207
Swarm Source
ipfs://bb3570dbb9f12939d26e065d1baf2ae8ff33a6895b5447dba96d743778cfc85b
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.