One of the Congress DAOs Alex Van de Sande deployed on 11 February 2016, the version that sells unicorns.
Historical Significance
The source is that verified file with transferOwnership declared inside Congress instead of inherited, and with the functions in a different order. Neither is a matter of taste. Solidity emits an inherited function ahead of the deriving contract's own, and this deployment writes the owner slot 4544 bytes in, well after code that an inherited function would have preceded. Declaration order steers the 2015 and 2016 optimizer's block layout, so the order is a reading of the deployed bytecode rather than a guess. Compiled with v0.2.0-nightly.2016.1.13+commit.d2f18c73 with the optimizer on, it reproduces all 7189 bytes of the deployment transaction exactly.
Context
Deployed on 11 February 2016, one of a run of Congress and token contracts this account put on chain that day while the DAO tutorial was being reworked. Another Congress went out from the same account the same day, at 0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359, and was verified on Etherscan at the time. It is the same contract with its functions written in a different order.
Key Facts
Description
Congress is the voting organisation from the ethereum.org DAO tutorial, in the form it reached by February 2016. Members carry a numeric vote weight rather than a yes or no right to vote, and a separate flag for whether they may open proposals. Proposals come in two flavours, one denominated in wei and one in ether, and each names a recipient, an amount and a payload to run. Votes are weighted by the member's weight, and once the debating period has run out executeProposal checks the quorum and the margin before sending the ether and running the payload. The contract also has a fallback function that sells unicorns: ether sent to it above the unicorn price mints unicorn tokens back to the sender through a separate token contract. It was deployed with every constructor parameter set to zero.
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)
contract owned {
address public owner;
function owned() {
owner = msg.sender;
}
modifier onlyOwner {
if (msg.sender != owner) throw;
_
}
}
/* The token is used as a voting shares */
contract token {
function mintToken(address target, uint256 mintedAmount);
}
contract Congress is owned {
/* Contract Variables and events */
uint public minimumQuorum;
uint public debatingPeriodInMinutes;
int public majorityMargin;
Proposal[] public proposals;
uint public numProposals;
mapping(address => uint) public memberId;
Member[] public members;
address public unicornAddress;
uint public priceOfAUnicornInFinney;
event ProposalAdded(uint proposalID, address recipient, uint amount, string description);
event Voted(uint proposalID, bool position, address voter, string justification);
event ProposalTallied(uint proposalID, int result, uint quorum, bool active);
event MembershipChanged(address member);
event ChangeOfRules(uint minimumQuorum, uint debatingPeriodInMinutes, int majorityMargin);
struct Proposal {
address recipient;
uint amount;
string description;
uint votingDeadline;
bool executed;
bool proposalPassed;
uint numberOfVotes;
int currentResult;
bytes32 proposalHash;
Vote[] votes;
mapping(address => bool) voted;
}
struct Member {
address member;
uint voteWeight;
bool canAddProposals;
string name;
uint memberSince;
}
struct Vote {
bool inSupport;
address voter;
string justification;
}
/* First time setup */
function Congress(uint minimumQuorumForProposals, uint minutesForDebate, int marginOfVotesForMajority, address congressLeader) {
minimumQuorum = minimumQuorumForProposals;
debatingPeriodInMinutes = minutesForDebate;
majorityMargin = marginOfVotesForMajority;
members.length++;
members[0] = Member({
member: 0,
voteWeight: 0,
canAddProposals: false,
memberSince: now,
name: ''
});
if (congressLeader != 0) owner = congressLeader;
}
/*change rules*/
function changeVotingRules(uint minimumQuorumForProposals, uint minutesForDebate, int marginOfVotesForMajority) onlyOwner {
minimumQuorum = minimumQuorumForProposals;
debatingPeriodInMinutes = minutesForDebate;
majorityMargin = marginOfVotesForMajority;
ChangeOfRules(minimumQuorum, debatingPeriodInMinutes, majorityMargin);
}
// ribbonPriceInEther
function changeUnicorn(uint newUnicornPriceInFinney, address newUnicornAddress) onlyOwner {
unicornAddress = newUnicornAddress;
priceOfAUnicornInFinney = newUnicornPriceInFinney;
}
/* Function to create a new proposal */
function newProposalInWei(address beneficiary, uint weiAmount, string JobDescription, bytes transactionBytecode) returns(uint proposalID) {
if (memberId[msg.sender] == 0 || !members[memberId[msg.sender]].canAddProposals) throw;
proposalID = proposals.length++;
Proposal p = proposals[proposalID];
p.recipient = beneficiary;
p.amount = weiAmount;
p.description = JobDescription;
p.proposalHash = sha3(beneficiary, weiAmount, transactionBytecode);
p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes;
p.executed = false;
p.proposalPassed = false;
p.numberOfVotes = 0;
ProposalAdded(proposalID, beneficiary, weiAmount, JobDescription);
numProposals = proposalID + 1;
}
/*make member*/
function changeMembership(address targetMember, uint voteWeight, bool canAddProposals, string memberName) onlyOwner {
uint id;
if (memberId[targetMember] == 0) {
memberId[targetMember] = members.length;
id = members.length++;
members[id] = Member({
member: targetMember,
voteWeight: voteWeight,
canAddProposals: canAddProposals,
memberSince: now,
name: memberName
});
} else {
id = memberId[targetMember];
Member m = members[id];
m.voteWeight = voteWeight;
m.canAddProposals = canAddProposals;
m.name = memberName;
}
MembershipChanged(targetMember);
}
function() {
if (msg.value > priceOfAUnicornInFinney) {
token unicorn = token(unicornAddress);
unicorn.mintToken(msg.sender, msg.value / (priceOfAUnicornInFinney * 1 finney));
}
}
function transferOwnership(address newOwner) onlyOwner {
owner = newOwner;
}
/* Function to create a new proposal */
function newProposalInEther(address beneficiary, uint etherAmount, string JobDescription, bytes transactionBytecode) returns(uint proposalID) {
if (memberId[msg.sender] == 0 || !members[memberId[msg.sender]].canAddProposals) throw;
proposalID = proposals.length++;
Proposal p = proposals[proposalID];
p.recipient = beneficiary;
p.amount = etherAmount * 1 ether;
p.description = JobDescription;
p.proposalHash = sha3(beneficiary, etherAmount * 1 ether, transactionBytecode);
p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes;
p.executed = false;
p.proposalPassed = false;
p.numberOfVotes = 0;
ProposalAdded(proposalID, beneficiary, etherAmount, JobDescription);
numProposals = proposalID + 1;
}
/* function to check if a proposal code matches */
function checkProposalCode(uint proposalNumber, address beneficiary, uint amount, bytes transactionBytecode) constant returns(bool codeChecksOut) {
Proposal p = proposals[proposalNumber];
return p.proposalHash == sha3(beneficiary, amount, transactionBytecode);
}
function vote(uint proposalNumber, bool supportsProposal, string justificationText) returns(uint voteID) {
if (memberId[msg.sender] == 0) throw;
uint voteWeight = members[memberId[msg.sender]].voteWeight;
Proposal p = proposals[proposalNumber]; // Get the proposal
if (p.voted[msg.sender] == true) throw; // If has already voted, cancel
p.voted[msg.sender] = true; // Set this voter as having voted
p.numberOfVotes += voteWeight; // Increase the number of votes
if (supportsProposal) { // If they support the proposal
p.currentResult += int(voteWeight); // Increase score
} else { // If they don't
p.currentResult -= int(voteWeight); // Decrease the score
}
// Create a log of this event
Voted(proposalNumber, supportsProposal, msg.sender, justificationText);
}
function executeProposal(uint proposalNumber, bytes transactionBytecode) returns(int result) {
Proposal p = proposals[proposalNumber];
/* Check if the proposal can be executed */
if (now < p.votingDeadline // has the voting deadline arrived?
|| p.executed // has it been already executed?
|| p.proposalHash != sha3(p.recipient, p.amount, transactionBytecode) // Does the transaction code match the proposal?
|| p.numberOfVotes < minimumQuorum) // has minimum quorum?
throw;
/* execute result */
if (p.currentResult > majorityMargin) {
/* If difference between support and opposition is larger than margin */
p.recipient.call.value(p.amount)(transactionBytecode);
p.executed = true;
p.proposalPassed = true;
} else {
p.executed = true;
p.proposalPassed = false;
}
// Fire Events
ProposalTallied(proposalNumber, p.currentResult, p.numberOfVotes, p.proposalPassed);
}
}External Links
Related contracts
Association (Mist D.A.O.)
Same deployerA token-weighted governance contract deployed by Avsa on Dec 3, 2015, using MistCoin as voting shares. 0.1 ETH remains locked after 10 years.
0x8d554c...d9b8dcDecember 3, 2015Congress
Same deployerAlex Van de Sande's Congress DAO from Dec 28, 2015: on-chain voting with member registry (mapping) and configurable quorum.
0xb3d47f...7c6c0cDecember 28, 2015Congress
Same deployerAlex Van de Sande's Congress DAO from Dec 28, 2015: on-chain voting system for proposals with configurable quorum and majority threshold.
0x7f6b46...03f101December 28, 2015Congress
Same deployerAlex Van de Sande's Congress DAO from Dec 28, 2015: on-chain voting system for proposals with configurable quorum and majority threshold.
0x1e5cbb...b7ff63December 28, 2015Congress
Same deployerA Congress DAO from the ethereum.org tutorial, deployed 28 December 2015, 23 minutes before the tutorial revision it came from was published.
0xe8e80d...4ed2daDecember 28, 2015Doge-ETH Bounty DAO
Same deployerThe Doge-Ethereum Bounty DAO created by avsa on Dec 28, 2015. Funded over 5,400 ETH in bridge development, holds 50,000 MistCoin. Active 2015-2021.
0xdbf03b...c8c6fbDecember 28, 2015