Advertisement
Guest User

Oracle.sol

a guest
Sep 25th, 2020
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.36 KB | None | 0 0
  1. pragma solidity ^ 0.6.6;
  2. pragma experimental ABIEncoderV2;
  3.  
  4. contract Oracle{
  5. address ORACLE = address(0);
  6. address address0 = address(0);
  7.  
  8. struct RequestTicket{
  9. uint ID;
  10. address sender;
  11. string query;
  12. uint timeRequested;
  13. uint timeWindow;
  14. bool finalized;
  15. uint txCoverageFee;
  16. uint serviceFee;
  17. bool subjective;
  18.  
  19. bool ticketRejected;
  20. uint numberOfOptions;
  21.  
  22. mapping(uint => string) resolvedStrings;
  23. mapping(uint => int) resolvedInts;
  24. mapping(uint => bytes) resolvedBytes;
  25. mapping(uint => address) resolvedAddresses;
  26.  
  27. mapping(address => mapping(address => bool)) attacks;
  28. mapping(address => bool) damaged;
  29.  
  30. mapping(address => bool) punished;
  31.  
  32.  
  33. uint8 dataType; // string, uint, bool, address
  34.  
  35. //commit
  36. mapping(address => bool) committed;
  37. mapping(address => bytes32) commitHash;
  38.  
  39. //reveal
  40. mapping(address => bool) revealed;
  41. mapping(address => bool) rejected;
  42. mapping(address => bool) voted;
  43.  
  44. mapping(address => string) stringVotes;
  45. mapping(address => int) intVotes;
  46. mapping(address => bytes) bytesVotes;
  47. mapping(address => address) addressVotes;
  48. }
  49.  
  50. //oracle configs
  51. uint constant ROUNDTABLE_SEATS = 0;
  52. uint constant RESPONSE_TIME_WINDOW = 1;
  53. uint constant DELEGATE_REWARDSHARE = 2;
  54. uint constant FREEZE_TIMEOUT = 3;
  55. uint constant TX_FEE_PER = 4;
  56. uint constant SERVICE_FEE = 5;
  57. uint constant CONFIGS = 6;
  58.  
  59. uint[] public oracleConfigurations = new uint[](CONFIGS);
  60. mapping(uint/*configID*/ => mapping(uint => uint) ) public totalVotes_forEach_configOption;
  61. mapping(uint/*configID*/ => mapping(address => uint) ) public individualsSelectedOption;
  62.  
  63. mapping(address => uint) resolveWeight;
  64. mapping(address => uint) weightLocked;
  65.  
  66. mapping(uint => RequestTicket) requestTickets;
  67. uint public requestTicketCount;
  68. //ROUND TABLE & Candidates
  69. mapping(uint => address) public chairsCandidate; // only looks at the first X indexes
  70. mapping(address => uint) candidatesChair;
  71. mapping(address => uint) timeSeated; // watchers aren't responsible for requestTickets that came in before them
  72. mapping(address => bool) frozen;
  73. mapping(address => uint) timeWhenThawedOut;
  74. mapping(address => bool) paused; // self pause
  75. mapping(address => bool) hasChair;
  76. uint chairs;
  77. uint public hotSeats;
  78.  
  79. uint256 constant scaleFactor = 0x10000000000000000;
  80. //PAYROLL
  81. mapping(address => uint) earnings;
  82. mapping(address => uint) totalShares;
  83. mapping(address => mapping(address => uint256)) public shares;
  84. mapping(address => mapping(address => uint256)) payouts;
  85. mapping(address => uint) earningsPerShare;
  86.  
  87. //Tx Coverage fee
  88. uint earningsPerWatcher;
  89. uint totalWatchers;
  90. mapping(address => uint256) watcherPayouts;
  91.  
  92.  
  93. //lazy UI data
  94. mapping(address => address[]) public yourBacking;
  95. mapping(address => mapping(address => bool)) public alreadyBacking;
  96.  
  97. ResolveToken resolveToken;
  98.  
  99. constructor(address _resolve) public{
  100. resolveToken = ResolveToken(_resolve);
  101. }
  102.  
  103. function addressPayable(address addr) public pure returns(address payable){
  104. return address( uint160(addr) );
  105. }
  106.  
  107. function addShares(address pool, address account, uint amount) internal{
  108. update(pool, account);
  109. totalShares[pool] += amount;
  110. shares[pool][account] += amount;
  111.  
  112. if(pool == ORACLE){
  113. updateWatcherTxEarnings(account);
  114. totalWatchers += 1;
  115. }
  116. }
  117.  
  118. function removeShares(address pool, address account, uint amount) internal{
  119. update(pool, account);
  120. totalShares[pool] -= amount;
  121. shares[pool][account] -= amount;
  122.  
  123. if(pool == ORACLE){
  124. updateWatcherTxEarnings(account);
  125. totalWatchers -= 1;
  126. }
  127. }
  128.  
  129. event ConsolidateEarnings(address account, uint amount);
  130. event WatcherPayroll(address watcher, uint paidOut);
  131. function update(address pool, address account) internal {
  132. uint owedPerShare = earningsPerShare[pool] - payouts[pool][account];
  133. uint newMoney = shares[pool][account] * owedPerShare;
  134. payouts[pool][account] = earningsPerShare[pool];
  135.  
  136. if(pool == ORACLE){
  137. uint eth4Watcher = newMoney * oracleConfigurations[DELEGATE_REWARDSHARE] / 1e18;
  138. earnings[account] += eth4Watcher/scaleFactor;
  139. uint newDivs;
  140. if(totalShares[account]>0)
  141. newDivs = (newMoney - eth4Watcher)/totalShares[account];
  142. else
  143. newDivs = 0;
  144. earningsPerShare[account/*this is what the watcher has to distribute to its electorates*/] += newDivs;
  145. emit ConsolidateEarnings(account, eth4Watcher/scaleFactor);
  146. emit WatcherPayroll(account, newDivs);
  147. }else{
  148. earnings[account] += newMoney/scaleFactor;
  149. emit ConsolidateEarnings(account, newMoney/scaleFactor);
  150. }
  151. }
  152.  
  153. event TxCashout(address watcher, uint amount);
  154. function updateWatcherTxEarnings(address watcher) internal {
  155. uint owed = earningsPerWatcher - watcherPayouts[watcher];
  156. watcherPayouts[watcher] = earningsPerWatcher;
  157. earnings[watcher] += owed;
  158. emit TxCashout(watcher, owed);
  159. }
  160.  
  161. event StakeResolves( address indexed addr, uint256 amountStaked, bytes _data );
  162. function tokenFallback(address from, uint value, bytes calldata _data) external{
  163. if( msg.sender == address(resolveToken) ){
  164. resolveWeight[from] += value;
  165. //update option totals
  166. uint option;
  167. for(uint8 config = 0; config<CONFIGS; config+=1){
  168. option = individualsSelectedOption[config][from];
  169. totalVotes_forEach_configOption[config][option] += value;
  170. assertOption(config, option);
  171. }
  172.  
  173. emit StakeResolves(from, value, _data);
  174. //nothing can be done with backImmediately until the backCandidate() function is abstracted to receive just an address because msg.sender from this fallback isn't who holds the tokens
  175. /*
  176. address backImmediately = bytesToAddress( _data );
  177.  
  178. if( backImmediately != address0){
  179. backCandidate(0xf4b218f2949Bc48720cC451f6BBb34E794a0Ba21,value, false);
  180. }*/
  181. }else{
  182. revert();
  183. }
  184. }
  185.  
  186. event UnstakeResolves(address sender, uint amount);
  187. function unstakeResolves(uint amount) public{
  188. address sender = msg.sender;
  189. if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) ){
  190. resolveWeight[sender] -= amount;
  191. for(uint config = 0; config<CONFIGS; config+=1){
  192. totalVotes_forEach_configOption[config][individualsSelectedOption[config][sender]] -= amount;
  193. }
  194. emit UnstakeResolves(sender, amount);
  195. resolveToken.transfer(sender, amount);
  196. }else{
  197. revert();
  198. }
  199. }
  200.  
  201. event BackCandidate(address sender,address candidate, uint amount);
  202. function backCandidate(address candidate, uint amount, bool _assert) public{
  203. address sender = msg.sender;
  204. require(candidate!=ORACLE);
  205. if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) && !isWatcher(candidate) ){
  206. weightLocked[sender] += amount;
  207. addShares(candidate, sender, amount);
  208. //I guess candidates should be able to opt into pausing themselves instead of being cast as a delegate right away.
  209. //Idk where else to write this comment
  210. //If the candidate isn't seated, and freezing and pause isn't preventing them from being seated ... then assertCandidate()
  211. if( candidatesChair[candidate] >= hotSeats && !frausted(candidate) && _assert){
  212. assertCandidate(candidate);
  213. }
  214. emit BackCandidate(sender, candidate, amount);
  215. //LAZY U.I.
  216. if(!alreadyBacking[sender][candidate]){
  217. yourBacking[sender].push(candidate);
  218. alreadyBacking[sender][candidate] = true;
  219. }
  220. }else{
  221. revert();
  222. }
  223. }
  224.  
  225. event WithdrawBacking(address sender,address candidate, uint amount);
  226. function withdrawBacking(address candidate, uint amount) public{
  227. address sender = msg.sender;
  228. if( amount <= shares[candidate][sender] && !frozen[candidate] && ( !(candidatesChair[candidate]<hotSeats) || paused[candidate] ) ){
  229. weightLocked[sender] -= amount;
  230. removeShares(candidate, sender, amount);
  231. emit WithdrawBacking(sender, candidate, amount);
  232. }else{
  233. revert();
  234. }
  235. }
  236.  
  237. function frausted(address candidate) public view returns(bool){
  238. return paused[candidate] || frozen[candidate];
  239. }
  240.  
  241. event AssertCandidate(address candidate, bool asserted, address replacedWatcher, uint newSeat);
  242. function assertCandidate(address candidate) public returns(bool success){
  243.  
  244. uint weakestChair;
  245. bool nullSeat;
  246.  
  247. address thisWatcher;
  248.  
  249. for(uint i; i<hotSeats; i+=1){
  250. thisWatcher = chairsCandidate[i];
  251. if( frausted( thisWatcher ) || thisWatcher == address0 ){
  252. nullSeat = true;
  253. weakestChair = i;
  254. }else if( totalShares[ thisWatcher ] < totalShares[ chairsCandidate[weakestChair] ] ){
  255. weakestChair = i;
  256. }
  257. if(nullSeat){
  258. break;
  259. }
  260. }
  261.  
  262. if( (totalShares[candidate] > totalShares[ chairsCandidate[weakestChair] ] || nullSeat ) && !isWatcher(candidate) ) {
  263. address targetCandidate = chairsCandidate[weakestChair];
  264.  
  265. if(targetCandidate!=address0)
  266. removeShares(ORACLE, targetCandidate, totalShares[targetCandidate]);
  267. addShares(ORACLE, candidate, totalShares[candidate]);
  268. timeSeated[candidate] = now;
  269.  
  270. hasChair[candidate] = true;
  271. hasChair[targetCandidate] = false;
  272.  
  273. chairsCandidate[weakestChair] = candidate;
  274. candidatesChair[candidate] = weakestChair;
  275.  
  276. return true;
  277. }
  278. return false;
  279. }
  280.  
  281. event OptionVote(address sender, uint config, uint option, uint weight);
  282. function optionVote(bool[] memory isModifying, uint[] memory modifiedOptions) public{
  283. address sender = msg.sender;
  284. uint config;
  285. uint modifiedOption;
  286.  
  287. for(config = 0; config<CONFIGS; config+=1){
  288. if(isModifying[config]){
  289. modifiedOption = modifiedOptions[config];
  290. totalVotes_forEach_configOption[config][ individualsSelectedOption[config][sender] ] -= resolveWeight[sender];
  291. individualsSelectedOption[config][sender] = modifiedOption;
  292. totalVotes_forEach_configOption[config][ modifiedOption ] += resolveWeight[sender];
  293. emit OptionVote(sender, config, modifiedOption, resolveWeight[sender]);
  294. assertOption( config, modifiedOption );
  295. }
  296. }
  297. }
  298.  
  299. event AssertOption(uint config, uint option);
  300. function assertOption(uint config, uint option) public{
  301. if( totalVotes_forEach_configOption[config][option] > totalVotes_forEach_configOption[config][ oracleConfigurations[config] ] ){
  302. oracleConfigurations[config] = option;
  303. emit AssertOption(config, option);
  304. }
  305. }
  306.  
  307. function isWatcher(address candidate) public view returns(bool){
  308. return candidatesChair[candidate]<hotSeats && hasChair[candidate] && !frausted(candidate);
  309. }
  310.  
  311. function getFee() public view returns(uint txCoverageFee, uint serviceFee){
  312. uint activeWatchers;
  313. for(uint chair = 0; chair<hotSeats; chair+=1){
  314. if( !frausted(chairsCandidate[chair]) ){
  315. activeWatchers += 1;
  316. }
  317. }
  318. return ( oracleConfigurations[TX_FEE_PER]*activeWatchers, oracleConfigurations[SERVICE_FEE] );
  319. }
  320. //------------------------------ Request Ticket Life Cycle
  321.  
  322. event FileRequestTicket(address sender, uint ticketID, string query, uint timeRequested, uint8 dataType, uint feePaid);
  323. function fileRequestTicket(string memory query, uint8 returnType, bool subjective) public payable returns(uint ticketID){
  324. uint ETH = msg.value;
  325. (uint txCoverageFee, uint serviceFee) = getFee();
  326. if(ETH == txCoverageFee + serviceFee ){
  327. if(returnType>3) returnType = 3;
  328.  
  329. ticketID = requestTicketCount;
  330. requestTicketCount++;
  331. RequestTicket storage ticket = requestTickets[requestTicketCount];
  332.  
  333. ticket.query = query;
  334. ticket.dataType = returnType;
  335. ticket.timeRequested = now;
  336. ticket.timeWindow = oracleConfigurations[RESPONSE_TIME_WINDOW];
  337. ticket.ID = ticketID;
  338. ticket.sender = msg.sender;
  339. ticket.subjective = subjective;
  340. ticket.txCoverageFee = txCoverageFee;
  341. ticket.serviceFee = serviceFee;
  342.  
  343. emit DATA(0, ticketID);
  344. emit DATA(3, oracleConfigurations[RESPONSE_TIME_WINDOW]);
  345.  
  346. emit FileRequestTicket(msg.sender, ticketID, query, now, returnType, ETH);
  347. return ticketID;
  348. }else{
  349. revert();
  350. }
  351. }
  352.  
  353. event CommitVote(address sender, uint ticketID, bytes32 hash);
  354. function commitVote(uint[] memory tickets, bytes32[] memory voteHashes) public{
  355. address sender = msg.sender;
  356. RequestTicket storage ticket;
  357. for(uint R; R<tickets.length; R+=1 ){
  358. ticket = requestTickets[ tickets[R] ];
  359. if(now <= ticket.timeRequested + ticket.timeWindow ){
  360. ticket.committed[sender] = true;
  361. ticket.commitHash[sender] = voteHashes[R];
  362. emit CommitVote(sender, tickets[R], voteHashes[R]);
  363. }
  364. }
  365. }
  366.  
  367. event DATA(uint8 VAR, uint NUMERIC);
  368. event RevealVote(address voter, uint ticketID, bool rejected, /*suba*/ string stringVote, int intVote, bytes bytesVote, address addressVote);
  369. function revealVote(uint[] memory tickets, bool[] memory rejected, string[] memory stringVotes, int[] memory intVotes, bytes[] memory bytesVotes, address[] memory addressVotes, string[] memory passwords) public returns(bool[] memory commitsMatchingReveals){
  370. address sender = msg.sender;
  371. RequestTicket memory ticket;
  372. bytes memory abiEncodePacked;
  373. commitsMatchingReveals = new bool[](tickets.length);
  374. //emit DATA(0, now);
  375. for(uint R; R<tickets.length; R+=1 ){
  376. ticket = requestTickets[ tickets[R] ];
  377. //emit DATA(1, ticket.timeRequested + ticket.timeWindow);
  378. //emit DATA(2, ticket.timeRequested + ticket.timeWindow*2);
  379. if(now > ticket.timeRequested + ticket.timeWindow && now <= ticket.timeRequested + ticket.timeWindow*2 ){
  380. //emit DATA(3, 1);
  381. if(ticket.dataType == 0){
  382. abiEncodePacked = abi.encodePacked( rejected[R], stringVotes[R], passwords[R] );
  383. }else if(ticket.dataType == 1){
  384. abiEncodePacked = abi.encodePacked( rejected[R], intVotes[R], passwords[R] );
  385. }else if(ticket.dataType == 2){
  386. abiEncodePacked = abi.encodePacked( rejected[R], bytesVotes[R], passwords[R] );
  387. }else if(ticket.dataType == 3){
  388. abiEncodePacked = abi.encodePacked( rejected[R], addressVotes[R], passwords[R] );
  389. }
  390.  
  391. if( compareBytes( keccak256(abiEncodePacked), requestTickets[ tickets[R] ].commitHash[sender]) ){
  392.  
  393. //emit DATA(4, 1+ticket.dataType);
  394. commitsMatchingReveals[R] = true;
  395. requestTickets[ tickets[R] ].revealed[sender] = true;
  396. if(rejected[R]){
  397. requestTickets[ tickets[R] ].rejected[sender] = true;
  398. }else{
  399. requestTickets[ tickets[R] ].voted[sender] = true;
  400. if(ticket.dataType == 0){
  401. requestTickets[ tickets[R] ].stringVotes[sender] = stringVotes[R];
  402. }else if(ticket.dataType == 1){
  403. requestTickets[ tickets[R] ].intVotes[sender] = intVotes[R];
  404. }else if(ticket.dataType == 2){
  405. requestTickets[ tickets[R] ].bytesVotes[sender] = bytesVotes[R];
  406. }else if(ticket.dataType == 3){
  407. requestTickets[ tickets[R] ].addressVotes[sender] = addressVotes[R];
  408. }
  409. }
  410. emit RevealVote(sender, tickets[R], rejected[R], stringVotes[R], intVotes[R], bytesVotes[R], addressVotes[R]);
  411. }
  412. }
  413. }
  414. }
  415.  
  416. event SubjectiveStance(address sender, uint ticketID, address defender, bool stance);
  417. function subjectiveStance(uint[] memory tickets, address[] memory defenders, bool[] memory stances) public{
  418. address sender = msg.sender;
  419. RequestTicket storage ticket;
  420. for(uint R; R<tickets.length; R+=1 ){
  421. ticket = requestTickets[ tickets[R] ];
  422. if( timeSeated[sender] <= ticket.timeRequested && timeSeated[defenders[R]] <= ticket.timeRequested && now > ticket.timeRequested + ticket.timeWindow*2 && now <= ticket.timeRequested + ticket.timeWindow*3 ){
  423. ticket.attacks[sender][defenders[R]] = stances[R];
  424. emit SubjectiveStance(sender, tickets[R], defenders[R], stances[R]);
  425. }
  426. }
  427. }
  428.  
  429. event Attack(address offense, address defense, uint damage);
  430. function calculateDamage( uint ticketID ) internal returns(uint combatWeight, uint[] memory damage){
  431. RequestTicket storage ticket = requestTickets[ticketID];
  432. address offensiveWatcher;
  433. address defender;
  434. uint Y;
  435. uint X;
  436. damage = new uint[](hotSeats);
  437. if(ticket.subjective){
  438. for(X = 0; X < hotSeats; X+=1){
  439. offensiveWatcher = chairsCandidate[X];
  440. if( !frausted(offensiveWatcher) && timeSeated[offensiveWatcher] <= ticket.timeRequested ){
  441. combatWeight += totalShares[offensiveWatcher];
  442. for(Y = 0; Y < hotSeats; Y+=1){
  443. if( !frausted(offensiveWatcher) ){
  444. defender = chairsCandidate[Y];
  445. if(ticket.attacks[offensiveWatcher][defender])
  446. damage[Y] += totalShares[offensiveWatcher];
  447. emit Attack(offensiveWatcher, defender, totalShares[offensiveWatcher]);
  448. }
  449. }
  450. }
  451. }
  452. }
  453. }
  454.  
  455. event FinalizedRequestOptions(string[] stringOptions, uint[] intOptions, bool[] bytesOptions, address[] addressOptions, address[] watchers);
  456. function finalizeRequest(uint ticketID) public{
  457. // if responsew time window is over or all delegates have voted,
  458. // anyone can finalize the request to trigger the event
  459. RequestTicket storage ticket = requestTickets[ticketID];
  460. if(!ticket.finalized){
  461.  
  462. address watcher;
  463.  
  464. string[] memory stringOptions = new string[](hotSeats);
  465. int[] memory intOptions = new int[](hotSeats);
  466. bytes[] memory bytesOptions = new bytes[](hotSeats);
  467. address[] memory addressOptions = new address[](hotSeats);
  468. uint[] memory optionWeights = new uint[](hotSeats);
  469.  
  470. uint[] memory UINTs = new uint[](7);//0= weight of votes, 1=top Option, 2= number of options, 3=top Option, 4 =total eligible weight, 5 = combat weight, 6 = loop for saving subjectives to storage
  471.  
  472. uint opt;
  473. uint[] memory damage;
  474. //emit DATA(0,1);
  475. (UINTs[5]/*combatWeight*/, damage) = calculateDamage(ticketID);
  476. for(uint chair = 0; chair < hotSeats; chair+=1){
  477. //emit DATA(1,chair);
  478. watcher = chairsCandidate[chair];
  479. if(damage[chair]<=UINTs[5]/*combatWeight*//2){
  480. //emit DATA(2,damage[chair]);
  481. if( watcher!=address0 && !frausted(watcher) && timeSeated[watcher] <= ticket.timeRequested ){
  482. //emit DATA(4,chair);
  483. UINTs[4]/*total Eligible Weight*/ += totalShares[watcher];
  484. if( ticket.voted[watcher] ){
  485. UINTs[0]/*weight of votes*/ += totalShares[watcher];
  486. //emit DATA(5, totalShares[watcher]);
  487. //check to see if chosen option already is accounted for, if so, add weight to it.
  488. for(opt = 0; opt<UINTs[2]/*option count*/; opt+=1){
  489. if( (ticket.dataType == 0 && compareStrings(stringOptions[opt], ticket.stringVotes[watcher]) ) ||
  490. (ticket.dataType == 1 && intOptions[opt] == ticket.intVotes[watcher]) ||
  491. (ticket.dataType == 2 && compareBytes( keccak256(bytesOptions[opt]), keccak256(ticket.bytesVotes[watcher]) ) ) ||
  492. (ticket.dataType == 3 && addressOptions[opt] == ticket.addressVotes[watcher])
  493. ){
  494. optionWeights[opt] += totalShares[watcher];
  495. //emit DATA(13,opt);
  496. //emit DATA(10,optionWeights[opt]);
  497. if(optionWeights[opt] > optionWeights[UINTs[3]/*top option*/] && !ticket.subjective){
  498. UINTs[3]/*top option*/ = opt;
  499. //emit DATA(11,optionWeights[opt]);
  500. }
  501. break;
  502. }
  503. }
  504.  
  505. //add new unique option
  506. if(opt == UINTs[2]/*option count*/){
  507. if(ticket.dataType == 0){
  508. stringOptions[UINTs[2]/*option count*/] = ticket.stringVotes[watcher];
  509. }else if(ticket.dataType == 1){
  510. intOptions[UINTs[2]/*option count*/] = ticket.intVotes[watcher];
  511. }else if(ticket.dataType == 2){
  512. bytesOptions[UINTs[2]/*option count*/] = ticket.bytesVotes[watcher];
  513. }else if(ticket.dataType == 3){
  514. addressOptions[UINTs[2]/*option count*/] = ticket.addressVotes[watcher];
  515. }
  516. optionWeights[UINTs[2]/*option count*/] = totalShares[watcher];
  517. /*if(optionWeights[ UINTs[2] ] > optionWeights[UINTs[3]] && !ticket.subjective){
  518. UINTs[3] = UINTs[2];
  519. }*/
  520. //emit DATA(12,UINTs[2]);
  521. //emit DATA(10,totalShares[watcher]);
  522. UINTs[2]/*option count*/+=1;
  523. }
  524. }else if(ticket.rejected[watcher]){
  525. UINTs[1]/*weight of rejections*/ += totalShares[watcher];
  526. //emit DATA(6,UINTs[1]);
  527. }
  528. }
  529. }else{
  530. //emit DATA(3,chair);
  531. ticket.damaged[watcher] = true;
  532. }
  533. }
  534.  
  535. if( (UINTs[4]/*total Eligible Weight*/ == (UINTs[1]/*weight of rejections*/ + UINTs[0]/*weight of votes*/) && !ticket.subjective) || (now > ticket.timeRequested + ticket.timeWindow*(ticket.subjective?3:2) ) ){
  536. bool rejected;
  537. //emit DATA(7,UINTs[4]/*total Eligible Weight*/);
  538. if( UINTs[1]/*weight of rejections*/ > optionWeights[UINTs[3]/*top option*/] ){
  539. rejected = true;
  540. }
  541.  
  542. //write results in stone
  543. if(rejected){
  544. ticket.ticketRejected = true;
  545. //emit DATA(8,0);
  546. }else{
  547. uint8 dataType = ticket.dataType;
  548. if(ticket.subjective){
  549. ticket.numberOfOptions = UINTs[2]/*option count*/;
  550. for(UINTs[6]=0;UINTs[6]<UINTs[2];UINTs[6]+=1){
  551. if(dataType == 0){
  552. ticket.resolvedStrings[UINTs[6]] = stringOptions[UINTs[6]];
  553. }else if(dataType == 1){
  554. ticket.resolvedInts[UINTs[6]] = intOptions[UINTs[6]];
  555. }else if(dataType == 2){
  556. ticket.resolvedBytes[UINTs[6]] = bytesOptions[UINTs[6]];
  557. }else if(dataType == 3){
  558. ticket.resolvedAddresses[UINTs[6]] = addressOptions[UINTs[6]];
  559. }
  560. }
  561. }else{
  562. //emit DATA(9, UINTs[3]);
  563. ticket.numberOfOptions = 1;
  564. if(dataType == 0){
  565. ticket.resolvedStrings[0] = stringOptions[UINTs[3]/*top option*/];
  566. }else if(dataType == 1){
  567. ticket.resolvedInts[0] = intOptions[UINTs[3]/*top option*/];
  568. }else if(dataType == 2){
  569. ticket.resolvedBytes[0] = bytesOptions[UINTs[3]/*top option*/];
  570. }else if(dataType == 3){
  571. ticket.resolvedAddresses[0] = addressOptions[UINTs[3]/*top option*/];
  572. }
  573. }
  574. }
  575.  
  576. //dish out the rewards
  577. earningsPerShare[ORACLE] += ticket.serviceFee * scaleFactor / totalShares[ORACLE];
  578. earningsPerWatcher += ticket.txCoverageFee / totalWatchers;
  579. emit DATA(14, ticket.txCoverageFee);
  580. emit DATA(15, ticket.serviceFee);
  581.  
  582.  
  583. ticket.finalized = true;
  584. }else{
  585. revert();
  586. }
  587. }
  588. }
  589.  
  590. event Cashout(address addr, uint ETH);
  591. function cashout(address[] memory pools) public{
  592. address payable sender = msg.sender;
  593. for(uint p; p < pools.length; p+=1){
  594. update(pools[p], sender);
  595. }
  596. uint ETH = earnings[sender];
  597. earnings[sender] = 0;
  598. emit Cashout(sender, ETH);
  599. sender.transfer( ETH );
  600. }
  601.  
  602. function runWatcherPayroll(address watcher) public{
  603. update(ORACLE, watcher );
  604. updateWatcherTxEarnings( watcher );
  605. }
  606.  
  607. /*function tryToPunish(uint[] memory tickets, address[] memory watchers) public{
  608. freezeNoncommits(tickets, watchers);
  609. freezeUnrevealedCommits(tickets, watchers);
  610. freezeWrongWatchers(tickets, watchers);
  611. }*/
  612.  
  613. event FreezeNoncommits(uint ticketID, address watcher);
  614. function freezeNoncommits(uint[] memory tickets, address[] memory watchers) public{
  615. // get them while they're still at the round table and we're in the reveal phase of a ticket
  616. RequestTicket storage ticket;
  617. for(uint i; i<watchers.length; i+=1){
  618. ticket = requestTickets[ tickets[i] ];
  619. if( candidatesChair[watchers[i]] < hotSeats &&
  620. !ticket.committed[ watchers[i] ] &&
  621. now > ticket.timeRequested + ticket.timeWindow //&&
  622. //now <= ticket.timeRequested + ticket.timeWindow*2
  623. ){
  624. if(punish(tickets[i] , watchers[i]) ){
  625. emit FreezeNoncommits(tickets[i] , watchers[i]);
  626. }
  627. }
  628. }
  629. }
  630.  
  631. event FreezeUnrevealedCommits(uint ticketID, address watcher);
  632. function freezeUnrevealedCommits(uint[] memory tickets, address[] memory watchers) public{
  633. // get them if they made a commit, but did not reveal it after the reveal window is over
  634. RequestTicket storage ticket;
  635. for(uint i; i<watchers.length; i+=1){
  636. ticket = requestTickets[ tickets[i] ];
  637. if( ticket.committed[ watchers[i] ] &&
  638. ticket.revealed[ watchers[i] ] &&
  639. now > requestTickets[ tickets[i] ].timeRequested + ticket.timeWindow*2
  640. ){
  641. if(punish(tickets[i] , watchers[i]) ){
  642. emit FreezeUnrevealedCommits(tickets[i] , watchers[i]);
  643. }
  644. }
  645. }
  646. }
  647.  
  648. event FreezeWrongWatchers(uint ticketID, address watcher);
  649. function freezeWrongWatchers(uint[] memory tickets, address[] memory watchers) public{
  650. // get them if the ticket is finalized and their vote doesn't match the resolved answer
  651. address watcher;
  652. RequestTicket storage ticket;
  653. for(uint i; i<watchers.length; i+=1){
  654. ticket = requestTickets[ tickets[i] ];
  655. watcher = watchers[i];
  656. if( ticket.finalized &&
  657. (!ticket.subjective && (
  658. (ticket.dataType == 0 && !compareStrings(ticket.resolvedStrings[0], ticket.stringVotes[ watcher ] ))||
  659. (ticket.dataType == 1 && ticket.resolvedInts[0] != ticket.intVotes[ watcher ] )||
  660. (ticket.dataType == 2 && compareBytes( keccak256(ticket.resolvedBytes[0]), keccak256(ticket.bytesVotes[ watcher ]) ) )||
  661. (ticket.dataType == 3 && ticket.resolvedAddresses[0] != ticket.addressVotes[ watcher ] )||
  662. (!ticket.ticketRejected && ticket.rejected[ watcher ] )//if they reject something the majority didn't reject
  663. ))||
  664. (ticket.subjective && ticket.damaged[ watcher ] )//if their subjective contribution is garbage
  665. ){
  666. if(punish(tickets[i] , watcher)){
  667. emit FreezeWrongWatchers(tickets[i] , watcher);
  668. }
  669. }
  670. }
  671. }
  672.  
  673. event Punish(address watcher, uint thatOutTime);
  674. function punish(uint ticketID, address watcher) internal returns(bool punished){
  675. if(!requestTickets[ticketID].punished[watcher] && isWatcher(watcher) && timeSeated[watcher] <= requestTickets[ ticketID ].timeRequested ){
  676. frozen[watcher] = true;
  677. timeWhenThawedOut[watcher] = now + oracleConfigurations[FREEZE_TIMEOUT];
  678. removeShares(ORACLE, watcher, totalShares[watcher]);
  679.  
  680. emit Punish(watcher, timeWhenThawedOut[watcher]);
  681. return true;
  682. }
  683. return false;
  684. }
  685.  
  686. event Thaw(address candidate, bool seated);
  687. function thaw(address candidate, bool _assert) public{
  688. if( now >= timeWhenThawedOut[candidate] ){
  689. bool seated;
  690. frozen[candidate] = false;
  691. if( candidatesChair[candidate] < hotSeats && !paused[candidate]){
  692. //
  693. addShares(ORACLE, candidate, totalShares[candidate]);
  694. seated = true;
  695. }else if( _assert ){
  696. seated = assertCandidate(candidate);
  697. }
  698. emit Thaw(candidate, seated);
  699. }else{
  700. revert();
  701. }
  702. }
  703.  
  704. event PauseOut(address sender, bool wasWatcher);
  705. function pauseOut() public{
  706. address sender = msg.sender;
  707. bool wasWatcher;
  708. if(isWatcher(sender)){
  709. wasWatcher = true;
  710. removeShares(ORACLE, sender, totalShares[sender]);
  711. }
  712. paused[sender] = true;
  713. emit PauseOut(sender, wasWatcher);
  714. }
  715.  
  716. event Unpause(address sender, bool seated);
  717. function unpause(bool _assert) public{
  718. address sender = msg.sender;
  719. paused[sender] = false;
  720. bool seated;
  721. if( candidatesChair[sender] < hotSeats && !frozen[sender]){
  722. //
  723. addShares(ORACLE, sender, totalShares[sender]);
  724. seated = true;
  725. timeSeated[sender] = now;//this refreshes when they sat down. so they lose responsibility for old tickets.
  726. }else if( _assert ){
  727. seated = assertCandidate(sender);
  728. }
  729. emit Unpause(sender, seated);
  730.  
  731. }
  732.  
  733. event UpdateRoundTable(uint newTotalHotSeats);
  734. function updateRoundTable(uint seats) public{
  735. // update hotSeats up and down.
  736. address candidate;
  737. uint s;
  738. for( s = 0; s<seats; s+=1){
  739. if( oracleConfigurations[ROUNDTABLE_SEATS] > hotSeats ){
  740. candidate = chairsCandidate[hotSeats];
  741. addShares(ORACLE, candidate, totalShares[candidate]);
  742. timeSeated[candidate] = now;
  743. hotSeats += 1;
  744. }
  745. if( oracleConfigurations[ROUNDTABLE_SEATS] < hotSeats ){
  746. candidate = chairsCandidate[hotSeats-1];
  747. removeShares(ORACLE, candidate, totalShares[candidate]);
  748. hotSeats -= 1;
  749. }
  750. if( oracleConfigurations[ROUNDTABLE_SEATS] == hotSeats ){break;}
  751. }
  752. emit UpdateRoundTable(hotSeats);
  753. }
  754.  
  755. function viewRequestTicket(uint ticketID) public view returns(
  756. address sender,
  757. string memory query,
  758. uint timeRequested,
  759. uint timeWindow,
  760. bool finalized,
  761. bool rejected,
  762. string[] memory resolvedStrings,
  763. int[] memory resolvedInts,
  764. bytes[] memory resolvedBytes,
  765. address[] memory resolvedAddresses,
  766. uint8 dataType){
  767.  
  768. RequestTicket storage T;
  769. T = requestTickets[ticketID];
  770. sender = T.sender;
  771. query = T.query;
  772. timeRequested = T.timeRequested;
  773. timeWindow = T.timeWindow;
  774. finalized = T.finalized;
  775. rejected = T.ticketRejected;
  776.  
  777. resolvedStrings = new string[](T.numberOfOptions);
  778. resolvedInts = new int[](T.numberOfOptions);
  779. resolvedBytes = new bytes[](T.numberOfOptions);
  780. resolvedAddresses = new address[](T.numberOfOptions);
  781. //yikes
  782. for(uint i = 0; i< T.numberOfOptions; i+=1){
  783. resolvedStrings[i] = T.resolvedStrings[i];
  784. resolvedInts[i] = T.resolvedInts[i];
  785. resolvedBytes[i] = T.resolvedBytes[i];
  786. resolvedAddresses[i] = T.resolvedAddresses[i];
  787. }
  788.  
  789. dataType = T.dataType;
  790. }
  791.  
  792. function viewCandidates(bool personal_or_roundtable, address perspective)public view returns(address[] memory addresses, uint[] memory dividends, bool[] memory hasChairs, uint[] memory seat, uint[] memory timesSeated, uint[] memory timesWhenThawedOut, bool[] memory isFrozen, bool[] memory isPaused){
  793. uint L;
  794. if(personal_or_roundtable){
  795. L = hotSeats;
  796. }else{
  797. L = yourBacking[perspective].length;
  798. }
  799.  
  800. dividends = new uint[](L);
  801. seat = new uint[](L);
  802. timesWhenThawedOut = new uint[](L);
  803. timesSeated = new uint[](L);
  804. isFrozen = new bool[](L);
  805. isPaused = new bool[](L);
  806. hasChairs = new bool[](L);
  807. addresses = new address[](L);
  808.  
  809. address candidate;
  810. for(uint c;c<L;c+=1){
  811. if(personal_or_roundtable){
  812. candidate = chairsCandidate[c];
  813. }else{
  814. candidate = yourBacking[perspective][c];
  815. }
  816. addresses[c] = candidate;
  817. dividends[c] = shares[candidate][perspective] * (earningsPerShare[candidate] - payouts[candidate][perspective]);
  818. seat[c] = candidatesChair[candidate];
  819. isFrozen[c] = frozen[candidate];
  820. isPaused[c] = paused[candidate];
  821. hasChairs[c] = hasChair[candidate];
  822. timesWhenThawedOut[c] = timeWhenThawedOut[candidate];
  823. timesSeated[c] = timeSeated[candidate];
  824. }
  825. }
  826.  
  827. function compareStrings(string memory a, string memory b) public pure returns (bool) {
  828. return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
  829. }
  830. function compareBytes(bytes32 a, bytes32 b) public pure returns (bool) {
  831. return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
  832. }
  833. function bytesToAddress(bytes memory bys) private pure returns (address addr){
  834. assembly {
  835. addr := mload(add(bys,20))
  836. }
  837. }
  838.  
  839. function accountData(address account) public view returns(
  840. uint _resolveWeight,
  841. uint _weightLocked,
  842. uint _candidatesChair,
  843. uint _timeSeated,
  844. bool _frozen,
  845. uint _timeWhenThawedOut,
  846. bool _paused,
  847. bool _hasChair,
  848. uint _earnings,
  849. uint _totalShares,
  850. uint _txCoverageFeeEarnings
  851. ){
  852. _resolveWeight = resolveWeight[account];
  853. _weightLocked = weightLocked[account];
  854. _candidatesChair = candidatesChair[account];
  855. _timeSeated = timeSeated[account];
  856. _frozen = frozen[account];
  857. _timeWhenThawedOut = timeWhenThawedOut[account];
  858. _paused = paused[account];
  859. _hasChair = hasChair[account];
  860. _earnings = earnings[account];
  861. _totalShares = totalShares[account];
  862. uint txCoverageFeeEarnings;
  863. if( isWatcher(account) ){
  864. txCoverageFeeEarnings = earningsPerWatcher - watcherPayouts[account];
  865. }
  866. _txCoverageFeeEarnings = txCoverageFeeEarnings;
  867. }
  868.  
  869. }
  870.  
  871. abstract contract ResolveToken{
  872. function transfer(address _to, uint256 _value) public virtual returns (bool);
  873. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement