Skip to content

Instantly share code, notes, and snippets.

@alexvandesande
Created June 4, 2016 21:02
Show Gist options
  • Select an option

  • Save alexvandesande/cce8cea7dea4be47e373c4003582d56c to your computer and use it in GitHub Desktop.

Select an option

Save alexvandesande/cce8cea7dea4be47e373c4003582d56c to your computer and use it in GitHub Desktop.
Proposal Framework
/*
This file is part of the DAO.
The DAO is free software: you can redistribute it and/or modify
it under the terms of the GNU lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The DAO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU lesser General Public License for more details.
You should have received a copy of the GNU lesser General Public License
along with the DAO. If not, see <http://www.gnu.org/licenses/>.
*/
/*
An Offer from a Contractor to the DAO without any reward going back to
the DAO.
Feel free to use as a template for your own proposal.
Actors:
- Offerer: the entity that creates the Offer. Usually it is the initial
Contractor.
- Contractor: the entity that has rights to withdraw ether to perform
its project.
- Client: the DAO that gives ether to the Contractor. It signs off
the Offer, can adjust daily withdraw limit or even fire the
Contractor.
*/
contract DAO {
Proposal[] public proposals;
struct Proposal {
address recipient;
uint amount;
// string description;
uint votingDeadline;
bool open;
bool proposalPassed;
bytes32 proposalHash;
uint proposalDeposit;
bool newCurator;
//SplitData[] splitData;
uint yea;
uint nay;
// mapping (address => bool) votedYes;
// mapping (address => bool) votedNo;
address creator;
}
uint public minQuorumDivisor;
uint public totalSupply;
}
contract priceOracle {
function convertPrice(uint units) returns (uint amountOfWei) {
return units * 1 ether;
}
}
contract DAOProposal {
// Period of time after which money can be withdrawn from this contract
uint constant payoutFreezePeriod = 3 weeks;
// The address of the Contractor.
DAO client = DAO(0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413); // address of DAO
DAO originalClient = client; // address of DAO who signed the contract
address public contractor;
address public milestoneOracle;
address public curators = 0xDa4a4626d3E16e094De3225A751aAb7128e96526;
// The hash of the Proposal/Offer document.
bytes32 public hashOfTheProposalDocument;
uint public dateOfSignature;
uint initialPayment;
uint totalPayments;
uint proposalId;
bool wasApprovedBeforeDeadline;
// creates contract states and milestones
enum State { preVote, Voting, Approved, Active, Void }
State public state;
struct Milestones {
uint value;
uint validAfter;
bool completed;
bool paid;
}
Milestones[] public milestones;
uint public totalMilestones;
// Some functions can only called by The DAO
modifier onlyClient {
if (msg.sender != address(client))
throw;
_
}
// Some functions can only called by The DAO
modifier onlyContractor {
if (msg.sender != address(contractor))
throw;
_
}
// Some functions can only called by The DAO
modifier onlyOracle {
if (msg.sender != address(milestoneOracle))
throw;
_
}
// Checks the state of the contract
modifier inState(State _state) {
if (state != _state) throw;
_
}
// Prevents methods from perfoming any value transfer
modifier noEther() {if (msg.value > 0) throw; _}
// STAGES OF A PROPOSAL
// PREVOTE
// When the proposal is created it's in a "prevote" state where it can be analyzed and
// optionally public support might be gathered
function DAOProposal(
address _contractor,
bytes32 _hashOfTheProposalDocument,
uint initialPayout,
uint[] milestoneDates,
uint[] milestoneValues
) {
contractor = _contractor;
hashOfTheProposalDocument = _hashOfTheProposalDocument;
state = State.preVote;
initialPayment = initialPayout;
totalPayments = initialPayout;
for (uint i=0; i< milestoneValues.length; i++) {
milestones.length++;
milestones[i] = Milestones({
value: milestoneValues[i],
validAfter: milestoneDates[i],
completed: false,
paid: false
}) ;
totalPayments += milestoneValues[i];
}
}
// VOTING
// Once a proposal is submitted, the Contractor can save its proposalId so
// the vote can be watched
function watchProposal(uint _proposalId) inState(State.preVote) onlyContractor {
address recipient;
uint votingDeadline;
bool open;
(recipient,,votingDeadline, open, ) = client.proposals(_proposalId);
if (recipient == address(this)
&& votingDeadline > now
&& open
&& proposalId == 0
) {
proposalId = _proposalId;
state = State.Voting;
}
}
// The proposal will not accept the results of the vote if it wasn't able to
function protectFromAmbush() {
// This function can be called by anyone
uint votingDeadline;
uint yea;
uint nay;
(,,votingDeadline,,,,,,yea,nay,) = client.proposals(proposalId);
// Only execute until 48 hours before the deadline
if (now > votingDeadline - 48 hours) throw;
// If so, then check if was approved at that moment
wasApprovedBeforeDeadline = (yea > nay);
}
// APPROVED
function() {
if (msg.sender == address(client)
&& state == State.Voting) {
uint votingDeadline;
uint yea;
uint nay;
(,,votingDeadline,,,,,,yea,nay,) = client.proposals(proposalId);
uint quorum = client.totalSupply() / client.minQuorumDivisor();
// Check if Yea is at least 75% of the quorum and if it was not approved by ambush
if (4 * yea < 3 * quorum
|| !wasApprovedBeforeDeadline) {
client.send(this.balance);
state = State.Void;
} else {
dateOfSignature = now;
state = State.Approved;
}
}
}
// Change the client DAO by giving the new DAO's address
// warning: The new DAO must come either from a split of the original
// DAO or an update via `newContract()` so that it can claim rewards
function updateClientAddress(DAO _newClient) onlyClient noEther {
client = _newClient;
}
// Change the contractor payout address
function updateContractorAddress(DAO _newClient) onlyContractor noEther {
client = _newClient;
}
}
contract MyProposal is DAOProposal {
// Add here your own code
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment