Last active
May 20, 2018 10:23
-
-
Save tarassh/1c57b6a5af5a217bbf679f6d54484e41 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.23; | |
contract RandomVote { | |
event ParticipantIndex(address indexed participant, uint indexed index, uint indexed stepsToNextRound); | |
event ParticipantNumber(address indexed participants, uint indexed number, uint indexed stepsToChoosingTheWinner); | |
event TheWinner(address indexed participant, uint indexed number); | |
address public winner; | |
uint public numberOfParticipants = 0; | |
uint public digestIndex = 0; | |
uint public numberIndex = 0; | |
mapping(address => bytes32) public digests; | |
mapping(address => uint) public numbers; | |
mapping(uint => address) public indexes; | |
bool public generationEnded = false; | |
uint public seed; | |
constructor(uint number) public { | |
require(number > 0); | |
numberOfParticipants = number; | |
} | |
modifier isRound1 { | |
require(digestIndex >= 0 && digestIndex < numberOfParticipants); | |
_; | |
} | |
modifier isRound2 { | |
require(digestIndex == numberOfParticipants && numberIndex < numberOfParticipants); | |
_; | |
} | |
function setDigest(string digestStr) public isRound1 { | |
require(digests[msg.sender] == 0x0); | |
bytes32 digest = fromHex(digestStr); | |
digests[msg.sender] = digest; | |
indexes[digestIndex] = msg.sender; | |
emit ParticipantIndex(msg.sender, digestIndex++, numberOfParticipants - digestIndex); | |
} | |
function setNumber(string numberStr) public isRound2 { | |
bytes memory temp = bytes(numberStr); | |
bytes32 digest = sha256(temp); | |
require(digests[msg.sender] == digest); | |
require(numbers[msg.sender] == 0); | |
uint number = parseInt(numberStr, temp.length); | |
numbers[msg.sender] = number; | |
seed += number; | |
emit ParticipantNumber(msg.sender, number, numberOfParticipants - (++numberIndex)); | |
if (numberIndex == numberOfParticipants) { | |
calculateRandom(); | |
} | |
} | |
function calculateRandom() internal { | |
uint256 random = seed % numberOfParticipants; | |
winner = indexes[random]; | |
generationEnded = true; | |
emit TheWinner(winner, random); | |
} | |
// Convert an hexadecimal character to their value | |
function fromHexChar(uint c) public pure returns (uint) { | |
if (byte(c) >= byte('0') && byte(c) <= byte('9')) { | |
return c - uint(byte('0')); | |
} | |
if (byte(c) >= byte('a') && byte(c) <= byte('f')) { | |
return 10 + c - uint(byte('a')); | |
} | |
if (byte(c) >= byte('A') && byte(c) <= byte('F')) { | |
return 10 + c - uint(byte('A')); | |
} | |
} | |
// Convert an hexadecimal string to raw bytes | |
function fromHex(string s) public pure returns (bytes32) { | |
require(bytes(s).length == 64); | |
bytes memory ss = bytes(s); | |
require(ss.length%2 == 0); // length must be even | |
bytes32 r; | |
for (uint i=0; i<32; ++i) { | |
bytes32 oneByte = byte(fromHexChar(uint(ss[2*i])) * 16 + | |
fromHexChar(uint(ss[2*i+1]))); | |
r |= oneByte >> 8 * i; | |
} | |
return r; | |
} | |
function parseInt(string _a, uint _b) internal pure returns (uint) { | |
bytes memory bresult = bytes(_a); | |
uint mint = 0; | |
bool decimals = false; | |
for (uint i = 0; i < bresult.length; i++) { | |
if ((bresult[i] >= 48) && (bresult[i] <= 57)) { | |
if (decimals) { | |
if (_b == 0) break; | |
else _b--; | |
} | |
mint *= 10; | |
mint += uint(bresult[i]) - 48; | |
} else if (bresult[i] == 46) decimals = true; | |
} | |
return mint; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment