The 2015 ethereum.org democracy tutorial under its original name: token holders propose payments, vote a position, and the contract pays out if the vote passes.
Historical Significance
The earlier name and the earlier shape of the tutorial that later became Association, and the one that was current while The DAO was being designed. Votes are cast as a signed position rather than a boolean, weighting happens at tally time, and the founder is recorded but given no special power, which makes it a clean statement of the idea: shareholders vote, and the treasury pays out when they agree.
Context
Ethereum's Frontier network went live on 30 July 2015 and the ethereum.org tutorials followed within weeks. The democracy page was the third of them, after the token and the crowdsale, and the contract it taught was renamed and rewritten several times over the following year.
Key Facts
Description
The democracy contract from the 2015 ethereum.org tutorial, in the revision that still called itself Democracy. Membership is holding a balance in a separate token: the contract stores that token's address, the account that deployed it as founder, a minimum quorum and a debating period fixed at construction.
Any holder may open a proposal naming a recipient, an amount, a word of data and a text description. Holders then vote by sending a position of minus one, zero or one, weighted later by their token balance, and each address may vote once per proposal. When the debating period has passed the proposal is tallied and, if the vote carries and the quorum is met, the contract sends the proposed amount to the recipient.
The proposal stores a single word of data rather than a hash of the transaction to be sent, so what a vote commits to is narrower than in the revisions that followed.
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
This contract has verified source code on Etherscan.
Show source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
contract token {
mapping (address => uint) public coinBalanceOf;
event CoinTransfer(address sender, address receiver, uint amount);
/* Initializes contract with initial supply tokens to the creator of the contract */
function token(uint supply) {
coinBalanceOf[msg.sender] = (supply || 10000);
}
/* Very simple trade function */
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (coinBalanceOf[msg.sender] < amount) return false;
coinBalanceOf[msg.sender] -= amount;
coinBalanceOf[receiver] += amount;
CoinTransfer(msg.sender, receiver, amount);
return true;
}
}
contract Democracy {
uint public minimumQuorum;
uint public debatingPeriod;
token public voterShare;
address public founder;
Proposal[] public proposals;
uint public numProposals;
event ProposalAdded(uint proposalID, address recipient, uint amount, bytes32 data, string description);
event Voted(uint proposalID, int position, address voter);
event ProposalTallied(uint proposalID, int result, uint quorum, bool active);
struct Proposal {
address recipient;
uint amount;
bytes32 data;
string description;
uint creationDate;
bool active;
Vote[] votes;
mapping (address => bool) voted;
}
struct Vote {
int position;
address voter;
}
function Democracy(token _voterShareAddress, uint _minimumQuorum, uint _debatingPeriod) {
founder = msg.sender;
voterShare = token(_voterShareAddress);
minimumQuorum = _minimumQuorum;
debatingPeriod = _debatingPeriod * 1 seconds;
}
function newProposal(address _recipient, uint _amount, bytes32 _data, string _description) returns (uint proposalID) {
if (voterShare.coinBalanceOf(msg.sender)>0) {
proposalID = proposals.length++;
Proposal p = proposals[proposalID];
p.recipient = _recipient;
p.amount = _amount;
p.data = _data;
p.description = _description;
p.creationDate = now;
p.active = true;
ProposalAdded(proposalID, _recipient, _amount, _data, _description);
numProposals = proposalID+1;
}
}
function vote(uint _proposalID, int _position) returns (uint voteID){
if (voterShare.coinBalanceOf(msg.sender)>0 && (_position >= -1 || _position <= 1 )) {
Proposal p = proposals[_proposalID];
if (p.voted[msg.sender] == true) return;
voteID = p.votes.length++;
p.votes[voteID] = Vote({position: _position, voter: msg.sender});
p.voted[msg.sender] = true;
Voted(_proposalID, _position, msg.sender);
}
}
function executeProposal(uint _proposalID) returns (int result) {
Proposal p = proposals[_proposalID];
/* Check if debating period is over */
if (now > (p.creationDate + debatingPeriod) && p.active){
uint quorum = 0;
/* tally the votes */
for (uint i = 0; i < p.votes.length; ++i) {
Vote v = p.votes[i];
uint voteWeight = voterShare.coinBalanceOf(v.voter);
quorum += voteWeight;
result += int(voteWeight) * v.position;
}
/* execute result */
if (quorum > minimumQuorum && result > 0 ) {
p.recipient.call.value(p.amount)(p.data);
p.active = false;
} else if (quorum > minimumQuorum && result < 0) {
p.active = false;
}
ProposalTallied(_proposalID, result, quorum, p.active);
}
}
}
External Links
Related contracts
test
Same deployerThe multiply contract that opens the go-ethereum Contract Tutorial, deployed with the author's own multiplier of 70 in place of 7.
0xdb685d...d68e91August 28, 2015Contract 0x051fdd...9f0723
Same deployerThe go-ethereum Contract Tutorial greeter, deployed with no constructor argument, so its greeting was left empty.
0x051fdd...9f0723August 29, 2015Contract 0x5272fe...b5804a
Same deployerThe go-ethereum Contract Tutorial greeter, deployed with no constructor argument, so its greeting was left empty.
0x5272fe...b5804aAugust 29, 2015Contract 0x13acd0...71885f
Same deployerThe go-ethereum Contract Tutorial greeter, deployed with no constructor argument, so its greeting was left empty.
0x13acd0...71885fAugust 29, 2015Contract 0x4d8ab2...ddcd63
Same deployerThe go-ethereum Contract Tutorial greeter, deployed with no constructor argument, so its greeting was left empty.
0x4d8ab2...ddcd63August 29, 2015Contract 0xd24d32...62b21c
Same deployerThe go-ethereum Contract Tutorial greeter, deployed with no constructor argument, so its greeting was left empty.
0xd24d32...62b21cAugust 29, 2015