1pragma solidity >=0.0; 2import "../Oracles/Oracle.sol"; 3 4 5/// @title Majority oracle contract - Allows to resolve an event based on multiple oracles with majority vote 6/// @author Stefan George - <stefan@gnosis.pm> 7contract MajorityOracle is Oracle { 8 9 /* 10 * Storage 11 */ 12 Oracle[] public oracles; 13 14 /* 15 * Public functions 16 */ 17 /// @dev Allows to create an oracle for a majority vote based on other oracles 18 /// @param _oracles List of oracles taking part in the majority vote 19 constructor(Oracle[] memory _oracles) 20 { 21 // At least 2 oracles should be defined 22 require(_oracles.length > 2); 23 for (uint i = 0; i < _oracles.length; i++) 24 // Oracle address cannot be null 25 require(address(_oracles[i]) != address(0)); 26 oracles = _oracles; 27 } 28 29 /// @dev Allows to registers oracles for a majority vote 30 /// @return outcomeSet Is outcome set? 31 /// @return outcome Outcome 32 function getStatusAndOutcome() 33 public 34 view 35 returns (bool outcomeSet, int outcome) 36 { 37 uint i; 38 int[] memory outcomes = new int[](oracles.length); 39 uint[] memory validations = new uint[](oracles.length); 40 for (i = 0; i < oracles.length; i++) 41 if (oracles[i].isOutcomeSet()) { 42 int _outcome = oracles[i].getOutcome(); 43 for (uint j = 0; j <= i; j++) 44 if (_outcome == outcomes[j]) { 45 validations[j] += 1; 46 break; 47 } 48 else if (validations[j] == 0) { 49 outcomes[j] = _outcome; 50 validations[j] = 1; 51 break; 52 } 53 } 54 uint outcomeValidations = 0; 55 uint outcomeIndex = 0; 56 for (i = 0; i < oracles.length; i++) 57 if (validations[i] > outcomeValidations) { 58 outcomeValidations = validations[i]; 59 outcomeIndex = i; 60 } 61 // There is a majority vote 62 if (outcomeValidations * 2 > oracles.length) { 63 outcomeSet = true; 64 outcome = outcomes[outcomeIndex]; 65 } 66 } 67 68 /// @dev Returns if winning outcome is set 69 /// @return Is outcome set? 70 function isOutcomeSet() 71 public 72 override 73 view 74 returns (bool) 75 { 76 (bool outcomeSet, ) = getStatusAndOutcome(); 77 return outcomeSet; 78 } 79 80 /// @dev Returns winning outcome 81 /// @return Outcome 82 function getOutcome() 83 public 84 override 85 view 86 returns (int) 87 { 88 (, int winningOutcome) = getStatusAndOutcome(); 89 return winningOutcome; 90 } 91} 92