Merge pull request #50 from Giveth/GriffGreen-patch-1

Updated Comments... still not done :-(
This commit is contained in:
perissology 2017-12-11 19:45:59 +00:00 committed by GitHub
commit e267e4c280
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 94 additions and 98 deletions

View File

@ -2,7 +2,8 @@ pragma solidity ^0.4.11;
/* /*
Copyright 2017, Jordi Baylina Copyright 2017, Jordi Baylina
Contributor: Adrià Massanet <adria@codecontext.io> Contributors: Adrià Massanet <adria@codecontext.io>, RJ Ewing, Griff
Green, Arthur Lunn
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -18,7 +19,6 @@ pragma solidity ^0.4.11;
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
// Contract Imports
import "./LiquidPledgingBase.sol"; import "./LiquidPledgingBase.sol";
/// @dev `LiquidPleding` allows for liquid pledging through the use of /// @dev `LiquidPleding` allows for liquid pledging through the use of
@ -40,33 +40,30 @@ contract LiquidPledging is LiquidPledgingBase {
function LiquidPledging(address _vault) LiquidPledgingBase(_vault) { function LiquidPledging(address _vault) LiquidPledgingBase(_vault) {
} }
/// @notice This is how value enters into the system which creates pledges; /// @notice This is how value enters the system and how pledges are created;
/// the token of value goes into the vault and the amount in the pledge /// the ether is sent to the vault, an pledge for the Giver is created (or
/// relevant to this Giver without delegates is increased, and a normal /// found), the amount of ETH donated in wei is added to the `amount` in
/// transfer is done to the idReceiver /// the Giver's Pledge, and an LP transfer is done to the idReceiver for
/// @param idGiver Identifier of the giver thats donating. /// the full amount
/// @param idReceiver To whom it's transfered. Can be the same giver, /// @param idGiver The id of the Giver donating; if 0, a new id is created
/// another giver, a delegate or a project. /// @param idReceiver The Admin receiving the donation; can be any Admin:
/// the Giver themselves, another Giver, a Delegate or a Project
function donate(uint64 idGiver, uint64 idReceiver) payable { function donate(uint64 idGiver, uint64 idReceiver) payable {
if (idGiver == 0) { if (idGiver == 0) {
// default to 3 day commitTime
// default to a 3 day (259200 seconds) commitTime
idGiver = addGiver("", "", 259200, ILiquidPledgingPlugin(0x0)); idGiver = addGiver("", "", 259200, ILiquidPledgingPlugin(0x0));
} }
PledgeAdmin storage sender = findAdmin(idGiver); PledgeAdmin storage sender = findAdmin(idGiver);
checkAdminOwner(sender); checkAdminOwner(sender);
require(sender.adminType == PledgeAdminType.Giver); require(sender.adminType == PledgeAdminType.Giver);
uint amount = msg.value; uint amount = msg.value;
require(amount > 0); require(amount > 0);
vault.transfer(amount); // Sends the `msg.value` (in wei) to the `vault`
vault.transfer(amount); // transfers the baseToken to the Vault
uint64 idPledge = findOrCreatePledge( uint64 idPledge = findOrCreatePledge(
idGiver, idGiver,
new uint64[](0), //what is new? new uint64[](0), // Creates empty array for delegationChain
0, 0,
0, 0,
0, 0,
@ -77,29 +74,26 @@ contract LiquidPledging is LiquidPledgingBase {
Pledge storage nTo = findPledge(idPledge); Pledge storage nTo = findPledge(idPledge);
nTo.amount += amount; nTo.amount += amount;
Transfer(0, idPledge, amount); Transfer(0, idPledge, amount); // An event
transfer(idGiver, idPledge, amount, idReceiver); transfer(idGiver, idPledge, amount, idReceiver); // LP accounting
} }
/// @notice Transfers amounts between pledges for internal accounting
/// @notice Moves value between pledges /// @param idSender Id of the Admin that is transferring the amount from
/// @param idSender ID of the giver, delegate or project admin that is /// Pledge to Pledge; this admin must have permissions to move the value
/// transferring the funds from Pledge to Pledge; this admin must have
/// permissions to move the value
/// @param idPledge Id of the pledge that's moving the value /// @param idPledge Id of the pledge that's moving the value
/// @param amount Quantity of value that's being moved /// @param amount Quantity of ETH (in wei) that this pledge is transferring
/// @param idReceiver Destination of the value, can be a giver sending to /// the authority to withdraw from the vault
/// a giver or a delegate, a delegate to another delegate or a project /// @param idReceiver Destination of the `amount`, can be a Giver/Project sending
/// to pre-commit it to that project if called from a delegate, /// to a Giver, a Delegate or a Project; a Delegate sending to another
/// or to commit it to the project if called from the owner. /// Delegate, or a Delegate pre-commiting it to a Project
function transfer( function transfer(
uint64 idSender, uint64 idSender,
uint64 idPledge, uint64 idPledge,
uint amount, uint amount,
uint64 idReceiver uint64 idReceiver
) ){
{
idPledge = normalizePledge(idPledge); idPledge = normalizePledge(idPledge);
@ -110,8 +104,9 @@ contract LiquidPledging is LiquidPledgingBase {
checkAdminOwner(sender); checkAdminOwner(sender);
require(p.pledgeState == PledgeState.Pledged); require(p.pledgeState == PledgeState.Pledged);
// If the sender is the owner // If the sender is the owner of the Pledge
if (p.owner == idSender) { if (p.owner == idSender) {
if (receiver.adminType == PledgeAdminType.Giver) { if (receiver.adminType == PledgeAdminType.Giver) {
transferOwnershipToGiver(idPledge, amount, idReceiver); transferOwnershipToGiver(idPledge, amount, idReceiver);
} else if (receiver.adminType == PledgeAdminType.Project) { } else if (receiver.adminType == PledgeAdminType.Project) {
@ -124,29 +119,30 @@ contract LiquidPledging is LiquidPledgingBase {
); );
appendDelegate(idPledge, amount, idReceiver); appendDelegate(idPledge, amount, idReceiver);
} else { } else {
// This should never be reached as the reciever.adminType
// should always be either a Giver, Project, or Delegate
assert(false); assert(false);
} }
return; return;
} }
// If the sender is a delegate // If the sender is a Delegate
uint senderDIdx = getDelegateIdx(p, idSender); uint senderDIdx = getDelegateIdx(p, idSender);
if (senderDIdx != NOTFOUND) { if (senderDIdx != NOTFOUND) {
// If the receiver is another giver // And the receiver is another Giver
if (receiver.adminType == PledgeAdminType.Giver) { if (receiver.adminType == PledgeAdminType.Giver) {
// Only accept to change to the original giver to // Only transfer to the Giver who owns the pldege
// remove all delegates
assert(p.owner == idReceiver); assert(p.owner == idReceiver);
undelegate(idPledge, amount, p.delegationChain.length); undelegate(idPledge, amount, p.delegationChain.length);
return; return;
} }
// If the receiver is another delegate // And the receiver is another Delegate
if (receiver.adminType == PledgeAdminType.Delegate) { if (receiver.adminType == PledgeAdminType.Delegate) {
uint receiverDIdx = getDelegateIdx(p, idReceiver); uint receiverDIdx = getDelegateIdx(p, idReceiver);
// If the receiver is not in the delegate list // And not in the delegationChain
if (receiverDIdx == NOTFOUND) { if (receiverDIdx == NOTFOUND) {
idPledge = undelegate( idPledge = undelegate(
idPledge, idPledge,
@ -155,10 +151,9 @@ contract LiquidPledging is LiquidPledgingBase {
); );
appendDelegate(idPledge, amount, idReceiver); appendDelegate(idPledge, amount, idReceiver);
// If the receiver is already part of the delegate chain and is // And part of the delegationChain and is after the sender, then
// after the sender, then all of the other delegates after the // all of the other delegates after the sender are removed and
// sender are removed and the receiver is appended at the // the receiver is appended at the end of the delegationChain
// end of the delegation chain
} else if (receiverDIdx > senderDIdx) { } else if (receiverDIdx > senderDIdx) {
idPledge = undelegate( idPledge = undelegate(
idPledge, idPledge,
@ -167,13 +162,10 @@ contract LiquidPledging is LiquidPledgingBase {
); );
appendDelegate(idPledge, amount, idReceiver); appendDelegate(idPledge, amount, idReceiver);
// If the receiver is already part of the delegate chain and is // And is already part of the delegate chain but is before the
// before the sender, then the sender and all of the other // sender, then the sender and all of the other delegates after
// delegates after the RECEIVER are removed from the chain, // the RECEIVER are removed from the delegationChain
// this is interesting because the delegate is removed from the } else if (receiverDIdx <= senderDIdx) {//TODO Check for Game Theory issues (from Arthur) this allows the sender to sort of go komakosi and remove himself and the delegates between himself and the receiver... should this authority be allowed?
// delegates that delegated to this delegate. Are there game theory
// issues? should this be allowed?
} else if (receiverDIdx <= senderDIdx) {
undelegate( undelegate(
idPledge, idPledge,
amount, amount,
@ -183,8 +175,8 @@ contract LiquidPledging is LiquidPledgingBase {
return; return;
} }
// If the delegate wants to support a project, they remove all // And the receiver is a Project, all the delegates after the sender
// the delegates after them in the chain and choose a project // are removed and the amount is pre-committed to the project
if (receiver.adminType == PledgeAdminType.Project) { if (receiver.adminType == PledgeAdminType.Project) {
idPledge = undelegate( idPledge = undelegate(
idPledge, idPledge,
@ -195,23 +187,19 @@ contract LiquidPledging is LiquidPledgingBase {
return; return;
} }
} }
assert(false); // It is not the owner nor any delegate. assert(false); // When the sender is not an owner or a delegate
} }
/// @notice This method is used to withdraw value from the system. /// @notice Authorizes a payment be made from the `vault` can be used by the
/// This can be used by the givers withdraw any un-commited donations. /// Giver to veto a pre-committed donation from a Delegate to an
/// @param idPledge Id of the pledge that wants to be withdrawn. /// intendedProject
/// @param amount Quantity of Ether that wants to be withdrawn. /// @param idPledge Id of the pledge that is to be redeemed into ether
/// @param amount Quantity of ether (in wei) to be authorized
function withdraw(uint64 idPledge, uint amount) { function withdraw(uint64 idPledge, uint amount) {
idPledge = normalizePledge(idPledge); // Updates pledge info
idPledge = normalizePledge(idPledge);
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);
require(p.pledgeState == PledgeState.Pledged); require(p.pledgeState == PledgeState.Pledged);
PledgeAdmin storage owner = findAdmin(p.owner); PledgeAdmin storage owner = findAdmin(p.owner);
checkAdminOwner(owner); checkAdminOwner(owner);
uint64 idNewPledge = findOrCreatePledge( uint64 idNewPledge = findOrCreatePledge(
@ -228,9 +216,10 @@ contract LiquidPledging is LiquidPledgingBase {
vault.authorizePayment(bytes32(idNewPledge), owner.addr, amount); vault.authorizePayment(bytes32(idNewPledge), owner.addr, amount);
} }
/// @notice Method called by the vault to confirm a payment. /// @notice `onlyVault` Confirms a withdraw request changing the PledgeState
/// @param idPledge Id of the pledge that wants to be withdrawn. /// from Paying to Paid
/// @param amount Quantity of Ether that wants to be withdrawn. /// @param idPledge Id of the pledge that is to be withdrawn
/// @param amount Quantity of ether (in wei) to be withdrawn
function confirmPayment(uint64 idPledge, uint amount) onlyVault { function confirmPayment(uint64 idPledge, uint amount) onlyVault {
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);
@ -248,13 +237,14 @@ contract LiquidPledging is LiquidPledgingBase {
doTransfer(idPledge, idNewPledge, amount); doTransfer(idPledge, idNewPledge, amount);
} }
/// @notice Method called by the vault to cancel a payment. /// @notice `onlyVault` Cancels a withdraw request, changing the PledgeState
/// @param idPledge Id of the pledge that wants to be canceled for withdraw. /// from Paying back to Pledged
/// @param amount Quantity of Ether that wants to be rolled back. /// @param idPledge Id of the pledge that's withdraw is to be canceled
/// @param amount Quantity of ether (in wei) to be canceled
function cancelPayment(uint64 idPledge, uint amount) onlyVault { function cancelPayment(uint64 idPledge, uint amount) onlyVault {
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);
require(p.pledgeState == PledgeState.Paying); //TODO change to revert require(p.pledgeState == PledgeState.Paying); //TODO change to revert????????????????????????????
// When a payment is canceled, never is assigned to a project. // When a payment is canceled, never is assigned to a project.
uint64 oldPledge = findOrCreatePledge( uint64 oldPledge = findOrCreatePledge(
@ -271,9 +261,9 @@ contract LiquidPledging is LiquidPledgingBase {
doTransfer(idPledge, oldPledge, amount); doTransfer(idPledge, oldPledge, amount);
} }
/// @notice Method called to cancel this project. /// @notice Changes the `project.canceled` flag to `true`; cannot be undone
/// @param idProject Id of the projct that wants to be canceled. /// @param idProject Id of the project that is to be canceled
function cancelProject(uint64 idProject) { function cancelProject(uint64 idProject) {
PledgeAdmin storage project = findAdmin(idProject); PledgeAdmin storage project = findAdmin(idProject);
checkAdminOwner(project); checkAdminOwner(project);
project.canceled = true; project.canceled = true;
@ -281,10 +271,12 @@ contract LiquidPledging is LiquidPledgingBase {
CancelProject(idProject); CancelProject(idProject);
} }
/// @notice Method called to cancel specific pledge. /// @notice Transfers `amount` in `idPledge` back to the `oldPledge` that
/// @param idPledge Id of the pledge that should be canceled. /// that sent it there in the first place, a Ctrl-z
/// @param amount Quantity of Ether that wants to be rolled back. /// @param idPledge Id of the pledge that is to be canceled
function cancelPledge(uint64 idPledge, uint amount) { /// @param amount Quantity of ether (in wei) to be transfered to the
/// `oldPledge`
function cancelPledge(uint64 idPledge, uint amount) {
idPledge = normalizePledge(idPledge); idPledge = normalizePledge(idPledge);
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);
@ -306,19 +298,19 @@ contract LiquidPledging is LiquidPledgingBase {
// efficient (saves gas) than calling these functions in series // efficient (saves gas) than calling these functions in series
/// Bit mask used for dividing pledge amounts in Multi pledge methods /// @dev Bitmask used for dividing pledge amounts in Multi pledge methods
uint constant D64 = 0x10000000000000000; uint constant D64 = 0x10000000000000000;
/// @notice `mTransfer` allows for multiple pledges to be transferred /// @notice Transfers multiple amounts within multiple Pledges in an
/// efficiently /// efficient single call
/// @param idSender ID of the giver, delegate or project admin that is /// @param idSender Id of the Admin that is transferring the amounts from
/// transferring the funds from Pledge to Pledge. This admin must have /// all the Pledges; this admin must have permissions to move the value
/// permissions to move the value /// @param pledgesAmounts An array of Pledge amounts and the idPledges with
/// @param pledgesAmounts An array of pledge amounts and IDs which are extrapolated /// which the amounts are associated; these are extrapolated using the D64
/// using the D64 bitmask /// bitmask
/// @param idReceiver Destination of the value, can be a giver sending /// @param idReceiver Destination of the `pledesAmounts`, can be a Giver or
/// to a giver or a delegate or a delegate to another delegate or a /// Project sending to a Giver, a Delegate or a Project; a Delegate sending
/// project to pre-commit it to that project /// to another Delegate, or a Delegate pre-commiting it to a Project
function mTransfer( function mTransfer(
uint64 idSender, uint64 idSender,
uint[] pledgesAmounts, uint[] pledgesAmounts,
@ -332,10 +324,11 @@ contract LiquidPledging is LiquidPledgingBase {
} }
} }
/// @notice `mWithdraw` allows for multiple pledges to be /// @notice Authorizes multiple amounts within multiple Pledges to be
/// withdrawn efficiently /// withdrawn from the `vault` in an efficient single call
/// @param pledgesAmounts An array of pledge amounts and IDs which are /// @param pledgesAmounts An array of Pledge amounts and the idPledges with
/// extrapolated using the D64 bitmask /// which the amounts are associated; these are extrapolated using the D64
/// bitmask
function mWithdraw(uint[] pledgesAmounts) { function mWithdraw(uint[] pledgesAmounts) {
for (uint i = 0; i < pledgesAmounts.length; i++ ) { for (uint i = 0; i < pledgesAmounts.length; i++ ) {
uint64 idPledge = uint64( pledgesAmounts[i] & (D64-1) ); uint64 idPledge = uint64( pledgesAmounts[i] & (D64-1) );
@ -482,16 +475,19 @@ contract LiquidPledging is LiquidPledgingBase {
/// end of the delegate chain for a given Pledge. /// end of the delegate chain for a given Pledge.
/// @param idPledge Id of the pledge thats delegate chain will be modified. /// @param idPledge Id of the pledge thats delegate chain will be modified.
/// @param amount Quantity of value that's shifted from delegates. /// @param amount Quantity of value that's shifted from delegates.
/// @param q Number (or depth) to remove as delegates /// @param q Number (or depth) of delegates to remove
/// @return toPledge The id for the pledge being adjusted or created
function undelegate( function undelegate(
uint64 idPledge, uint64 idPledge,
uint amount, uint amount,
uint q uint q
) internal returns (uint64){ ) internal returns (uint64)
{
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);
uint64[] memory newDelegationChain = new uint64[]( uint64[] memory newDelegationChain = new uint64[](
p.delegationChain.length - q p.delegationChain.length - q
); );
for (uint i=0; i<p.delegationChain.length - q; i++) { for (uint i=0; i<p.delegationChain.length - q; i++) {
newDelegationChain[i] = p.delegationChain[i]; newDelegationChain[i] = p.delegationChain[i];
} }
@ -559,8 +555,7 @@ contract LiquidPledging is LiquidPledgingBase {
callPlugins(false, from, to, amount); callPlugins(false, from, to, amount);
} }
/// @notice `normalizePledge` only affects pledges with the Pledged PledgeState /// @notice Only affects pledges with the Pledged PledgeState for 2 things:
/// and does 2 things:
/// #1: Checks if the pledge should be committed. This means that /// #1: Checks if the pledge should be committed. This means that
/// if the pledge has an intendedProject and it is past the /// if the pledge has an intendedProject and it is past the
/// commitTime, it changes the owner to be the proposed project /// commitTime, it changes the owner to be the proposed project
@ -573,9 +568,10 @@ contract LiquidPledging is LiquidPledgingBase {
/// appropriately. /// appropriately.
/// ///
/// This function can be called by anybody at anytime on any pledge. /// This function can be called by anybody at anytime on any pledge.
/// In general it can be called to force the calls of the affected /// In general it can be called to force the calls of the affected
/// plugins, which also need to be predicted by the UI /// plugins, which also need to be predicted by the UI
/// @param idPledge This is the id of the pledge that will be normalized /// @param idPledge This is the id of the pledge that will be normalized
/// @return The normalized Pledge!
function normalizePledge(uint64 idPledge) returns(uint64) { function normalizePledge(uint64 idPledge) returns(uint64) {
Pledge storage p = findPledge(idPledge); Pledge storage p = findPledge(idPledge);