Guest User

Oracle Smart contract

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