The Voting with delegation example from the Solidity documentation, opened over three proposals named A, B and C.
Context
Deployed 15 December 2015, during the Frontier era.
Key Facts
Description
The Ballot contract from the Voting with delegation example in the Solidity documentation. The constructor takes the proposal names, makes the deployer chairperson and gives that address one unit of voting weight. giveRightToVote, which throws unless the caller is the chairperson and the target has not already voted, sets an address to weight one. delegate hands a voter's weight to another address, following any chain of delegations already in place and throwing if the chain leads back to the caller; if the final delegate has already voted the weight is added straight to the proposal they chose, otherwise it is added to their own weight. vote adds the caller's weight to a proposal and throws if the index is out of range. winningProposal walks the proposals and returns the index with the highest count, without breaking a tie. This deployment was created with the proposal names A, B and C.
Source Verified
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Verification ProofShow source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
/// @title Voting with delegation.
contract Ballot {
// This declares a new complex type which will
// be used for variables later.
// It will represent a single voter.
struct Voter {
uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
// This is a type for a single proposal.
struct Proposal
{
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
// This declares a state variable that
// stores a `Voter` struct for each possible address.
mapping(address => Voter) public voters;
// A dynamically-sized array of `Proposal` structs.
Proposal[] public proposals;
/// Create a new ballot to choose one of `proposalNames`.
function Ballot(bytes32[] proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// For each of the provided proposal names,
// create a new proposal object and add it
// to the end of the array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary
// Proposal object and `proposals.push(...)`
// appends it to the end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
function giveRightToVote(address voter) {
if (msg.sender != chairperson || voters[voter].voted) {
// `throw` terminates and reverts all changes to
// the state and to Ether balances. It is often
// a good idea to use this if functions are
// called incorrectly. But watch out, this
// will also consume all provided gas.
throw;
}
voters[voter].weight = 1;
}
/// Delegate your vote to the voter `to`.
function delegate(address to) {
// assigns reference
Voter sender = voters[msg.sender];
if (sender.voted)
throw;
// Forward the delegation as long as
// `to` also delegated.
// In general, such loops are very dangerous,
// because if they run too long, they might
// need more gas than is available in a block.
// In this case, the delegation will not be executed,
// but in other situations, such loops might
// cause a contract to get "stuck" completely.
while (
voters[to].delegate != address(0) &&
voters[to].delegate != msg.sender
) {
to = voters[to].delegate;
}
// We found a loop in the delegation, not allowed.
if (to == msg.sender) {
throw;
}
// Since `sender` is a reference, this
// modifies `voters[msg.sender].voted`
sender.voted = true;
sender.delegate = to;
Voter delegate = voters[to];
if (delegate.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate.vote].voteCount += sender.weight;
}
else {
// If the delegate did not vote yet,
// add to her weight.
delegate.weight += sender.weight;
}
}
/// Give your vote (including votes delegated to you)
/// to proposal `proposals[proposal].name`.
function vote(uint proposal) {
Voter sender = voters[msg.sender];
if (sender.voted)
throw;
sender.voted = true;
sender.vote = proposal;
// If `proposal` is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/// @dev Computes the winning proposal taking all
/// previous votes into account.
function winningProposal() constant
returns (uint winningProposal)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal = p;
}
}
}
}External Links
Related contracts
EFSubMultisig
Same eraA 2-of-3 motion register deployed by the Ethereum Foundation's EF 1 wallet on August 12, 2015, thirteen days after Frontier. Three hardcoded developer keys co-sign to emit an on-chain event. Holds no ETH and makes no external calls. Serpent source recovered by exact bytecode match.
0x209711...b23d25August 12, 2015Ethereum Multisig Wallet (EF Signer)
Same eraA personal multisig wallet deployed 20 days after Ethereum's Frontier launch by a confirmed Ethereum Foundation multisig signer. Based on Gav Wood's Wallet.sol.
0xfe8ad7...783715August 20, 2015Democracy DAO
Same eraOn-chain governance contract with proposals, voting, and execution. Stripped-down version of the go-ethereum wiki Democracy DAO tutorial.
0xb5b8a0...9cfec6September 24, 2015ProtoDAO_0x7931c901_Sep24
Same eraSep 24, 2015 proto-DAO experiment — eight months before TheDAO. One of 10 byte-identical sister contracts deployed by 0x7931c901 in a 40-minute burst.
0x8d0c13...ff4f34September 24, 2015ProtoDAO_0x7931c901_Sep24
Same eraSep 24, 2015 proto-DAO experiment — eight months before TheDAO. One of 10 byte-identical sister contracts deployed by 0x7931c901 in a 40-minute burst.
0x8ecd7a...605874September 24, 2015ProtoDAO_0x7931c901_Sep24
Same eraSep 24, 2015 proto-DAO experiment — eight months before TheDAO. One of 10 byte-identical sister contracts deployed by 0x7931c901 in a 40-minute burst.
0xba2423...0516e0September 24, 2015