github.com/diadata-org/diadata@v1.4.593/contracts/Dispute.sol (about) 1 pragma solidity 0.4.25; 2 3 import "./DIAToken.sol"; 4 import "zos-lib/contracts/Initializable.sol"; 5 import "openzeppelin-eth/contracts/math/SafeMath.sol"; 6 7 contract Dispute is Initializable { 8 using SafeMath for uint; 9 // DIA token 10 DIAToken private dia_; 11 // Event to emit when a dispute is open 12 event DisputeOpen(uint256 _id, uint _deadline); 13 // Event to emit when a dispute is finalized 14 event DisputeClosed(uint256 _id, bool _result); 15 // How many blocks should we wait before the dispute can be closed 16 uint private DISPUTE_LENGTH; 17 // How many token a user should stake on each vote 18 uint private VOTE_COST; 19 // Disputes 20 mapping (uint256=>Disputes) private disputes_; 21 // Rewards that each voter can claim 22 mapping (address=>uint256) public rewards_; 23 24 struct Disputes{ 25 // Block number to finalize dispute 26 uint deadline; 27 // Array of voters 28 Voter[] voters; 29 // Voters index in the voters array 30 mapping(address=>uint) votersIndex; 31 } 32 // Voters 33 struct Voter { 34 // store voter address. Required for payout 35 address id; 36 // Vote. true:keep, false:drop 37 bool vote; 38 } 39 40 /** 41 * @dev Acts as constructor for upgradeable contracts 42 * @param _dia Address of DIA token contract. 43 */ 44 function initialize(DIAToken _dia) public initializer() { 45 // ~2 weeks. weeks x days x hours x minute x seconds 46 DISPUTE_LENGTH = 2*7*24*60*60; 47 VOTE_COST = 10; 48 dia_ = _dia; 49 } 50 51 /** 52 * @dev Cast vote. 53 * @param _id Data source identifier. 54 * @param _vote true for drop and false to keep. 55 */ 56 function vote(uint256 _id, bool _vote) public{ 57 // check only new voters 58 require (disputes_[_id].votersIndex[msg.sender] == 0, "Address already voted"); 59 require (disputes_[_id].deadline > 0, "Dispute not available"); 60 dia_.transferFrom(msg.sender, this, VOTE_COST); 61 disputes_[_id].voters.push(Voter(msg.sender, _vote)); 62 disputes_[_id].votersIndex[msg.sender] = disputes_[_id].voters.length; 63 } 64 65 /** 66 * @dev Start a dispute. 67 * @param _id data source identifier. 68 */ 69 function openDispute(uint256 _id) external { 70 require(disputes_[_id].deadline == 0, "Dispute already ongoing"); 71 disputes_[_id].deadline = now+DISPUTE_LENGTH; 72 emit DisputeOpen(_id, disputes_[_id].deadline); 73 vote(_id, true); 74 } 75 76 /** 77 * @dev Once the deadline is reached this function should be called to get decision. 78 * @param _id data source id. 79 */ 80 function triggerDecision(uint256 _id) external{ 81 // Maybe we can get rid of a require 82 require(disputes_[_id].deadline > 0, "Dispute not available"); 83 require(now > disputes_[_id].deadline, "Dispute deadline not reached"); 84 // prevent method to be called again before its done 85 disputes_[_id].deadline = 0; 86 uint256 dropVotes = 0; 87 uint256 keepVotes = 0; 88 uint totalVoters = disputes_[_id].voters.length; 89 for (uint i = 0; i<totalVoters; i++){ 90 if (disputes_[_id].voters[i].vote) 91 dropVotes++; 92 else 93 keepVotes++; 94 } 95 bool drop = (dropVotes>keepVotes); 96 uint payment; 97 // use safe math to compute payment 98 if (drop) 99 payment = ((totalVoters).mul(VOTE_COST)).div(dropVotes); 100 else 101 payment = ((totalVoters).mul(VOTE_COST)).div(keepVotes); 102 for (i = 0; i < totalVoters; i++){ 103 if (disputes_[_id].voters[i].vote == drop){ 104 rewards_[disputes_[_id].voters[i].id] += payment; 105 } 106 delete disputes_[_id].votersIndex[disputes_[_id].voters[i].id]; 107 } 108 delete disputes_[_id]; 109 emit DisputeClosed(_id, drop); 110 } 111 112 /** 113 * @dev Claim rewards 114 */ 115 function claimRewards() external { 116 require(rewards_[msg.sender] > 0, "No balance to withdraw"); 117 dia_.transfer(msg.sender, rewards_[msg.sender]); 118 rewards_[msg.sender] = 0; 119 } 120 121 /** 122 * @dev Check rewards balance for account calling the method 123 */ 124 function checkRewardsBalance() external view returns (uint256) { 125 return rewards_[msg.sender]; 126 } 127 128 /** 129 * @dev get dispute status. 130 * @param _id data source id. 131 */ 132 function isDisputeOpen(uint256 _id) external view returns (bool) { 133 return (disputes_[_id].deadline>0); 134 } 135 136 /** 137 * @dev check if address voted already. 138 * @param _id data source identifier. 139 */ 140 function didCastVote(uint256 _id) external view returns (bool){ 141 return (disputes_[_id].votersIndex[msg.sender]>0); 142 } 143 }