Created
June 4, 2016 21:02
-
-
Save alexvandesande/cce8cea7dea4be47e373c4003582d56c to your computer and use it in GitHub Desktop.
Proposal Framework
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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