Commit b0e0831a authored by Robert Martin-Legene's avatar Robert Martin-Legene

El contrato con 2 contratos

parent a9211029
// Basado en https://soliditycookbook.com/voting
// vim:syntax:filetype=javascript:ai:sm
// vim:expandtab:backspace=indent,eol,start:softtabstop=4
pragma solidity >= 0.5.2;
/// @title A single ballot contract which allows certain
/// @title accounts to vote (one single vote).
/// @author soliditycookbook.com & Robert Martin-Legene
/// @notice A Chairman will deploy the contract, setting up initial
/// @notice conditions. Before the voting period starts the Chairman
/// @notice must also tell the contract who is allowed to vote.
contract Ballot
{
/// @dev This is a struct for a single voter.
/// @dev Voter.vote is the index of the voted proposal or -1 if
/// @dev the account has not voted yet.
struct Voter
{
address voter;
uint[] votedProposals;
uint votesLeft;
}
string public ballotTitle;
address payable public ballotChairman;
uint public ballotVoteStarts;
uint public ballotVoteBefore;
uint public ballotPercentOfRegisteredVotersReqToBeValid;
uint public ballotPercentOfVotesCastToWin;
/// @dev Counting registered voters who do not vote as blank
/// @dev votes, has the effect that it is more difficult
/// @dev to acquire the desired votes.
bool public ballotCountNonvotesAsBlanks;
uint public ballotMaxVotesPerVoter;
uint public ballotMaxVotesPerProposal;
/// @dev The votermap points to the index(number) that the struct of the
/// @dev account can be found.
mapping( address => uint )
public voterMap;
Voter[] public voterList;
/// @dev Short name (up to 32 bytes)
bytes32[] public proposalList;
uint[] private emptyuintlist;
/// @notice When the SC is being deployed, you must define initial conditions. When specifying percentages they are to have been multiplied with 100 million (5% is written as 5 million, since 5% is actially 0.05).
/// @param title Name of the things being voted for.
/// @param voteStarts Time in seconds (since Unix Epoch) when the voting starts (note that voters must be defined before voting starts).
/// @param voteBefore Time in seconds (since Unix Epoch) at/after which it is too late to vote. After this point, the Ballot is effectively readonly.
/// @param percentOfRegisteredVotersReqToBeValid How many of the registered voters must vote before the result of the Ballot can be considered valid. E.g. if 50% is set and only 40% votes, then the result of the Ballot can not be used.
/// @param percentOfVotesCastToWin How many of the votes that are cast are required to win. This is often 50.000001% ("more than half"), 67.777778% ("two thirds") or 0% (proposal with most votes - e.g. voting for most popular fruit).
/// @param countNonvotesAsBlanks Whether or not to count voters whom did not vote, as having voted blank.
/// @param maxVotesPerVoter How many votes can a voter cast. Often this is 1 (one).
/// @param maxVotesPerProposal How many votes one voter can cast on each proposal. I.e. can (s)he vote use all his votes on one proposal?
/// @param proposalNames 32 char "strings" listing all the options available to vote for.
constructor(
string memory title,
uint voteStarts,
uint voteBefore,
uint percentOfRegisteredVotersReqToBeValid,
uint percentOfVotesCastToWin,
bool countNonvotesAsBlanks,
uint maxVotesPerVoter,
uint maxVotesPerProposal,
bytes32[] memory proposalNames
)
public
{
require( voteBefore > now );
require( percentOfRegisteredVotersReqToBeValid <= 100000000 );
require( percentOfVotesCastToWin <= 100000000 );
// chairman can not automatically vote.
// Chairman must giveRightToVote to himself if
// he wants to vote.
ballotChairman = tx.origin;
ballotTitle = title;
ballotVoteStarts = voteStarts;
ballotVoteBefore = voteBefore;
ballotPercentOfRegisteredVotersReqToBeValid = percentOfRegisteredVotersReqToBeValid;
ballotPercentOfVotesCastToWin = percentOfVotesCastToWin;
ballotCountNonvotesAsBlanks = countNonvotesAsBlanks;
ballotMaxVotesPerVoter = maxVotesPerVoter;
ballotMaxVotesPerProposal = maxVotesPerProposal;
/// @dev For each of the provided proposal names,
/// @dev add it to the end of the proposalList
uint incoming = proposalNames.length;
uint i = 0;
while ( i < incoming )
{
proposalList.push( proposalNames[i] );
i++;
}
}
/// @notice Give 'voters' the right to vote on this ballot.
/// @param voters The list of voters to add to the list of allowed voters.
function giveRightToVote( address[] memory voters )
public
{
// May only be called by chairman.
require( msg.sender == ballotChairman );
require( ballotVoteBefore < now );
uint len = voters.length;
uint i = 0;
while ( i < len )
{
address voter = voters[i];
uint idx = voterMap[voter];
/// @dev Can't add any voters more than once.
require( idx == 0 );
/// @dev Not even the voter listed in [0] can vote more than once.
if ( voterList.length > 0 )
require( voterList[0].voter != voter );
/// @dev If the voter's address doesn't match, it is because
/// @dev he doesn't exist (and then we always have idx=0).
/// @dev So we push him onto the voterList.
idx = voterList.push(
Voter(
{
voter: voter,
votedProposals: emptyuintlist,
votesLeft: ballotMaxVotesPerVoter
}
)
) - 1;
voterMap[voter] = idx;
i++;
}
}
function getVoterIdx( address voter )
public
view
returns( int )
{
uint idx = voterMap[voter];
if ( idx > 0 )
return int(idx);
if ( voterList[0].voter == voter )
return 0;
return -1;
}
function vote( uint proposal )
public
{
require( proposal < proposalList.length );
require( ballotVoteStarts >= now );
require( ballotVoteBefore < now );
int idx = getVoterIdx( msg.sender );
require( idx > -1 );
uint uidx = uint( idx );
require( voterList[uidx].votesLeft > 0 );
uint proposalCounter = 0;
uint i = voterList[uidx].votedProposals.length;
while ( i > 0 )
{
i--;
if ( voterList[uidx].votedProposals[i] == proposal )
proposalCounter++;
}
require( proposalCounter < ballotMaxVotesPerProposal );
voterList[uidx].votesLeft--;
voterList[uidx].votedProposals.push( proposal );
}
function uncreate()
public
{
if ( msg.sender != ballotChairman )
return;
if ( ballotVoteStarts <= now )
return;
selfdestruct( ballotChairman );
}
}
contract NewBallot
{
function newBallot(
string memory title,
uint voteStarts,
uint voteBefore,
uint percentOfRegisteredVotersReqToBeValid,
uint percentOfVotesCastToWin,
bool countNonvotesAsBlanks,
uint maxVotesPerVoter,
uint maxVotesPerProposal,
bytes32[] memory proposalNames
)
public
returns (Ballot newaddr)
{
// Create a new ballot contract. Returns the new contract's address.
// tx.origin will be ballotChairman ("owner") of that contract.
return new Ballot(
title,
voteStarts,
voteBefore,
percentOfRegisteredVotersReqToBeValid,
percentOfVotesCastToWin,
countNonvotesAsBlanks,
maxVotesPerVoter,
maxVotesPerProposal,
proposalNames
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment