diff --git a/contracts/ILiquidPledging.sol b/contracts/ILiquidPledging.sol index 87fe94e..1f5f477 100644 --- a/contracts/ILiquidPledging.sol +++ b/contracts/ILiquidPledging.sol @@ -2,7 +2,9 @@ pragma solidity ^0.4.11; contract ILiquidPledging { - enum NoteManagerType { Donor, Delegate, Project } +// TODO: make this enum its own contract... or at least make it so that an owner +// can add a new NoteManagerType + enum NoteManagerType { Donor, Delegate, Project} enum PaymentState {NotPaid, Paying, Paid} function numberOfNotes() constant returns (uint); diff --git a/contracts/LiquidPledging.sol b/contracts/LiquidPledging.sol index 5d3dd57..8e92dac 100644 --- a/contracts/LiquidPledging.sol +++ b/contracts/LiquidPledging.sol @@ -5,22 +5,24 @@ import "./LiquidPledgingBase.sol"; contract LiquidPledging is LiquidPledgingBase { - uint constant MAX_DELEGATES = 20; - uint constant MAX_SUBPROJECT_LEVEL = 20; + ////// // Constructor ////// + // This constructor actualy also calls the constructor for the + // `LiquidPledgingBase` contract function LiquidPledging(address _vault) LiquidPledgingBase(_vault) { } - /// @notice This is the main entry of Ether to the system. Ethether goes to - /// the vault and then the Note for the donor withou delegates is increased. + /// @notice This is how value enters into the system which creates notes. The + /// token of value goes into the vault and then the amount in the Note + /// relevant to this donor without delegates is increased. /// After that, a normal transfer is done to the idReceiver. - /// @param idDonor Id of the donor thats donating. - /// @param idReceiver To who it's transfered. Can ve the same donnor, another + /// @param idDonor Identifier of the donor thats donating. + /// @param idReceiver To whom it's transfered. Can be the same donor, another /// donor, a delegate or a project - function donate(uint64 idDonor, uint64 idReceiver) payable { + function donate(uint64 idDonor, uint64 idReceiver) payable {// TODO change to `pledge()` NoteManager storage sender = findManager(idDonor); require(sender.managerType == NoteManagerType.Donor); @@ -30,10 +32,10 @@ contract LiquidPledging is LiquidPledgingBase { require(amount > 0); - vault.transfer(amount); + vault.transfer(amount); // transfers the baseToken to the Vault uint64 idNote = findNote( idDonor, - new uint64[](0), + new uint64[](0), //what is new 0, 0, 0, @@ -49,13 +51,13 @@ contract LiquidPledging is LiquidPledgingBase { } - /// @notice This is the main function to move Ether from one Note to the other - /// @param idSender Id of the donor, delegate or project manager that is transferin - /// the funds from Note to note. This manager must have permisions to move the Ether - /// @param idNote Id of the note that's moving the Ether. - /// @param amount Quantity of Ether that's moving. - /// @param idReceiver Destination of the Ether, can be a donor to move Ether between donors, - /// A delegate to delegate that Ether, or a project to commit or precommit it to that project. + /// @notice This is the main function to move value from one Note to the other + /// @param idSender ID of the donor, delegate or project manager that is transfering + /// the funds from Note to Note. This manager must have permisions to move the value + /// @param idNote Id of the note that's moving the value + /// @param amount Quantity of value that's being moved + /// @param idReceiver Destination of the value, can be a donor sending to a donor or + /// a delegate, a delegate to another delegate or a project to precommit it to that project function transfer(uint64 idSender, uint64 idNote, uint amount, uint64 idReceiver) { idNote = normalizeNote(idNote); @@ -85,7 +87,7 @@ contract LiquidPledging is LiquidPledgingBase { uint senderDIdx = getDelegateIdx(n, idSender); if (senderDIdx != NOTFOUND) { - // If the receiver is another doner + // If the receiver is another donor if (receiver.managerType == NoteManagerType.Donor) { // Only accept to change to the original donor to remove all delegates assert(n.owner == idReceiver); @@ -96,23 +98,32 @@ contract LiquidPledging is LiquidPledgingBase { // If the receiver is another delegate if (receiver.managerType == NoteManagerType.Delegate) { uint receiverDIdx = getDelegateIdx(n, idReceiver); + // If the receiver is not in the delegate list if (receiverDIdx == NOTFOUND) { undelegate(idNote, amount, n.delegationChain.length - senderDIdx - 1); appendDelegate(idNote, amount, idReceiver); - // If the receiver is after the delegate list and is not the next one. - // Canccel delegations an redelegate + + // If the receiver is already part of the delegate chain and is + // after the sender, then all of the other delegates after the sender are + // removed and the receiver is appended at the end of the delegation chain } else if (receiverDIdx > senderDIdx) { undelegate(idNote, amount, n.delegationChain.length - senderDIdx - 1); appendDelegate(idNote, amount, idReceiver); - // If it's before the list cancel thelegations until him + + // If the receiver is already part of the delegate chain and is + // before the sender, then the sender and all of the other + // delegates after the RECEIVER are revomved from the chain, + // this is interesting because the delegate undelegates from the + // delegates that delegated to this delegate... game theory issues? should this be allowed } else if (receiverDIdx <= senderDIdx) { undelegate(idNote, amount, n.delegationChain.length - receiverDIdx -1); } return; } - // If the delegate chose a project to assign + // If the delegate wants to support a project, they undelegate all + // the delegates after them in the chain and choose a project if (receiver.managerType == NoteManagerType.Project) { undelegate(idNote, amount, n.delegationChain.length - senderDIdx - 1); proposeAssignProject(idNote, amount, idReceiver); @@ -123,8 +134,8 @@ contract LiquidPledging is LiquidPledgingBase { } - /// @notice This method is used to withdraw Ether from the system. This can be used - /// from the doonurs to rollback a not commited donation or by project manager to use + /// @notice This method is used to withdraw value from the system. This can be used + /// by the donors to avoid committing the donation or by project manager to use /// the Ether. /// @param idNote Id of the note that wants to be withdrawed. /// @param amount Quantity of Ether that wants to be withdrawed. @@ -183,7 +194,7 @@ contract LiquidPledging is LiquidPledgingBase { function cancelPayment(uint64 idNote, uint amount) onlyVault { Note storage n = findNote(idNote); - require(n.paymentState == PaymentState.Paying); + require(n.paymentState == PaymentState.Paying); //TODO change to revert // When a payment is cacnceled, never is assigned to a project. uint64 oldNote = findNote( @@ -212,6 +223,8 @@ contract LiquidPledging is LiquidPledgingBase { // Multi note methods //////// + // This set of functions makes moving a lot of notes around much more + // efficient (saves gas) than calling these functions in series uint constant D64 = 0x10000000000000000; function mTransfer(uint64 idSender, uint[] notesAmounts, uint64 idReceiver) { for (uint i = 0; i < notesAmounts.length; i++ ) { @@ -253,7 +266,8 @@ contract LiquidPledging is LiquidPledgingBase { // Private methods /////// - + // this function is obvious, but it can also be called to undelegate everyone + // by setting your self as teh idReceiver function transferOwnershipToProject(uint64 idNote, uint amount, uint64 idReceiver) internal { Note storage n = findNote(idNote); @@ -265,24 +279,19 @@ contract LiquidPledging is LiquidPledgingBase { 0, n.oldNote, PaymentState.NotPaid); - - // If the owner does not change, then just let it this way. - if (n.owner == idReceiver) return; uint64 toNote = findNote( - idReceiver, - new uint64[](0), - 0, - 0, - oldNote, - PaymentState.NotPaid); + idReceiver, + new uint64[](0), + 0, + 0, + oldNote, + PaymentState.NotPaid); doTransfer(idNote, toNote, amount); } function transferOwnershipToDonor(uint64 idNote, uint amount, uint64 idReceiver) internal { - // If the owner does not change, then just let it this way. Note storage n = findNote(idNote); - if (n.owner == idReceiver) return; uint64 toNote = findNote( idReceiver, new uint64[](0), @@ -296,12 +305,15 @@ contract LiquidPledging is LiquidPledgingBase { function appendDelegate(uint64 idNote, uint amount, uint64 idReceiver) internal { Note storage n= findNote(idNote); - require(n.delegationChain.length < MAX_DELEGATES); + require(n.delegationChain.length < MAX_DELEGATES); //TODO change to revert and say the error uint64[] memory newDelegationChain = new uint64[](n.delegationChain.length + 1); for (uint i=0; i uint64) hNote2ddx; + // this mapping allows you to search for a specific note's index number by the hash of that note + mapping (bytes32 => uint64) hNote2ddx;//TODO Fix typo ///// @@ -51,8 +55,8 @@ contract LiquidPledgingBase { ////// function LiquidPledgingBase(address _vault) { - managers.length = 1; - notes.length = 1; + managers.length = 1; // we reserve the 0 manager + notes.length = 1; // we reserve the 0 note vault = Vault(_vault); } @@ -61,7 +65,7 @@ contract LiquidPledgingBase { // Managers functions ////// - function addDonor(string name, uint64 commitTime) { + function addDonor(string name, uint64 commitTime) {//Todo return idManager managers.push(NoteManager( NoteManagerType.Donor, msg.sender, @@ -73,7 +77,7 @@ contract LiquidPledgingBase { DonorAdded(uint64(managers.length-1)); } - event DonorAdded(uint64 indexed idMember); + event DonorAdded(uint64 indexed idDonor); function updateDonor( uint64 idDonor, @@ -90,9 +94,9 @@ contract LiquidPledgingBase { DonorUpdated(idDonor); } - event DonorUpdated(uint64 indexed idMember); + event DonorUpdated(uint64 indexed idDonor); - function addDelegate(string name) { + function addDelegate(string name) { //TODO return index number managers.push(NoteManager( NoteManagerType.Delegate, msg.sender, @@ -104,7 +108,7 @@ contract LiquidPledgingBase { DeegateAdded(uint64(managers.length-1)); } - event DeegateAdded(uint64 indexed idMember); + event DeegateAdded(uint64 indexed idDelegate); function updateDelegate(uint64 idDelegate, address newAddr, string newName) { NoteManager storage delegate = findManager(idDelegate); @@ -115,7 +119,7 @@ contract LiquidPledgingBase { DelegateUpdated(idDelegate); } - event DelegateUpdated(uint64 indexed idMember); + event DelegateUpdated(uint64 indexed idDelegate); function addProject(string name, address reviewer, uint64 commitTime) { managers.push(NoteManager( @@ -129,7 +133,7 @@ contract LiquidPledgingBase { ProjectAdded(uint64(managers.length-1)); } - event ProjectAdded(uint64 indexed idMember); + event ProjectAdded(uint64 indexed idProject); function updateProject(uint64 idProject, address newAddr, string newName, uint64 newCommitTime) { NoteManager storage project = findManager(idProject); @@ -141,7 +145,7 @@ contract LiquidPledgingBase { ProjectUpdated(idProject); } - function updateProjectCanceler(uint64 idProject, address newReviewer) { + function updateProjectReviewer(uint64 idProject, address newReviewer) { NoteManager storage project = findManager(idProject); require(project.managerType == NoteManagerType.Project); require(project.reviewer == msg.sender); @@ -149,7 +153,7 @@ contract LiquidPledgingBase { ProjectUpdated(idProject); } - event ProjectUpdated(uint64 indexed idMember); + event ProjectUpdated(uint64 indexed idManager); ////////// @@ -179,7 +183,7 @@ contract LiquidPledgingBase { oldNote = n.oldNote; paymentState = n.paymentState; } - + // This is to return the delegates one by one, because you can not return an array function getNoteDelegate(uint64 idNote, uint idxDelegate) constant returns( uint64 idDelegate, address addr, @@ -217,6 +221,9 @@ contract LiquidPledgingBase { // Private methods /////// + // All notes exist... but if the note hasn't been created in this system yet then it wouldn't + // be in the hash array hNoteddx[] + // this function creates a balloon if one is not created already... this ballon has 0 for the amount function findNote( uint64 owner, uint64[] delegationChain, @@ -245,12 +252,35 @@ contract LiquidPledgingBase { return notes[idNote]; } - function getOldestNoteNotCanceled(uint64 idNote) internal constant returns(uint64) { + // a constant for the case that a delegate is requested that is not a delegate in the system + uint64 constant NOTFOUND = 0xFFFFFFFFFFFFFFFF; + + // helper function that searches the delegationChain fro a specific delegate and + // level of delegation returns their idx in the delegation cahin which reflect their level of authority + function getDelegateIdx(Note n, uint64 idDelegate) internal returns(uint64) { + for (uint i=0; i