Guest User

Untitled

a guest
Apr 21st, 2022
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.14 KB | None | 0 0
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^ 0.8.11;
  3.  
  4. contract AdventureDAO{
  5. address ORACLE = address(0);
  6. address address0 = address(0);
  7.  
  8. struct RequestTicket{
  9. uint ID;
  10. address sender;
  11. uint timeRequested;
  12. uint timeWindow;
  13. bool finalized;
  14. uint serviceFee;
  15. bool subjective;
  16.  
  17. mapping(address => mapping(address => bool)) attacks;
  18. mapping(address => bool) damaged;
  19.  
  20. uint8 dataType; // uint, address
  21.  
  22. //commit
  23. mapping(address => bool) committed;
  24. mapping(address => bytes32) commitHash;
  25.  
  26. //reveal
  27. mapping(address => bool) revealed;
  28. mapping(address => bool) rejected;
  29. mapping(address => bool) voted;
  30.  
  31. mapping(address => int) intVotes;
  32. mapping(address => address) addressVotes;
  33.  
  34. //RESULTS
  35. bool ticketRejected;
  36. uint numberOfOptions;
  37.  
  38. //results
  39. mapping(uint => uint) weightOfResults;
  40. mapping(uint => int) resolvedInts;
  41. mapping(uint => address) resolvedAddresses;
  42. }
  43.  
  44. //oracle configs
  45. uint constant ROUNDTABLE_SEATS = 0;
  46. uint constant RESPONSE_TIME_WINDOW = 1;
  47. uint constant DELEGATE_REWARDSHARE = 2;
  48. uint constant FREEZE_TIMEOUT = 3;
  49. uint constant SERVICE_FEE = 4;
  50. uint constant TX_FEE_PER = 5;
  51. uint constant CONFIGS = 6;
  52.  
  53. uint[] public oracleConfigurations = new uint[](CONFIGS);
  54.  
  55. mapping(address => uint) resolveWeight;
  56. mapping(address => uint) weightLocked;
  57.  
  58. mapping(uint => RequestTicket) requestTickets;
  59. uint requestTicketCount;
  60. //ROUND TABLE & Candidates
  61. mapping(uint => address) public chairsCandidate; // only looks at the first X indexes
  62. mapping(address => uint) candidatesChair;
  63. mapping(address => uint) timeSeated; // watchers aren't responsible for requestTickets that came in before them
  64. mapping(address => bool) frozen;
  65. mapping(address => bool) isWatcher;
  66. mapping(address => uint) latestPunishment;
  67. mapping(address => uint) timeWhenThawedOut;
  68. uint chairs;
  69. uint public hotSeats;
  70.  
  71. uint256 constant scaleFactor = 0x10000000000000000;
  72. //PAYROLL
  73. mapping(address => uint) earnings;
  74. mapping(address => uint) totalShares;
  75. mapping(address => mapping(address => uint256)) public shares;
  76. mapping(address => mapping(address => uint256)) payouts;
  77. mapping(address => uint) earningsPerShare;
  78.  
  79. //Tx Coverage fee
  80. uint earningsPerWatcher;
  81. uint public totalWatchers;
  82. mapping(address => uint256) watcherPayouts;
  83.  
  84.  
  85. //lazy UI data
  86. mapping(address => address[]) public yourBacking;
  87. mapping(address => mapping(address => bool)) public alreadyBacking;
  88.  
  89. ResolveToken public resolveToken;
  90. address payable haleySales;
  91. Pyramid public pyramid = Pyramid(/*insert pyramid address here*/);
  92. uint genesis;
  93.  
  94. constructor(){
  95. resolveToken = pyramid.resolveToken();
  96. genesis = _now();
  97. haleySales = payable(msg.sender);
  98.  
  99. freshConfigs();
  100. registered[address(this)] = true;
  101. }
  102.  
  103. uint lastTimeTicketWasFinalized;
  104. function failSafe() public{
  105. if(_now() - lastTimeTicketWasFinalized > 43200){
  106. freshConfigs();
  107. }
  108. }
  109.  
  110. function freshConfigs() internal{
  111. lastTimeTicketWasFinalized = _now();
  112. hotSeats = 7;
  113. oracleConfigurations[ROUNDTABLE_SEATS] = 7;
  114. oracleConfigurations[RESPONSE_TIME_WINDOW] = 60*5;
  115. oracleConfigurations[DELEGATE_REWARDSHARE] = 25*1e18;
  116. oracleConfigurations[FREEZE_TIMEOUT] = 86400;
  117. oracleConfigurations[SERVICE_FEE] = 0;
  118. oracleConfigurations[TX_FEE_PER] = 0;
  119. }
  120.  
  121. function _now()internal view returns(uint){
  122. return block.timestamp;
  123. }
  124.  
  125. function addShares(address pool, address account, uint amount) internal{
  126. update(pool, account);
  127. totalShares[pool] += amount;
  128. shares[pool][account] += amount;
  129.  
  130. if(pool == ORACLE){
  131. updateWatcherTxEarnings(account,false);
  132. if (account != address0){
  133. totalWatchers += 1;
  134. isWatcher[account] = true;
  135. }
  136. }
  137. }
  138.  
  139. function removeShares(address pool, address account, uint amount) internal{
  140. update(pool, account);
  141. totalShares[pool] -= amount;
  142. shares[pool][account] -= amount;
  143.  
  144. if(pool == ORACLE){
  145. updateWatcherTxEarnings(account,true);
  146. if (account != address0){
  147. isWatcher[account] = false;
  148.  
  149. uint emptiedSeat = candidatesChair[account];
  150.  
  151. address tail = chairsCandidate[totalWatchers-1];
  152. chairsCandidate[ emptiedSeat ] = tail;
  153. candidatesChair[tail] = emptiedSeat;
  154.  
  155. totalWatchers -= 1;
  156. }
  157. }
  158. }
  159.  
  160. function dividendsOf(address pool, address account) public view returns(uint){
  161. uint owedPerShare = earningsPerShare[pool] - payouts[pool][account];
  162. if(pool == ORACLE && !isWatcher[account] )
  163. return 0;
  164. return shares[pool][account] * owedPerShare / scaleFactor;
  165. }
  166.  
  167.  
  168. event WatcherPayroll(address watcher, uint paidOut);
  169. function update(address pool, address account) internal {
  170. uint newMoney = dividendsOf(pool, account);
  171. payouts[pool][account] = earningsPerShare[pool];
  172.  
  173. if(pool == ORACLE){
  174. uint eth4Watcher = newMoney * oracleConfigurations[DELEGATE_REWARDSHARE] / (1e20);
  175. earnings[account] += eth4Watcher;
  176.  
  177. uint newDivs;
  178. if(totalShares[account]>0){
  179. newDivs = (newMoney - eth4Watcher) * scaleFactor / totalShares[account];
  180. }else{
  181. newDivs = 0;
  182. }
  183.  
  184. earningsPerShare[account/*this is what the watcher has to distribute to its electorates*/] += newDivs;
  185. }else{
  186. earnings[account] += newMoney;
  187. }
  188. }
  189.  
  190. event TxCashout(address watcher, uint amount);
  191. function updateWatcherTxEarnings(address watcher, bool paying) internal {
  192. uint owed = earningsPerWatcher - watcherPayouts[watcher];
  193. watcherPayouts[watcher] = earningsPerWatcher;
  194. if(paying) earnings[watcher] += owed;
  195. emit TxCashout(watcher, owed);
  196. }
  197.  
  198. event StakeResolves( address indexed addr, uint256 amountStaked, bytes _data );
  199. function tokenFallback(address from, uint value, bytes calldata _data) external{
  200. if( msg.sender == address(resolveToken) ){
  201. if(from == address(pyramid)){
  202. return;// if the pyramid is sending resolve tokens back to this contract, then do nothing.
  203. }
  204. resolveWeight[from] += value;
  205.  
  206. emit StakeResolves(from, value, _data);
  207.  
  208. address backImmediately = bytesToAddress( _data );
  209.  
  210. if( backImmediately != address0){
  211. backCandidate(from, backImmediately, value);
  212. }
  213.  
  214. }else{
  215. revert();
  216. }
  217. }
  218.  
  219. event UnstakeResolves(address sender, uint amount);
  220. function unstakeResolves(uint amount) public{
  221. address sender = msg.sender;
  222. if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) ){
  223. resolveWeight[sender] -= amount;
  224.  
  225. emit UnstakeResolves(sender, amount);
  226.  
  227. resolveToken.transfer(sender, amount);
  228. }else{
  229. revert();
  230. }
  231. }
  232.  
  233. event BackCandidate(address sender,address candidate, uint amount);
  234. function stakeCandidate(address candidate, uint amount) public{ backCandidate(msg.sender, candidate, amount); }
  235. function backCandidate(address sender, address candidate, uint amount) internal{
  236. require(candidate!=ORACLE);
  237. if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) && !frozen[candidate] && !isWatcher[candidate] ){
  238. weightLocked[sender] += amount;
  239. addShares(candidate, sender, amount);
  240.  
  241. emit BackCandidate(sender, candidate, amount);
  242. //LAZY U.I.
  243. if(!alreadyBacking[sender][candidate]){
  244. yourBacking[sender].push(candidate);
  245. alreadyBacking[sender][candidate] = true;
  246. }
  247. }else{
  248. revert();
  249. }
  250. }
  251.  
  252. event PullBacking(address sender, address candidate, uint amount);
  253. function pullBacking( address candidate, uint amount ) public{
  254. address sender = msg.sender;
  255. if( amount <= shares[candidate][sender] && !frozen[candidate] && !isWatcher[candidate] ){
  256. weightLocked[sender] -= amount;
  257. removeShares(candidate, sender, amount);
  258. emit PullBacking(sender, candidate, amount);
  259. }else{
  260. revert();
  261. }
  262. }
  263.  
  264. function pullAllTheWay(address candidate, uint amount) public{
  265. pullBacking(candidate, amount);
  266. unstakeResolves(amount);
  267. }
  268.  
  269. event AssertCandidate(address candidate, bool successfulAssert, address replacedWatcher, uint newSeat);
  270. function assertCandidate() public returns(bool success){
  271. address candidate = msg.sender;
  272. uint weakestChair;
  273. bool nullSeat;
  274. require( !frozen[candidate] && hotSeats > 0);
  275. address thisWatcher;
  276.  
  277. if(hotSeats == totalWatchers){
  278. for(uint i; i<hotSeats; i+=1){
  279. thisWatcher = chairsCandidate[i];
  280. if( totalShares[ thisWatcher ] < totalShares[ chairsCandidate[weakestChair] ] ){
  281. weakestChair = i;
  282. }
  283. }
  284. }else{
  285. nullSeat = true;
  286. weakestChair = totalWatchers;
  287. }
  288.  
  289. if( (totalShares[candidate] > totalShares[ chairsCandidate[weakestChair] ] || nullSeat ) && !isWatcher[candidate] ){
  290. address targetCandidate = chairsCandidate[weakestChair];
  291.  
  292. if(!nullSeat){
  293. removeShares(ORACLE, targetCandidate, totalShares[targetCandidate]);
  294. }else{
  295. targetCandidate = address0;
  296. }
  297.  
  298. addShares(ORACLE, candidate, totalShares[candidate]);
  299. timeSeated[candidate] = _now();
  300.  
  301. chairsCandidate[weakestChair] = candidate;
  302. candidatesChair[candidate] = weakestChair;
  303.  
  304. emit AssertCandidate(candidate, true, targetCandidate, weakestChair);
  305. return true;
  306. }
  307.  
  308. emit AssertCandidate(candidate, false, address0, weakestChair);
  309. return false;
  310. }
  311.  
  312.  
  313. //mapping(uint => uint) internalRequestID;
  314. mapping(uint => bool) internalRequestType;
  315. mapping(uint => uint8) configType;
  316. mapping(uint => uint) configSetting;
  317. event OracleConfigRequest(uint8 config, uint setting, uint indexed ticketID);
  318. function oracleConfigRequest(uint8 config, uint setting) public payable returns(uint ticketID){
  319. ticketID = this.fileRequestTicket{value: msg.value }(1,true);
  320. require(config<CONFIGS);
  321. configType[ticketID] = config;
  322. configSetting[ticketID] = setting;
  323. emit OracleConfigRequest(config, setting, ticketID);
  324. }
  325.  
  326. mapping(uint => address) requestedContract;
  327. mapping(address => bool) public registered;
  328. event OracleJobRequest(string description, address _contract, bool updatedState , uint indexed ticketID);
  329. function oracleJobRequest(string memory description, address _contract, bool updatedState) public payable returns(uint ticketID){
  330. ticketID = this.fileRequestTicket{ value: msg.value }(1,true);
  331. internalRequestType[ticketID] = true;
  332. configSetting[ticketID] = updatedState?1:0;
  333. requestedContract[ticketID] = _contract;
  334. emit OracleJobRequest(description, _contract, updatedState, ticketID);
  335. }
  336.  
  337. event jobNotUpdated(address _contract, uint indexed ticketID);
  338. event jobUpdated(address _contract, bool updatedState, uint indexed ticketID);
  339. event configRejected(uint8 _configType, uint _configSetting, uint indexed ticketID);
  340. event configAccepted(uint8 _configType, uint _configSetting, uint indexed ticketID);
  341. function oracleIntFallback(uint ticketID, bool EXCEPTION, uint numberOfOptions, uint[] memory optionWeights, int[] memory intOptions) public{
  342. uint optWeight;
  343. uint positive;
  344. uint negative;
  345. require( msg.sender == address(this) );
  346.  
  347. if(!EXCEPTION){
  348. //YES OR NO?
  349. for(uint i; i < numberOfOptions; i+=1){
  350. optWeight = optionWeights[i];
  351. if(intOptions[i]>0){
  352. positive += optWeight;
  353. }else{
  354. negative += optWeight;
  355. }
  356. }
  357.  
  358. if(internalRequestType[ticketID]){
  359. address _requestedContract = requestedContract[ticketID];
  360. bool updatedState = configSetting[ticketID]>0;
  361. if(positive>negative){
  362. registered[_requestedContract] = updatedState;
  363. emit jobUpdated(_requestedContract, updatedState, ticketID);
  364. }else{
  365. emit jobNotUpdated(_requestedContract, ticketID);
  366. }
  367. }else{
  368. uint8 _configType = configType[ticketID];
  369. uint _configSetting = configSetting[ticketID];
  370.  
  371. if(positive>negative){
  372.  
  373. if(_configType == RESPONSE_TIME_WINDOW){ _configSetting = _configSetting>180?_configSetting:180; }
  374. if(_configType == ROUNDTABLE_SEATS){
  375. _configSetting = _configSetting>7?_configSetting:7;
  376. }
  377. if(_configType == DELEGATE_REWARDSHARE){ _configSetting = _configSetting>1e20?1e20:_configSetting; }
  378.  
  379. oracleConfigurations[_configType] = _configSetting;
  380.  
  381. if(_configType == ROUNDTABLE_SEATS){
  382. if(hotSeats<oracleConfigurations[ROUNDTABLE_SEATS]){
  383. hotSeats = oracleConfigurations[ROUNDTABLE_SEATS];
  384. }
  385. }
  386.  
  387. emit configAccepted(_configType, _configSetting, ticketID);
  388. }else{
  389. emit configRejected(_configType, _configSetting, ticketID);
  390. }
  391. }
  392. }
  393. }
  394.  
  395.  
  396. function getFee() public view returns(uint txCoverageFee, uint serviceFee){
  397. return ( oracleConfigurations[TX_FEE_PER]*hotSeats, oracleConfigurations[SERVICE_FEE] );
  398. }
  399.  
  400. uint public devFunds;
  401. function updatePines(address addr) public{
  402. require(msg.sender == haleySales);
  403. haleySales = payable(addr);
  404. }
  405.  
  406. function devPull() public{
  407. require(msg.sender == haleySales);
  408. uint money = devFunds;
  409. devFunds = 0;
  410. payable(msg.sender).transfer( money );
  411. }
  412.  
  413.  
  414. mapping(address => address) public useCaseBank;
  415. mapping(address => uint) public partnerRewards;
  416.  
  417. function newPartnership(address usecase, address partner) public {
  418. require(msg.sender == haleySales && useCaseBank[usecase] == address0);
  419. useCaseBank[usecase] = partner;
  420. }
  421.  
  422. function payPartner(address partner) public{
  423. require( partnerRewards[partner] > 0 );
  424. uint money = partnerRewards[partner];
  425. partnerRewards[partner] = 0;
  426. payable(partner).transfer( money );
  427. }
  428.  
  429. //------------------------------ Request Ticket Life Cycle
  430. event FileRequestTicket(address sender, uint ticketID, uint8 dataType, bool subjective, uint timeRequested, uint responseTimeWindow, uint feePaid);
  431. function fileRequestTicket( uint8 returnType, bool subjective) public payable returns(uint ticketID){
  432. uint ETH = msg.value;
  433. address sender = msg.sender;
  434. (uint txCoverageFee, uint serviceFee) = getFee();
  435.  
  436. uint devFee = serviceFee/20;
  437.  
  438. require( (returnType == 1 || returnType == 0) && registered[sender] );
  439.  
  440. if(ETH >= txCoverageFee + serviceFee + devFee){
  441.  
  442. ticketID = requestTicketCount;
  443. RequestTicket storage ticket = requestTickets[requestTicketCount];
  444. requestTicketCount++;
  445.  
  446. ticket.dataType = returnType;
  447. ticket.timeRequested = _now();
  448. ticket.timeWindow = oracleConfigurations[RESPONSE_TIME_WINDOW];
  449. ticket.ID = ticketID;
  450. ticket.sender = sender;
  451. ticket.subjective = subjective;
  452. ticket.serviceFee = ETH - devFee - txCoverageFee;
  453.  
  454. if( useCaseBank[sender] != address0 ){
  455. devFunds += devFee/10; // 0.5%
  456. partnerRewards[ useCaseBank[sender] ] += devFee - devFee/10; // 4.5%
  457. }else{
  458. devFunds += devFee;
  459. }
  460.  
  461. earningsPerWatcher += txCoverageFee / totalWatchers;
  462.  
  463. emit FileRequestTicket(msg.sender, ticketID, returnType, subjective, _now(), ticket.timeWindow, ETH);
  464. }else{
  465. revert();
  466. }
  467. }
  468.  
  469. event CommitVote(address voter, uint ticketID, bytes32 hash);
  470. function commitVote(uint[] memory tickets, bytes32[] memory voteHashes) external{
  471. address sender = msg.sender;
  472. RequestTicket storage ticket;
  473. for(uint R; R<tickets.length; R+=1 ){
  474. ticket = requestTickets[ tickets[R] ];
  475. if( _now() <= ticket.timeRequested + ticket.timeWindow ){
  476. ticket.committed[sender] = true;
  477. ticket.commitHash[sender] = voteHashes[R];
  478. emit CommitVote(sender, tickets[R], voteHashes[R]);
  479. }else{
  480. revert();//outside of timewindow
  481. }
  482. }
  483. }
  484.  
  485. event RevealVote(address voter, uint ticketID, bool rejected, int intVote, address addressVote, string comments);
  486. function revealVote(uint[] memory tickets, bool[] memory rejected, int[] memory intVotes, address[] memory addressVotes, uint[] memory passwords, string memory comments) external{
  487. address sender = msg.sender;
  488. RequestTicket storage ticket;
  489. bytes memory abiEncodePacked;
  490. for(uint R; R<tickets.length; R+=1 ){
  491. ticket = requestTickets[ tickets[R] ];
  492. if( ticket.committed[sender] ){
  493. if(_now() > ticket.timeRequested + ticket.timeWindow && _now() <= ticket.timeRequested + ticket.timeWindow*2 ){
  494. if(ticket.dataType == 1){
  495. abiEncodePacked = abi.encodePacked( rejected[R], intVotes[R], passwords[R] );
  496. }else if(ticket.dataType == 0){
  497. abiEncodePacked = abi.encodePacked( rejected[R], addressVotes[R], passwords[R] );
  498. }
  499.  
  500. if( compareBytes( keccak256(abiEncodePacked), requestTickets[ tickets[R] ].commitHash[sender]) ){
  501.  
  502. requestTickets[ tickets[R] ].revealed[sender] = true;
  503. if(rejected[R]){
  504. requestTickets[ tickets[R] ].rejected[sender] = true;
  505. }else{
  506. requestTickets[ tickets[R] ].voted[sender] = true;
  507. if(ticket.dataType == 1){
  508. requestTickets[ tickets[R] ].intVotes[sender] = intVotes[R];
  509. }else if(ticket.dataType == 0){
  510. requestTickets[ tickets[R] ].addressVotes[sender] = addressVotes[R];
  511. }
  512. }
  513. emit RevealVote(sender, tickets[R], rejected[R], intVotes[R], addressVotes[R], comments);
  514. }else{
  515. revert();//not a match
  516. }
  517. }else{
  518. revert();//outside of timewindow
  519. }
  520. }
  521. }
  522. }
  523.  
  524. event SubjectiveStance(address voter, uint ticketID, address defender, bool stance);
  525. function subjectiveStance(uint[] memory tickets, address[] memory defenders, bool[] memory stances) external{
  526. address sender = msg.sender;
  527. RequestTicket storage ticket;
  528. for(uint R; R<tickets.length; R+=1 ){
  529. ticket = requestTickets[ tickets[R] ];
  530. if(timeSeated[sender] <= ticket.timeRequested){
  531. if( timeSeated[defenders[R]] <= ticket.timeRequested && _now() > ticket.timeRequested + ticket.timeWindow*2 && _now() <= ticket.timeRequested + ticket.timeWindow*3 ){
  532. ticket.attacks[sender][defenders[R]] = stances[R];
  533. emit SubjectiveStance(sender, tickets[R], defenders[R], stances[R]);
  534. }else{
  535. revert();//outside timewindow
  536. }
  537. }else{
  538. revert();//you just got here homie, whatcha takin' shots for?
  539. }
  540. }
  541. }
  542.  
  543. function calculateDamage( uint ticketID ) internal view returns(uint combatWeight, uint[] memory damage){
  544. RequestTicket storage ticket = requestTickets[ticketID];
  545. address offensiveWatcher;
  546. address defender;
  547. uint Y;
  548. uint X;
  549. damage = new uint[](hotSeats);
  550. if(ticket.subjective){
  551. for(X = 0; X < hotSeats; X+=1){
  552. offensiveWatcher = chairsCandidate[X];
  553. if( isWatcher[offensiveWatcher] && timeSeated[offensiveWatcher] <= ticket.timeRequested ){
  554. combatWeight += totalShares[offensiveWatcher];
  555. for(Y = 0; Y < hotSeats; Y+=1){
  556. defender = chairsCandidate[Y];
  557. if( isWatcher[defender] && timeSeated[defender] <= ticket.timeRequested){
  558. if(ticket.attacks[offensiveWatcher][defender]){
  559. damage[Y] += totalShares[offensiveWatcher];
  560. }
  561. }
  562. }
  563. }
  564. }
  565. }
  566. }
  567.  
  568. event FinalizedRequest(uint ticketID, address[] watchers);
  569. function finalizeRequests(uint[] memory tickets) external{
  570. for(uint R; R<tickets.length; R+=1 ){
  571. finalizeRequest( tickets[R] );
  572. }
  573. }
  574.  
  575. function finalizeRequest(uint ticketID) public{
  576. // if response time window is over or all delegates have voted,
  577. // anyone can finalize the request to trigger the event
  578. RequestTicket storage ticket = requestTickets[ticketID];
  579. if(!ticket.finalized){
  580.  
  581. address watcher;
  582.  
  583. int[] memory intOptions = new int[](hotSeats);
  584. address[] memory addressOptions = new address[](hotSeats);
  585. uint[] memory optionWeights = new uint[](hotSeats);
  586.  
  587. address[] memory watchers = new address[](hotSeats);// lazy UI data
  588.  
  589. 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
  590.  
  591. uint opt;
  592. uint[] memory damage;
  593. (UINTs[5]/*combatWeight*/, damage) = calculateDamage(ticketID);
  594. for(uint chair = 0; chair < hotSeats; chair+=1){
  595. watcher = chairsCandidate[chair];
  596. watchers[chair] = watcher;
  597. if(damage[chair]<=UINTs[5]/*combatWeight*//2){
  598. if( watcher!=address0 && isWatcher[watcher] && timeSeated[watcher] <= ticket.timeRequested && ticket.revealed[watcher] ){
  599. UINTs[4]/*total Eligible Weight*/ += totalShares[watcher];
  600. if( ticket.voted[watcher] ){
  601. UINTs[0]/*weight of votes*/ += totalShares[watcher];
  602. //check to see if chosen option already is accounted for, if so, add weight to it.
  603. for(opt = 0; opt<UINTs[2]/*option count*/; opt+=1){
  604. if( (ticket.dataType == 1 && intOptions[opt] == ticket.intVotes[watcher]) ||
  605. (ticket.dataType == 0 && addressOptions[opt] == ticket.addressVotes[watcher])
  606. ){
  607. optionWeights[opt] += totalShares[watcher];
  608. if(optionWeights[opt] > optionWeights[UINTs[3]/*top option*/] && !ticket.subjective){
  609. UINTs[3]/*top option*/ = opt;
  610. }
  611. break;
  612. }
  613. }
  614.  
  615. //add new unique option
  616. if(opt == UINTs[2]/*option count*/){
  617. if(ticket.dataType == 1){
  618. intOptions[UINTs[2]/*option count*/] = ticket.intVotes[watcher];
  619. }else if(ticket.dataType == 0){
  620. addressOptions[UINTs[2]/*option count*/] = ticket.addressVotes[watcher];
  621. }
  622. optionWeights[UINTs[2]/*option count*/] = totalShares[watcher];
  623.  
  624. UINTs[2]/*option count*/+=1;
  625. }
  626. }else if(ticket.rejected[watcher]){
  627. UINTs[1]/*weight of rejections*/ += totalShares[watcher];
  628. }
  629. }
  630. }else{
  631. ticket.damaged[watcher] = true;
  632. }
  633. }
  634.  
  635. 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) ) ){
  636.  
  637. bool rejected;
  638. if( UINTs[1]/*weight of rejections*/ > optionWeights[UINTs[3]/*top option*/] || UINTs[2]/*option count*/ == 0){
  639. rejected = true;
  640. }
  641. uint8 dataType = ticket.dataType;
  642. //write results in stone
  643. if(rejected){
  644. ticket.ticketRejected = true;
  645. }else{
  646. if(ticket.subjective){
  647. ticket.numberOfOptions = UINTs[2]/*option count*/;
  648. for(UINTs[6]=0;UINTs[6]<UINTs[2];UINTs[6]+=1){
  649. ticket.weightOfResults[UINTs[6]] = optionWeights[UINTs[6]];
  650. if(dataType == 1){
  651. ticket.resolvedInts[UINTs[6]] = intOptions[UINTs[6]];
  652. }else if(dataType == 0){
  653. ticket.resolvedAddresses[UINTs[6]] = addressOptions[UINTs[6]];
  654. }
  655. }
  656. }else{
  657. ticket.numberOfOptions = UINTs[2]==0?0:1;//just in case no one responds the number of options needs to be 0
  658. if(dataType == 1){
  659. ticket.resolvedInts[0] = intOptions[UINTs[3]/*top option*/];
  660. }else if(dataType == 0){
  661. ticket.resolvedAddresses[0] = addressOptions[UINTs[3]/*top option*/];
  662. }
  663. }
  664. }
  665.  
  666. //dish out the rewards
  667. earningsPerShare[ORACLE] += ticket.serviceFee * scaleFactor / totalShares[ORACLE];
  668.  
  669. ticket.finalized = true;
  670. if(ticket.subjective){
  671. if(dataType == 1){
  672. Requestor(ticket.sender).oracleIntFallback(ticket.ID, ticket.ticketRejected, ticket.numberOfOptions, optionWeights, intOptions);
  673. }else if(dataType == 0){
  674. Requestor(ticket.sender).oracleAddressFallback(ticket.ID, ticket.ticketRejected, ticket.numberOfOptions, optionWeights, addressOptions);
  675. }
  676. }else{
  677. if(dataType == 1){
  678. Requestor(ticket.sender).oracleObjectiveIntFallback(ticket.ID, ticket.ticketRejected, intOptions[0]);
  679. }else if(dataType == 0){
  680. Requestor(ticket.sender).oracleObjectiveAddressFallback(ticket.ID, ticket.ticketRejected, addressOptions[0]);
  681. }
  682. }
  683.  
  684. emit FinalizedRequest(ticket.ID, watchers);
  685. lastTimeTicketWasFinalized = _now();
  686. }else{
  687. revert();
  688. }
  689. }
  690. }
  691.  
  692. event Cashout(address addr, uint ETH);
  693. function cashout(address[] memory pools) external{
  694. address payable sender = payable(msg.sender);
  695. for(uint p; p < pools.length; p+=1){
  696. update(pools[p], sender);
  697. }
  698. runWatcherPayroll(sender);
  699. uint ETH = earnings[sender];
  700. earnings[sender] = 0;
  701. emit Cashout(sender, ETH);
  702. sender.transfer( ETH );
  703. }
  704.  
  705. function runWatcherPayroll(address watcher) public{
  706. if( isWatcher[watcher] ){
  707. update(ORACLE, watcher );
  708. updateWatcherTxEarnings( watcher, true );
  709. }
  710. }
  711.  
  712. function tryToPunish(uint[] memory tickets, address[] memory watchers) external{
  713. freezeNoncommits(tickets, watchers);
  714. freezeUnrevealedCommits(tickets, watchers);
  715. freezeWrongWatchers(tickets, watchers);
  716. }
  717.  
  718. event FreezeNoncommits(uint ticketID, address watcher);
  719. function freezeNoncommits(uint[] memory tickets, address[] memory watchers) public{
  720. // get them while they're still at the round table and we're in the reveal phase of a ticket
  721. RequestTicket storage ticket;
  722. for(uint i; i<watchers.length; i+=1){
  723. ticket = requestTickets[ tickets[i] ];
  724. if( isWatcher[ watchers[i] ] &&
  725. !ticket.committed[ watchers[i] ] &&
  726. timeSeated[ watchers[i] ] <= ticket.timeRequested &&
  727. _now() > ticket.timeRequested + ticket.timeWindow
  728. ){
  729. if(punish(tickets[i] , watchers[i]) ){
  730. emit FreezeNoncommits(tickets[i] , watchers[i]);
  731. }
  732. }
  733. }
  734. }
  735.  
  736. event FreezeUnrevealedCommits(uint ticketID, address watcher);
  737. function freezeUnrevealedCommits(uint[] memory tickets, address[] memory watchers) public{
  738. // get them if they made a commit, but did not reveal it after the reveal window is over
  739. RequestTicket storage ticket;
  740. for(uint i; i<watchers.length; i+=1){
  741. ticket = requestTickets[ tickets[i] ];
  742. if( isWatcher[ watchers[i] ] &&
  743. !ticket.revealed[ watchers[i] ] &&
  744. timeSeated[ watchers[i] ] <= ticket.timeRequested &&
  745. _now() > requestTickets[ tickets[i] ].timeRequested + ticket.timeWindow*2
  746. ){
  747. if(punish(tickets[i] , watchers[i]) ){
  748. emit FreezeUnrevealedCommits(tickets[i] , watchers[i]);
  749. }
  750. }
  751. }
  752. }
  753.  
  754. event FreezeWrongWatchers(uint ticketID, address watcher);
  755. function freezeWrongWatchers(uint[] memory tickets, address[] memory watchers) public{
  756. // get them if the ticket is finalized and their vote doesn't match the resolved answer
  757. address watcher;
  758. RequestTicket storage ticket;
  759. for(uint i; i<watchers.length; i+=1){
  760. ticket = requestTickets[ tickets[i] ];
  761. watcher = watchers[i];
  762. if( ticket.finalized &&
  763. isWatcher[ watchers[i] ] &&
  764. timeSeated[ watchers[i] ] <= ticket.timeRequested &&
  765. !ticket.ticketRejected &&
  766. (
  767. (!ticket.subjective && (
  768. (ticket.dataType == 1 && ticket.resolvedInts[0] != ticket.intVotes[ watcher ] )||
  769. (ticket.dataType == 0 && ticket.resolvedAddresses[0] != ticket.addressVotes[ watcher ] )
  770. ))||
  771. (ticket.subjective && ticket.damaged[ watcher ] )||//if their subjective contribution is garbage
  772. ticket.rejected[ watcher ]//if they reject something the majority didn't reject
  773. )
  774. ){
  775. if(punish(tickets[i] , watcher)){
  776. emit FreezeWrongWatchers(tickets[i] , watcher);
  777. }
  778. }
  779. }
  780. }
  781.  
  782. event Punish(address watcher, uint thawOutTime);
  783. function punish(uint ticketID, address watcher) internal returns(bool punished){
  784. RequestTicket storage ticket = requestTickets[ticketID];
  785. if(latestPunishment[watcher] < ticket.timeRequested+ticket.timeWindow*(ticket.subjective?3:2)){
  786. if( isWatcher[watcher] ){
  787. removeShares(ORACLE, watcher, totalShares[watcher]);
  788. }
  789.  
  790. frozen[watcher] = true;
  791. latestPunishment[watcher] = ticket.timeRequested;
  792. timeWhenThawedOut[watcher] = _now() + oracleConfigurations[FREEZE_TIMEOUT];
  793.  
  794. emit Punish(watcher, timeWhenThawedOut[watcher]);
  795. return true;
  796. }
  797. return false;
  798. }
  799.  
  800. event Thaw(address candidate);
  801. function thaw(address candidate, bool _assert) public{
  802. if( _now() >= timeWhenThawedOut[candidate] && frozen[candidate] ) {
  803. frozen[candidate] = false;
  804. if(_assert && candidate == msg.sender){
  805. assertCandidate();
  806. }
  807. emit Thaw(candidate);
  808. }else{
  809. revert();
  810. }
  811. }
  812.  
  813. event UpdateRoundTable(uint newTotalHotSeats);
  814. function updateRoundTable(uint seats) public{
  815. // update hotSeats for when they're lower.
  816. uint s;
  817. uint i;
  818. uint weakestChair;
  819. address thisWatcher;
  820. uint configSEATS = oracleConfigurations[ROUNDTABLE_SEATS];
  821.  
  822. if( configSEATS == hotSeats ) return;
  823.  
  824. if( hotSeats > totalWatchers && configSEATS < hotSeats){
  825. hotSeats = totalWatchers;
  826. }
  827.  
  828. for( s = 0; s<seats; s+=1 ){
  829.  
  830. for( i=0; i<hotSeats; i+=1){
  831. thisWatcher = chairsCandidate[i];
  832. if( totalShares[ thisWatcher ] < totalShares[ chairsCandidate[weakestChair] ] ){
  833. weakestChair = i;
  834. }
  835. }
  836.  
  837. thisWatcher = chairsCandidate[weakestChair];
  838. removeShares(ORACLE, thisWatcher, totalShares[thisWatcher]);
  839.  
  840. hotSeats-=1;
  841.  
  842. if( configSEATS == hotSeats ){break;}
  843. }
  844.  
  845. emit UpdateRoundTable(hotSeats);
  846. }
  847.  
  848. function viewRequestTicket(uint ticketID) public view returns(
  849. address sender,
  850. uint timeRequested,
  851. uint timeWindow,
  852. uint numberOfOptions,
  853. bool finalized,
  854. bool rejected,
  855. uint[] memory weightOfResults,
  856. int[] memory resolvedInts,
  857. address[] memory resolvedAddresses
  858. ){
  859. RequestTicket storage T = requestTickets[ticketID];
  860. sender = T.sender;
  861. timeRequested = T.timeRequested;
  862. timeWindow = T.timeWindow;
  863. finalized = T.finalized;
  864. numberOfOptions = T.numberOfOptions;
  865. rejected = T.ticketRejected;
  866.  
  867. weightOfResults = new uint[](T.numberOfOptions);
  868. resolvedInts = new int[](T.numberOfOptions);
  869. resolvedAddresses = new address[](T.numberOfOptions);
  870. //yikes
  871. for(uint i = 0; i< T.numberOfOptions; i+=1){
  872. weightOfResults[i] = T.weightOfResults[i];
  873. resolvedInts[i] = T.resolvedInts[i];
  874. resolvedAddresses[i] = T.resolvedAddresses[i];
  875. }
  876. }
  877.  
  878. function viewCandidates(bool personal_or_roundtable, address perspective) public view returns(address[] memory addresses, uint[] memory dividends, uint[] memory seat, uint[] memory weights, uint[] memory clocks, bool[] memory isFrozen, bool[] memory atTable, uint[] memory roundTableDividends){
  879. uint L;
  880.  
  881. if(personal_or_roundtable){
  882. L = hotSeats;
  883. }else{
  884. L = yourBacking[perspective].length;
  885. }
  886.  
  887. dividends = new uint[](L);
  888. seat = new uint[](L);
  889. roundTableDividends = new uint[](L);
  890.  
  891. weights = new uint[](L*2);
  892. clocks = new uint[](L*3);
  893.  
  894. isFrozen = new bool[](L);
  895. atTable = new bool[](L);
  896.  
  897. addresses = new address[](L);
  898.  
  899. address candidate;
  900. for(uint c = 0; c<L; c+=1){
  901. if(personal_or_roundtable){
  902. candidate = chairsCandidate[c];
  903. }else{
  904. candidate = yourBacking[perspective][c];
  905. }
  906. addresses[c] = candidate;
  907. dividends[c] = dividendsOf(candidate, perspective);
  908. roundTableDividends[c] = dividendsOf(ORACLE, candidate);
  909. seat[c] = candidatesChair[candidate];
  910. weights[c] = shares[candidate][perspective];
  911. weights[c+L] = totalShares[candidate];
  912. isFrozen[c] = frozen[candidate];
  913. atTable[c] = isWatcher[candidate];
  914. clocks[c] = timeWhenThawedOut[candidate];
  915. clocks[c+L] = timeSeated[candidate];
  916. clocks[c+L*2] = latestPunishment[candidate];
  917. }
  918. }
  919.  
  920. function viewGovernance() public view returns(uint[] memory data){
  921. data = new uint[](CONFIGS);
  922. for(uint i = 0; i< CONFIGS; i+=1){
  923. data[i] = oracleConfigurations[i];
  924. }
  925. }
  926.  
  927. function accountData(address account) public view returns(
  928. uint _resolveWeight,
  929. uint _weightLocked,
  930. uint _timeSeated,
  931. bool _frozen,
  932. bool _isWatcher,
  933. uint _earnings,
  934. uint _totalShares,
  935. uint[] memory UINTs
  936. ){
  937. _resolveWeight = resolveWeight[account];
  938. _weightLocked = weightLocked[account];
  939. _timeSeated = timeSeated[account];
  940. _frozen = frozen[account];
  941. _isWatcher = isWatcher[account];
  942. _earnings = earnings[account];
  943. _totalShares = totalShares[account];
  944. UINTs = new uint[](5);
  945.  
  946. if( _isWatcher ){
  947. UINTs[0] = earningsPerWatcher - watcherPayouts[account];//txCoverageFee
  948. UINTs[1] = dividendsOf(ORACLE, account) * oracleConfigurations[DELEGATE_REWARDSHARE] / (1e20);
  949. }
  950.  
  951. UINTs[2] = timeWhenThawedOut[account];
  952. UINTs[3] = latestPunishment[account];
  953. UINTs[4] = candidatesChair[account];
  954. }
  955.  
  956. function compareStrings(string memory a, string memory b) public pure returns (bool) {
  957. return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
  958. }
  959. function compareBytes(bytes32 a, bytes32 b) public pure returns (bool) {
  960. return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
  961. }
  962. function bytesToAddress(bytes memory bys) private pure returns (address addr){
  963. assembly {
  964. addr := mload( add(bys,20) )
  965. }
  966. }
  967. }
  968.  
  969. abstract contract ResolveToken{
  970. function transfer(address _to, uint256 _value) public virtual returns (bool);
  971. }
  972.  
  973. abstract contract Pyramid{
  974. function resolveToken() public view virtual returns(ResolveToken);
  975. }
  976.  
  977. abstract contract Requestor{
  978. function oracleIntFallback(uint ticketID, bool EXCEPTION, uint numberOfOptions, uint[] memory optionWeights, int[] memory intOptions) public virtual;
  979. function oracleAddressFallback(uint ticketID, bool EXCEPTION, uint numberOfOptions, uint[] memory optionWeights, address[] memory addressOptions) external virtual;
  980. function oracleObjectiveIntFallback(uint ticketID, bool EXCEPTION, int resolved_int) external virtual;
  981. function oracleObjectiveAddressFallback(uint ticketID, bool EXCEPTION, address resolved_address) external virtual;
  982. }
  983.  
  984. // fearless, into the black
Advertisement
Add Comment
Please, Sign In to add comment