Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^ 0.6.6;
- pragma experimental ABIEncoderV2;
- contract Oracle{
- address ORACLE = address(0);
- address address0 = address(0);
- struct RequestTicket{
- uint ID;
- address sender;
- string query;
- uint timeRequested;
- uint timeWindow;
- bool finalized;
- uint txCoverageFee;
- uint serviceFee;
- bool subjective;
- bool ticketRejected;
- uint numberOfOptions;
- mapping(uint => string) resolvedStrings;
- mapping(uint => int) resolvedInts;
- mapping(uint => bytes) resolvedBytes;
- mapping(uint => address) resolvedAddresses;
- mapping(address => mapping(address => bool)) attacks;
- mapping(address => bool) damaged;
- mapping(address => bool) punished;
- uint8 dataType; // string, uint, bool, address
- //commit
- mapping(address => bool) committed;
- mapping(address => bytes32) commitHash;
- //reveal
- mapping(address => bool) revealed;
- mapping(address => bool) rejected;
- mapping(address => bool) voted;
- mapping(address => string) stringVotes;
- mapping(address => int) intVotes;
- mapping(address => bytes) bytesVotes;
- mapping(address => address) addressVotes;
- }
- //oracle configs
- uint constant ROUNDTABLE_SEATS = 0;
- uint constant RESPONSE_TIME_WINDOW = 1;
- uint constant DELEGATE_REWARDSHARE = 2;
- uint constant FREEZE_TIMEOUT = 3;
- uint constant TX_FEE_PER = 4;
- uint constant SERVICE_FEE = 5;
- uint constant CONFIGS = 6;
- uint[] public oracleConfigurations = new uint[](CONFIGS);
- mapping(uint/*configID*/ => mapping(uint => uint) ) public totalVotes_forEach_configOption;
- mapping(uint/*configID*/ => mapping(address => uint) ) public individualsSelectedOption;
- mapping(address => uint) resolveWeight;
- mapping(address => uint) weightLocked;
- mapping(uint => RequestTicket) requestTickets;
- uint public requestTicketCount;
- //ROUND TABLE & Candidates
- mapping(uint => address) public chairsCandidate; // only looks at the first X indexes
- mapping(address => uint) candidatesChair;
- mapping(address => uint) timeSeated; // watchers aren't responsible for requestTickets that came in before them
- mapping(address => bool) frozen;
- mapping(address => uint) timeWhenThawedOut;
- mapping(address => bool) paused; // self pause
- mapping(address => bool) hasChair;
- uint chairs;
- uint public hotSeats;
- uint256 constant scaleFactor = 0x10000000000000000;
- //PAYROLL
- mapping(address => uint) earnings;
- mapping(address => uint) totalShares;
- mapping(address => mapping(address => uint256)) public shares;
- mapping(address => mapping(address => uint256)) payouts;
- mapping(address => uint) earningsPerShare;
- //Tx Coverage fee
- uint earningsPerWatcher;
- uint totalWatchers;
- mapping(address => uint256) watcherPayouts;
- //lazy UI data
- mapping(address => address[]) public yourBacking;
- mapping(address => mapping(address => bool)) public alreadyBacking;
- ResolveToken resolveToken;
- constructor(address _resolve) public{
- resolveToken = ResolveToken(_resolve);
- }
- function addressPayable(address addr) public pure returns(address payable){
- return address( uint160(addr) );
- }
- function addShares(address pool, address account, uint amount) internal{
- update(pool, account);
- totalShares[pool] += amount;
- shares[pool][account] += amount;
- if(pool == ORACLE){
- updateWatcherTxEarnings(account);
- totalWatchers += 1;
- }
- }
- function removeShares(address pool, address account, uint amount) internal{
- update(pool, account);
- totalShares[pool] -= amount;
- shares[pool][account] -= amount;
- if(pool == ORACLE){
- updateWatcherTxEarnings(account);
- totalWatchers -= 1;
- }
- }
- event ConsolidateEarnings(address account, uint amount);
- event WatcherPayroll(address watcher, uint paidOut);
- function update(address pool, address account) internal {
- uint owedPerShare = earningsPerShare[pool] - payouts[pool][account];
- uint newMoney = shares[pool][account] * owedPerShare;
- payouts[pool][account] = earningsPerShare[pool];
- if(pool == ORACLE){
- uint eth4Watcher = newMoney * oracleConfigurations[DELEGATE_REWARDSHARE] / 1e18;
- earnings[account] += eth4Watcher/scaleFactor;
- uint newDivs;
- if(totalShares[account]>0)
- newDivs = (newMoney - eth4Watcher)/totalShares[account];
- else
- newDivs = 0;
- earningsPerShare[account/*this is what the watcher has to distribute to its electorates*/] += newDivs;
- emit ConsolidateEarnings(account, eth4Watcher/scaleFactor);
- emit WatcherPayroll(account, newDivs);
- }else{
- earnings[account] += newMoney/scaleFactor;
- emit ConsolidateEarnings(account, newMoney/scaleFactor);
- }
- }
- event TxCashout(address watcher, uint amount);
- function updateWatcherTxEarnings(address watcher) internal {
- uint owed = earningsPerWatcher - watcherPayouts[watcher];
- watcherPayouts[watcher] = earningsPerWatcher;
- earnings[watcher] += owed;
- emit TxCashout(watcher, owed);
- }
- event StakeResolves( address indexed addr, uint256 amountStaked, bytes _data );
- function tokenFallback(address from, uint value, bytes calldata _data) external{
- if( msg.sender == address(resolveToken) ){
- resolveWeight[from] += value;
- //update option totals
- uint option;
- for(uint8 config = 0; config<CONFIGS; config+=1){
- option = individualsSelectedOption[config][from];
- totalVotes_forEach_configOption[config][option] += value;
- assertOption(config, option);
- }
- emit StakeResolves(from, value, _data);
- //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
- /*
- address backImmediately = bytesToAddress( _data );
- if( backImmediately != address0){
- backCandidate(0xf4b218f2949Bc48720cC451f6BBb34E794a0Ba21,value, false);
- }*/
- }else{
- revert();
- }
- }
- event UnstakeResolves(address sender, uint amount);
- function unstakeResolves(uint amount) public{
- address sender = msg.sender;
- if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) ){
- resolveWeight[sender] -= amount;
- for(uint config = 0; config<CONFIGS; config+=1){
- totalVotes_forEach_configOption[config][individualsSelectedOption[config][sender]] -= amount;
- }
- emit UnstakeResolves(sender, amount);
- resolveToken.transfer(sender, amount);
- }else{
- revert();
- }
- }
- event BackCandidate(address sender,address candidate, uint amount);
- function backCandidate(address candidate, uint amount, bool _assert) public{
- address sender = msg.sender;
- require(candidate!=ORACLE);
- if( amount <= ( resolveWeight[sender] - weightLocked[sender] ) && !isWatcher(candidate) ){
- weightLocked[sender] += amount;
- addShares(candidate, sender, amount);
- //I guess candidates should be able to opt into pausing themselves instead of being cast as a delegate right away.
- //Idk where else to write this comment
- //If the candidate isn't seated, and freezing and pause isn't preventing them from being seated ... then assertCandidate()
- if( candidatesChair[candidate] >= hotSeats && !frausted(candidate) && _assert){
- assertCandidate(candidate);
- }
- emit BackCandidate(sender, candidate, amount);
- //LAZY U.I.
- if(!alreadyBacking[sender][candidate]){
- yourBacking[sender].push(candidate);
- alreadyBacking[sender][candidate] = true;
- }
- }else{
- revert();
- }
- }
- event WithdrawBacking(address sender,address candidate, uint amount);
- function withdrawBacking(address candidate, uint amount) public{
- address sender = msg.sender;
- if( amount <= shares[candidate][sender] && !frozen[candidate] && ( !(candidatesChair[candidate]<hotSeats) || paused[candidate] ) ){
- weightLocked[sender] -= amount;
- removeShares(candidate, sender, amount);
- emit WithdrawBacking(sender, candidate, amount);
- }else{
- revert();
- }
- }
- function frausted(address candidate) public view returns(bool){
- return paused[candidate] || frozen[candidate];
- }
- event AssertCandidate(address candidate, bool asserted, address replacedWatcher, uint newSeat);
- function assertCandidate(address candidate) public returns(bool success){
- uint weakestChair;
- bool nullSeat;
- address thisWatcher;
- for(uint i; i<hotSeats; i+=1){
- thisWatcher = chairsCandidate[i];
- if( frausted( thisWatcher ) || thisWatcher == address0 ){
- nullSeat = true;
- weakestChair = i;
- }else if( totalShares[ thisWatcher ] < totalShares[ chairsCandidate[weakestChair] ] ){
- weakestChair = i;
- }
- if(nullSeat){
- break;
- }
- }
- if( (totalShares[candidate] > totalShares[ chairsCandidate[weakestChair] ] || nullSeat ) && !isWatcher(candidate) ) {
- address targetCandidate = chairsCandidate[weakestChair];
- if(targetCandidate!=address0)
- removeShares(ORACLE, targetCandidate, totalShares[targetCandidate]);
- addShares(ORACLE, candidate, totalShares[candidate]);
- timeSeated[candidate] = now;
- hasChair[candidate] = true;
- hasChair[targetCandidate] = false;
- chairsCandidate[weakestChair] = candidate;
- candidatesChair[candidate] = weakestChair;
- return true;
- }
- return false;
- }
- event OptionVote(address sender, uint config, uint option, uint weight);
- function optionVote(bool[] memory isModifying, uint[] memory modifiedOptions) public{
- address sender = msg.sender;
- uint config;
- uint modifiedOption;
- for(config = 0; config<CONFIGS; config+=1){
- if(isModifying[config]){
- modifiedOption = modifiedOptions[config];
- totalVotes_forEach_configOption[config][ individualsSelectedOption[config][sender] ] -= resolveWeight[sender];
- individualsSelectedOption[config][sender] = modifiedOption;
- totalVotes_forEach_configOption[config][ modifiedOption ] += resolveWeight[sender];
- emit OptionVote(sender, config, modifiedOption, resolveWeight[sender]);
- assertOption( config, modifiedOption );
- }
- }
- }
- event AssertOption(uint config, uint option);
- function assertOption(uint config, uint option) public{
- if( totalVotes_forEach_configOption[config][option] > totalVotes_forEach_configOption[config][ oracleConfigurations[config] ] ){
- oracleConfigurations[config] = option;
- emit AssertOption(config, option);
- }
- }
- function isWatcher(address candidate) public view returns(bool){
- return candidatesChair[candidate]<hotSeats && hasChair[candidate] && !frausted(candidate);
- }
- function getFee() public view returns(uint txCoverageFee, uint serviceFee){
- uint activeWatchers;
- for(uint chair = 0; chair<hotSeats; chair+=1){
- if( !frausted(chairsCandidate[chair]) ){
- activeWatchers += 1;
- }
- }
- return ( oracleConfigurations[TX_FEE_PER]*activeWatchers, oracleConfigurations[SERVICE_FEE] );
- }
- //------------------------------ Request Ticket Life Cycle
- event FileRequestTicket(address sender, uint ticketID, string query, uint timeRequested, uint8 dataType, uint feePaid);
- function fileRequestTicket(string memory query, uint8 returnType, bool subjective) public payable returns(uint ticketID){
- uint ETH = msg.value;
- (uint txCoverageFee, uint serviceFee) = getFee();
- if(ETH == txCoverageFee + serviceFee ){
- if(returnType>3) returnType = 3;
- ticketID = requestTicketCount;
- requestTicketCount++;
- RequestTicket storage ticket = requestTickets[requestTicketCount];
- ticket.query = query;
- ticket.dataType = returnType;
- ticket.timeRequested = now;
- ticket.timeWindow = oracleConfigurations[RESPONSE_TIME_WINDOW];
- ticket.ID = ticketID;
- ticket.sender = msg.sender;
- ticket.subjective = subjective;
- ticket.txCoverageFee = txCoverageFee;
- ticket.serviceFee = serviceFee;
- emit DATA(0, ticketID);
- emit DATA(3, oracleConfigurations[RESPONSE_TIME_WINDOW]);
- emit FileRequestTicket(msg.sender, ticketID, query, now, returnType, ETH);
- return ticketID;
- }else{
- revert();
- }
- }
- event CommitVote(address sender, uint ticketID, bytes32 hash);
- function commitVote(uint[] memory tickets, bytes32[] memory voteHashes) public{
- address sender = msg.sender;
- RequestTicket storage ticket;
- for(uint R; R<tickets.length; R+=1 ){
- ticket = requestTickets[ tickets[R] ];
- if(now <= ticket.timeRequested + ticket.timeWindow ){
- ticket.committed[sender] = true;
- ticket.commitHash[sender] = voteHashes[R];
- emit CommitVote(sender, tickets[R], voteHashes[R]);
- }
- }
- }
- event DATA(uint8 VAR, uint NUMERIC);
- event RevealVote(address voter, uint ticketID, bool rejected, /*suba*/ string stringVote, int intVote, bytes bytesVote, address addressVote);
- 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){
- address sender = msg.sender;
- RequestTicket memory ticket;
- bytes memory abiEncodePacked;
- commitsMatchingReveals = new bool[](tickets.length);
- //emit DATA(0, now);
- for(uint R; R<tickets.length; R+=1 ){
- ticket = requestTickets[ tickets[R] ];
- //emit DATA(1, ticket.timeRequested + ticket.timeWindow);
- //emit DATA(2, ticket.timeRequested + ticket.timeWindow*2);
- if(now > ticket.timeRequested + ticket.timeWindow && now <= ticket.timeRequested + ticket.timeWindow*2 ){
- //emit DATA(3, 1);
- if(ticket.dataType == 0){
- abiEncodePacked = abi.encodePacked( rejected[R], stringVotes[R], passwords[R] );
- }else if(ticket.dataType == 1){
- abiEncodePacked = abi.encodePacked( rejected[R], intVotes[R], passwords[R] );
- }else if(ticket.dataType == 2){
- abiEncodePacked = abi.encodePacked( rejected[R], bytesVotes[R], passwords[R] );
- }else if(ticket.dataType == 3){
- abiEncodePacked = abi.encodePacked( rejected[R], addressVotes[R], passwords[R] );
- }
- if( compareBytes( keccak256(abiEncodePacked), requestTickets[ tickets[R] ].commitHash[sender]) ){
- //emit DATA(4, 1+ticket.dataType);
- commitsMatchingReveals[R] = true;
- requestTickets[ tickets[R] ].revealed[sender] = true;
- if(rejected[R]){
- requestTickets[ tickets[R] ].rejected[sender] = true;
- }else{
- requestTickets[ tickets[R] ].voted[sender] = true;
- if(ticket.dataType == 0){
- requestTickets[ tickets[R] ].stringVotes[sender] = stringVotes[R];
- }else if(ticket.dataType == 1){
- requestTickets[ tickets[R] ].intVotes[sender] = intVotes[R];
- }else if(ticket.dataType == 2){
- requestTickets[ tickets[R] ].bytesVotes[sender] = bytesVotes[R];
- }else if(ticket.dataType == 3){
- requestTickets[ tickets[R] ].addressVotes[sender] = addressVotes[R];
- }
- }
- emit RevealVote(sender, tickets[R], rejected[R], stringVotes[R], intVotes[R], bytesVotes[R], addressVotes[R]);
- }
- }
- }
- }
- event SubjectiveStance(address sender, uint ticketID, address defender, bool stance);
- function subjectiveStance(uint[] memory tickets, address[] memory defenders, bool[] memory stances) public{
- address sender = msg.sender;
- RequestTicket storage ticket;
- for(uint R; R<tickets.length; R+=1 ){
- ticket = requestTickets[ tickets[R] ];
- if( timeSeated[sender] <= ticket.timeRequested && timeSeated[defenders[R]] <= ticket.timeRequested && now > ticket.timeRequested + ticket.timeWindow*2 && now <= ticket.timeRequested + ticket.timeWindow*3 ){
- ticket.attacks[sender][defenders[R]] = stances[R];
- emit SubjectiveStance(sender, tickets[R], defenders[R], stances[R]);
- }
- }
- }
- event Attack(address offense, address defense, uint damage);
- function calculateDamage( uint ticketID ) internal returns(uint combatWeight, uint[] memory damage){
- RequestTicket storage ticket = requestTickets[ticketID];
- address offensiveWatcher;
- address defender;
- uint Y;
- uint X;
- damage = new uint[](hotSeats);
- if(ticket.subjective){
- for(X = 0; X < hotSeats; X+=1){
- offensiveWatcher = chairsCandidate[X];
- if( !frausted(offensiveWatcher) && timeSeated[offensiveWatcher] <= ticket.timeRequested ){
- combatWeight += totalShares[offensiveWatcher];
- for(Y = 0; Y < hotSeats; Y+=1){
- if( !frausted(offensiveWatcher) ){
- defender = chairsCandidate[Y];
- if(ticket.attacks[offensiveWatcher][defender])
- damage[Y] += totalShares[offensiveWatcher];
- emit Attack(offensiveWatcher, defender, totalShares[offensiveWatcher]);
- }
- }
- }
- }
- }
- }
- event FinalizedRequestOptions(string[] stringOptions, uint[] intOptions, bool[] bytesOptions, address[] addressOptions, address[] watchers);
- function finalizeRequest(uint ticketID) public{
- // if responsew time window is over or all delegates have voted,
- // anyone can finalize the request to trigger the event
- RequestTicket storage ticket = requestTickets[ticketID];
- if(!ticket.finalized){
- address watcher;
- string[] memory stringOptions = new string[](hotSeats);
- int[] memory intOptions = new int[](hotSeats);
- bytes[] memory bytesOptions = new bytes[](hotSeats);
- address[] memory addressOptions = new address[](hotSeats);
- uint[] memory optionWeights = new uint[](hotSeats);
- 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
- uint opt;
- uint[] memory damage;
- //emit DATA(0,1);
- (UINTs[5]/*combatWeight*/, damage) = calculateDamage(ticketID);
- for(uint chair = 0; chair < hotSeats; chair+=1){
- //emit DATA(1,chair);
- watcher = chairsCandidate[chair];
- if(damage[chair]<=UINTs[5]/*combatWeight*//2){
- //emit DATA(2,damage[chair]);
- if( watcher!=address0 && !frausted(watcher) && timeSeated[watcher] <= ticket.timeRequested ){
- //emit DATA(4,chair);
- UINTs[4]/*total Eligible Weight*/ += totalShares[watcher];
- if( ticket.voted[watcher] ){
- UINTs[0]/*weight of votes*/ += totalShares[watcher];
- //emit DATA(5, totalShares[watcher]);
- //check to see if chosen option already is accounted for, if so, add weight to it.
- for(opt = 0; opt<UINTs[2]/*option count*/; opt+=1){
- if( (ticket.dataType == 0 && compareStrings(stringOptions[opt], ticket.stringVotes[watcher]) ) ||
- (ticket.dataType == 1 && intOptions[opt] == ticket.intVotes[watcher]) ||
- (ticket.dataType == 2 && compareBytes( keccak256(bytesOptions[opt]), keccak256(ticket.bytesVotes[watcher]) ) ) ||
- (ticket.dataType == 3 && addressOptions[opt] == ticket.addressVotes[watcher])
- ){
- optionWeights[opt] += totalShares[watcher];
- //emit DATA(13,opt);
- //emit DATA(10,optionWeights[opt]);
- if(optionWeights[opt] > optionWeights[UINTs[3]/*top option*/] && !ticket.subjective){
- UINTs[3]/*top option*/ = opt;
- //emit DATA(11,optionWeights[opt]);
- }
- break;
- }
- }
- //add new unique option
- if(opt == UINTs[2]/*option count*/){
- if(ticket.dataType == 0){
- stringOptions[UINTs[2]/*option count*/] = ticket.stringVotes[watcher];
- }else if(ticket.dataType == 1){
- intOptions[UINTs[2]/*option count*/] = ticket.intVotes[watcher];
- }else if(ticket.dataType == 2){
- bytesOptions[UINTs[2]/*option count*/] = ticket.bytesVotes[watcher];
- }else if(ticket.dataType == 3){
- addressOptions[UINTs[2]/*option count*/] = ticket.addressVotes[watcher];
- }
- optionWeights[UINTs[2]/*option count*/] = totalShares[watcher];
- /*if(optionWeights[ UINTs[2] ] > optionWeights[UINTs[3]] && !ticket.subjective){
- UINTs[3] = UINTs[2];
- }*/
- //emit DATA(12,UINTs[2]);
- //emit DATA(10,totalShares[watcher]);
- UINTs[2]/*option count*/+=1;
- }
- }else if(ticket.rejected[watcher]){
- UINTs[1]/*weight of rejections*/ += totalShares[watcher];
- //emit DATA(6,UINTs[1]);
- }
- }
- }else{
- //emit DATA(3,chair);
- ticket.damaged[watcher] = true;
- }
- }
- 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) ) ){
- bool rejected;
- //emit DATA(7,UINTs[4]/*total Eligible Weight*/);
- if( UINTs[1]/*weight of rejections*/ > optionWeights[UINTs[3]/*top option*/] ){
- rejected = true;
- }
- //write results in stone
- if(rejected){
- ticket.ticketRejected = true;
- //emit DATA(8,0);
- }else{
- uint8 dataType = ticket.dataType;
- if(ticket.subjective){
- ticket.numberOfOptions = UINTs[2]/*option count*/;
- for(UINTs[6]=0;UINTs[6]<UINTs[2];UINTs[6]+=1){
- if(dataType == 0){
- ticket.resolvedStrings[UINTs[6]] = stringOptions[UINTs[6]];
- }else if(dataType == 1){
- ticket.resolvedInts[UINTs[6]] = intOptions[UINTs[6]];
- }else if(dataType == 2){
- ticket.resolvedBytes[UINTs[6]] = bytesOptions[UINTs[6]];
- }else if(dataType == 3){
- ticket.resolvedAddresses[UINTs[6]] = addressOptions[UINTs[6]];
- }
- }
- }else{
- //emit DATA(9, UINTs[3]);
- ticket.numberOfOptions = 1;
- if(dataType == 0){
- ticket.resolvedStrings[0] = stringOptions[UINTs[3]/*top option*/];
- }else if(dataType == 1){
- ticket.resolvedInts[0] = intOptions[UINTs[3]/*top option*/];
- }else if(dataType == 2){
- ticket.resolvedBytes[0] = bytesOptions[UINTs[3]/*top option*/];
- }else if(dataType == 3){
- ticket.resolvedAddresses[0] = addressOptions[UINTs[3]/*top option*/];
- }
- }
- }
- //dish out the rewards
- earningsPerShare[ORACLE] += ticket.serviceFee * scaleFactor / totalShares[ORACLE];
- earningsPerWatcher += ticket.txCoverageFee / totalWatchers;
- emit DATA(14, ticket.txCoverageFee);
- emit DATA(15, ticket.serviceFee);
- ticket.finalized = true;
- }else{
- revert();
- }
- }
- }
- event Cashout(address addr, uint ETH);
- function cashout(address[] memory pools) public{
- address payable sender = msg.sender;
- for(uint p; p < pools.length; p+=1){
- update(pools[p], sender);
- }
- uint ETH = earnings[sender];
- earnings[sender] = 0;
- emit Cashout(sender, ETH);
- sender.transfer( ETH );
- }
- function runWatcherPayroll(address watcher) public{
- update(ORACLE, watcher );
- updateWatcherTxEarnings( watcher );
- }
- /*function tryToPunish(uint[] memory tickets, address[] memory watchers) public{
- freezeNoncommits(tickets, watchers);
- freezeUnrevealedCommits(tickets, watchers);
- freezeWrongWatchers(tickets, watchers);
- }*/
- event FreezeNoncommits(uint ticketID, address watcher);
- function freezeNoncommits(uint[] memory tickets, address[] memory watchers) public{
- // get them while they're still at the round table and we're in the reveal phase of a ticket
- RequestTicket storage ticket;
- for(uint i; i<watchers.length; i+=1){
- ticket = requestTickets[ tickets[i] ];
- if( candidatesChair[watchers[i]] < hotSeats &&
- !ticket.committed[ watchers[i] ] &&
- now > ticket.timeRequested + ticket.timeWindow //&&
- //now <= ticket.timeRequested + ticket.timeWindow*2
- ){
- if(punish(tickets[i] , watchers[i]) ){
- emit FreezeNoncommits(tickets[i] , watchers[i]);
- }
- }
- }
- }
- event FreezeUnrevealedCommits(uint ticketID, address watcher);
- function freezeUnrevealedCommits(uint[] memory tickets, address[] memory watchers) public{
- // get them if they made a commit, but did not reveal it after the reveal window is over
- RequestTicket storage ticket;
- for(uint i; i<watchers.length; i+=1){
- ticket = requestTickets[ tickets[i] ];
- if( ticket.committed[ watchers[i] ] &&
- ticket.revealed[ watchers[i] ] &&
- now > requestTickets[ tickets[i] ].timeRequested + ticket.timeWindow*2
- ){
- if(punish(tickets[i] , watchers[i]) ){
- emit FreezeUnrevealedCommits(tickets[i] , watchers[i]);
- }
- }
- }
- }
- event FreezeWrongWatchers(uint ticketID, address watcher);
- function freezeWrongWatchers(uint[] memory tickets, address[] memory watchers) public{
- // get them if the ticket is finalized and their vote doesn't match the resolved answer
- address watcher;
- RequestTicket storage ticket;
- for(uint i; i<watchers.length; i+=1){
- ticket = requestTickets[ tickets[i] ];
- watcher = watchers[i];
- if( ticket.finalized &&
- (!ticket.subjective && (
- (ticket.dataType == 0 && !compareStrings(ticket.resolvedStrings[0], ticket.stringVotes[ watcher ] ))||
- (ticket.dataType == 1 && ticket.resolvedInts[0] != ticket.intVotes[ watcher ] )||
- (ticket.dataType == 2 && compareBytes( keccak256(ticket.resolvedBytes[0]), keccak256(ticket.bytesVotes[ watcher ]) ) )||
- (ticket.dataType == 3 && ticket.resolvedAddresses[0] != ticket.addressVotes[ watcher ] )||
- (!ticket.ticketRejected && ticket.rejected[ watcher ] )//if they reject something the majority didn't reject
- ))||
- (ticket.subjective && ticket.damaged[ watcher ] )//if their subjective contribution is garbage
- ){
- if(punish(tickets[i] , watcher)){
- emit FreezeWrongWatchers(tickets[i] , watcher);
- }
- }
- }
- }
- event Punish(address watcher, uint thatOutTime);
- function punish(uint ticketID, address watcher) internal returns(bool punished){
- if(!requestTickets[ticketID].punished[watcher] && isWatcher(watcher) && timeSeated[watcher] <= requestTickets[ ticketID ].timeRequested ){
- frozen[watcher] = true;
- timeWhenThawedOut[watcher] = now + oracleConfigurations[FREEZE_TIMEOUT];
- removeShares(ORACLE, watcher, totalShares[watcher]);
- emit Punish(watcher, timeWhenThawedOut[watcher]);
- return true;
- }
- return false;
- }
- event Thaw(address candidate, bool seated);
- function thaw(address candidate, bool _assert) public{
- if( now >= timeWhenThawedOut[candidate] ){
- bool seated;
- frozen[candidate] = false;
- if( candidatesChair[candidate] < hotSeats && !paused[candidate]){
- //
- addShares(ORACLE, candidate, totalShares[candidate]);
- seated = true;
- }else if( _assert ){
- seated = assertCandidate(candidate);
- }
- emit Thaw(candidate, seated);
- }else{
- revert();
- }
- }
- event PauseOut(address sender, bool wasWatcher);
- function pauseOut() public{
- address sender = msg.sender;
- bool wasWatcher;
- if(isWatcher(sender)){
- wasWatcher = true;
- removeShares(ORACLE, sender, totalShares[sender]);
- }
- paused[sender] = true;
- emit PauseOut(sender, wasWatcher);
- }
- event Unpause(address sender, bool seated);
- function unpause(bool _assert) public{
- address sender = msg.sender;
- paused[sender] = false;
- bool seated;
- if( candidatesChair[sender] < hotSeats && !frozen[sender]){
- //
- addShares(ORACLE, sender, totalShares[sender]);
- seated = true;
- timeSeated[sender] = now;//this refreshes when they sat down. so they lose responsibility for old tickets.
- }else if( _assert ){
- seated = assertCandidate(sender);
- }
- emit Unpause(sender, seated);
- }
- event UpdateRoundTable(uint newTotalHotSeats);
- function updateRoundTable(uint seats) public{
- // update hotSeats up and down.
- address candidate;
- uint s;
- for( s = 0; s<seats; s+=1){
- if( oracleConfigurations[ROUNDTABLE_SEATS] > hotSeats ){
- candidate = chairsCandidate[hotSeats];
- addShares(ORACLE, candidate, totalShares[candidate]);
- timeSeated[candidate] = now;
- hotSeats += 1;
- }
- if( oracleConfigurations[ROUNDTABLE_SEATS] < hotSeats ){
- candidate = chairsCandidate[hotSeats-1];
- removeShares(ORACLE, candidate, totalShares[candidate]);
- hotSeats -= 1;
- }
- if( oracleConfigurations[ROUNDTABLE_SEATS] == hotSeats ){break;}
- }
- emit UpdateRoundTable(hotSeats);
- }
- function viewRequestTicket(uint ticketID) public view returns(
- address sender,
- string memory query,
- uint timeRequested,
- uint timeWindow,
- bool finalized,
- bool rejected,
- string[] memory resolvedStrings,
- int[] memory resolvedInts,
- bytes[] memory resolvedBytes,
- address[] memory resolvedAddresses,
- uint8 dataType){
- RequestTicket storage T;
- T = requestTickets[ticketID];
- sender = T.sender;
- query = T.query;
- timeRequested = T.timeRequested;
- timeWindow = T.timeWindow;
- finalized = T.finalized;
- rejected = T.ticketRejected;
- resolvedStrings = new string[](T.numberOfOptions);
- resolvedInts = new int[](T.numberOfOptions);
- resolvedBytes = new bytes[](T.numberOfOptions);
- resolvedAddresses = new address[](T.numberOfOptions);
- //yikes
- for(uint i = 0; i< T.numberOfOptions; i+=1){
- resolvedStrings[i] = T.resolvedStrings[i];
- resolvedInts[i] = T.resolvedInts[i];
- resolvedBytes[i] = T.resolvedBytes[i];
- resolvedAddresses[i] = T.resolvedAddresses[i];
- }
- dataType = T.dataType;
- }
- 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){
- uint L;
- if(personal_or_roundtable){
- L = hotSeats;
- }else{
- L = yourBacking[perspective].length;
- }
- dividends = new uint[](L);
- seat = new uint[](L);
- timesWhenThawedOut = new uint[](L);
- timesSeated = new uint[](L);
- isFrozen = new bool[](L);
- isPaused = new bool[](L);
- hasChairs = new bool[](L);
- addresses = new address[](L);
- address candidate;
- for(uint c;c<L;c+=1){
- if(personal_or_roundtable){
- candidate = chairsCandidate[c];
- }else{
- candidate = yourBacking[perspective][c];
- }
- addresses[c] = candidate;
- dividends[c] = shares[candidate][perspective] * (earningsPerShare[candidate] - payouts[candidate][perspective]);
- seat[c] = candidatesChair[candidate];
- isFrozen[c] = frozen[candidate];
- isPaused[c] = paused[candidate];
- hasChairs[c] = hasChair[candidate];
- timesWhenThawedOut[c] = timeWhenThawedOut[candidate];
- timesSeated[c] = timeSeated[candidate];
- }
- }
- function compareStrings(string memory a, string memory b) public pure returns (bool) {
- return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
- }
- function compareBytes(bytes32 a, bytes32 b) public pure returns (bool) {
- return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
- }
- function bytesToAddress(bytes memory bys) private pure returns (address addr){
- assembly {
- addr := mload(add(bys,20))
- }
- }
- function accountData(address account) public view returns(
- uint _resolveWeight,
- uint _weightLocked,
- uint _candidatesChair,
- uint _timeSeated,
- bool _frozen,
- uint _timeWhenThawedOut,
- bool _paused,
- bool _hasChair,
- uint _earnings,
- uint _totalShares,
- uint _txCoverageFeeEarnings
- ){
- _resolveWeight = resolveWeight[account];
- _weightLocked = weightLocked[account];
- _candidatesChair = candidatesChair[account];
- _timeSeated = timeSeated[account];
- _frozen = frozen[account];
- _timeWhenThawedOut = timeWhenThawedOut[account];
- _paused = paused[account];
- _hasChair = hasChair[account];
- _earnings = earnings[account];
- _totalShares = totalShares[account];
- uint txCoverageFeeEarnings;
- if( isWatcher(account) ){
- txCoverageFeeEarnings = earningsPerWatcher - watcherPayouts[account];
- }
- _txCoverageFeeEarnings = txCoverageFeeEarnings;
- }
- }
- abstract contract ResolveToken{
- function transfer(address _to, uint256 _value) public virtual returns (bool);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement