From a785a31dcea0cb8292b94fd9648b279800edc6f8 Mon Sep 17 00:00:00 2001 From: Griff Green Date: Thu, 23 Nov 2017 10:00:28 -0500 Subject: [PATCH] Commented all but the Whitelist additions --- contracts/LiquidPledgingBase.sol | 354 +++++++++++++++++-------------- 1 file changed, 195 insertions(+), 159 deletions(-) diff --git a/contracts/LiquidPledgingBase.sol b/contracts/LiquidPledgingBase.sol index 854a85d..e26d89f 100644 --- a/contracts/LiquidPledgingBase.sol +++ b/contracts/LiquidPledgingBase.sol @@ -20,108 +20,110 @@ pragma solidity ^0.4.11; import "./ILiquidPledgingPlugin.sol"; import "../node_modules/giveth-common-contracts/contracts/Owned.sol"; -/// @dev `Vault` serves as an interface to allow the `LiquidPledgingBase` -/// contract to interface with a `Vault` contract +/// @dev `LPVault` serves as an interface to allow the `LiquidPledgingBase` +/// contract to interface with a `LPVault` contract contract LPVault { function authorizePayment(bytes32 _ref, address _dest, uint _amount); function () payable; } /// @dev `LiquidPledgingBase` is the base level contract used to carry out -/// liquid pledging. This function mostly handles the data structures -/// and basic CRUD methods for liquid pledging. +/// liquid pledging's most basic functions, mostly handling and searching the +/// data structures contract LiquidPledgingBase is Owned { + // Limits inserted to prevent large loops that could prevent canceling uint constant MAX_DELEGATES = 20; uint constant MAX_SUBPROJECT_LEVEL = 20; uint constant MAX_INTERPROJECT_LEVEL = 20; enum PledgeAdminType { Giver, Delegate, Project } - enum PaymentState { Pledged, Paying, Paid } // TODO name change Pledged + enum PaymentState { Pledged, Paying, Paid } - /// @notice This struct defines the details of each the PledgeAdmin, these - /// PledgeAdmins can own pledges and act as delegates - struct PledgeAdmin { // TODO name change PledgeAdmin + /// @dev This struct defines the details of the `PledgeAdmin` which are + /// Referenced by their id and can own pledges and act as delegates + struct PledgeAdmin { PledgeAdminType adminType; // Giver, Delegate or Project - address addr; // account or contract address for admin + address addr; // Account or contract address for admin string name; - string url; + string url; // Can be IPFS hash uint64 commitTime; // In seconds, used for Givers' & Delegates' vetos uint64 parentProject; // Only for projects bool canceled; //Always false except for canceled projects - // if the plugin is 0x0 then nothing happens if its a contract address - // than that smart contract is called via the milestone contract + + /// @dev if the plugin is 0x0 then nothing happens, if its an address + // than that smart contract is called when appropriate ILiquidPledgingPlugin plugin; } struct Pledge { uint amount; uint64 owner; // PledgeAdmin - uint64[] delegationChain; // list of index numbers - // TODO change the name only used for when delegates are - // pre-committing to a project - uint64 intendedProject; - // When the intendedProject will become the owner - uint64 commitTime; - // this points to the Pledge[] index that the Pledge was derived from - uint64 oldPledge; - PaymentState paymentState; + uint64[] delegationChain; // List of delegates in order of authority + uint64 intendedProject; // Used when delegates are sending to projects + uint64 commitTime; // When the intendedProject will become the owner + uint64 oldPledge; // Points to the id that this Pledge was derived from + PaymentState paymentState; // Pledged, Paying, Paid } Pledge[] pledges; PledgeAdmin[] admins; //The list of pledgeAdmins 0 means there is no admin LPVault public vault; - // this mapping allows you to search for a specific pledge's - // index number by the hash of that pledge - mapping (bytes32 => uint64) hPledge2idx;//TODO Fix typo + /// @dev this mapping allows you to search for a specific pledge's + /// index number by the hash of that pledge + mapping (bytes32 => uint64) hPledge2idx; mapping (bytes32 => bool) pluginWhitelist; - + bool public usePluginWhitelist = true; - -///// +///////////// // Modifiers -///// +///////////// - /// @notice basic method to restrict a function to only the current vault + + /// @dev The `vault`is the only addresses that can call a function with this + /// modifier modifier onlyVault() { require(msg.sender == address(vault)); _; } -////// +/////////////// // Constructor -////// +/////////////// - /// @notice The Constructor creates the `LiquidPledgingBase` - /// on the blockchain - /// @param _vault The vault where ETH backing this pledge is stored + /// @notice The Constructor creates `LiquidPledgingBase` on the blockchain + /// @param _vault The vault where the ETH backing the pledges is stored function LiquidPledgingBase(address _vault) { admins.length = 1; // we reserve the 0 admin pledges.length = 1; // we reserve the 0 pledge - vault = LPVault(_vault); + vault = LPVault(_vault); // Assigns the specified vault } -/////// -// Admin functions -////// +///////////////////////// +// PledgeAdmin functions +///////////////////////// - /// @notice `addGiver` Creates a giver and adds them to the list of admins. - /// @param name This is the name used to identify the giver. - /// @param url This is a link to the givers profile or a representative site. - /// @param commitTime Set the default commit time period for this giver. - /// @param plugin This is givers liquid pledge plugin allowing for - /// extended functionality. + /// @notice Creates a Giver Admin with the `msg.sender` as the Admin address + /// @param name The name used to identify the Giver + /// @param url The link to the Giver's profile often an IPFS hash + /// @param commitTime The length of time in seconds the Giver has to + /// veto when the Giver's delegates Pledge funds to a project + /// @param plugin This is Giver's liquid pledge plugin allowing for + /// extended functionality + /// @return idGiver The id number used to reference this Admin function addGiver( string name, string url, uint64 commitTime, ILiquidPledgingPlugin plugin ) returns (uint64 idGiver) { - require(isValidPlugin(plugin)); + + require(isValidPlugin(plugin)); // Plugin check + idGiver = uint64(admins.length); admins.push(PledgeAdmin( @@ -139,15 +141,15 @@ contract LiquidPledgingBase is Owned { event GiverAdded(uint64 indexed idGiver); - /// @notice `updateGiver` allows for basic update operation to change the address, - /// name or commitTime associated with a specific giver. - /// @param idGiver This is the internal ID used to specify the admin lookup - /// that coresponds to the giver. - /// @param newAddr This parameter specifies an address to change the given - /// correspondancec between the giver's internal ID and an external address. - /// @param newName This is the name used to identify the giver. - /// @param newUrl This is a link to the givers profile or a representative site. - /// @param newCommitTime Set the default commit time period for this giver. + /// @notice Updates a Giver's info to change the address, name, url, or + /// commitTime, it cannot be used to change a plugin, and it must be called + /// by the current address of the Giver + /// @param idGiver This is the Admin id number used to specify the Giver + /// @param newAddr The new address that represents this Giver + /// @param newName The new name used to identify the Giver + /// @param newUrl The new link to the Giver's profile often an IPFS hash + /// @param newCommitTime Sets the length of time in seconds the Giver has to + /// veto when the Giver's delegates Pledge funds to a project function updateGiver( uint64 idGiver, address newAddr, @@ -156,8 +158,8 @@ contract LiquidPledgingBase is Owned { uint64 newCommitTime) { PledgeAdmin storage giver = findAdmin(idGiver); - require(giver.adminType == PledgeAdminType.Giver); //Must be a Giver - require(giver.addr == msg.sender); //current addr had to originate this tx + require(giver.adminType == PledgeAdminType.Giver); // Must be a Giver + require(giver.addr == msg.sender); // Current addr had to send this tx giver.addr = newAddr; giver.name = newName; giver.url = newUrl; @@ -167,18 +169,25 @@ contract LiquidPledgingBase is Owned { event GiverUpdated(uint64 indexed idGiver); - /// @notice `addDelegate` Creates a delegate and adds them to the list of admins. - /// @param name This is the name used to identify the delegate. - /// @param url This is a link to the delegates profile or a representative site. - /// @param commitTime Set the default commit time period for this delegate. - /// @param plugin This is givers liquid pledge plugin allowing for extended functionality. + /// @notice Creates a Delegate Admin with the `msg.sender` as the Admin addr + /// @param name The name used to identify the Delegate + /// @param url The link to the Delegate's profile often an IPFS hash + /// @param commitTime Sets the length of time in seconds the Delegate has to + /// veto when the Delegate delegates to another Delegate and they pledge + /// those funds to a project + /// @param plugin This is Delegate's liquid pledge plugin allowing for + /// extended functionality + /// @return idxDelegate The id number used to reference this Delegate within + /// the admins array function addDelegate( string name, string url, uint64 commitTime, ILiquidPledgingPlugin plugin - ) returns (uint64 idxDelegate) { //TODO return index number - require(isValidPlugin(plugin)); + ) returns (uint64 idxDelegate) { + + require(isValidPlugin(plugin)); // Plugin check + idxDelegate = uint64(admins.length); admins.push(PledgeAdmin( @@ -196,15 +205,16 @@ contract LiquidPledgingBase is Owned { event DelegateAdded(uint64 indexed idxDelegate); - /// @notice `updateDelegate` allows for basic update operation to change the address, - /// name or commitTime associated with a specific delegate. - /// @param idxDelegate This is the internal ID used to specify the admin lookup - /// that coresponds to the delegate. - /// @param newAddr This parameter specifies an address to change the given - /// correspondancec between the giver's internal ID and an external address. - /// @param newName This is the name used to identify the delegate. - /// @param newUrl This is a link to the delegates profile or a representative site. - /// @param newCommitTime Set the default commit time period for this giver. + /// @notice Updates a Delegate's info to change the address, name, url, or + /// commitTime, it cannot be used to change a plugin, and it must be called + /// by the current address of the Delegate + /// @param idxDelegate The Admin id number used to specify the Delegate + /// @param newAddr The new address that represents this Delegate + /// @param newName The new name used to identify the Delegate + /// @param newUrl The new link to the Delegate's profile often an IPFS hash + /// @param newCommitTime Sets the length of time in seconds the Delegate has + /// to veto when the Delegate delegates to a Delegate and they pledge those + /// funds to a project function updateDelegate( uint64 idxDelegate, address newAddr, @@ -213,7 +223,7 @@ contract LiquidPledgingBase is Owned { uint64 newCommitTime) { PledgeAdmin storage delegate = findAdmin(idxDelegate); require(delegate.adminType == PledgeAdminType.Delegate); - require(delegate.addr == msg.sender); + require(delegate.addr == msg.sender);// Current addr had to send this tx delegate.addr = newAddr; delegate.name = newName; delegate.url = newUrl; @@ -223,14 +233,18 @@ contract LiquidPledgingBase is Owned { event DelegateUpdated(uint64 indexed idxDelegate); - /// @notice `addProject` Creates a project and adds it to the list of admins. - /// @param name This is the name used to identify the project. - /// @param url This is a link to the projects profile or a representative site. - /// @param projectAdmin This is the projects admin. This should be a trusted individual. - /// @param parentProject If this project has a parent project or a project it's - /// derived from use this parameter to supply it. - /// @param commitTime Set the default commit time period for this project. - /// @param plugin This is the projects liquid pledge plugin allowing for extended functionality. + /// @notice Creates a Project Admin with the `msg.sender` as the Admin addr + /// @param name The name used to identify the Project + /// @param url The link to the Project's profile often an IPFS hash + /// @param projectAdmin The address for the trusted project manager + /// @param parentProject The Admin id number for the parent Campaign or 0 if + /// there is no parentProject + /// @param commitTime Sets the length of time in seconds the Project has to + /// veto when the Project delegates to another Delegate and they pledge + /// those funds to a project + /// @param plugin This is Project's liquid pledge plugin allowing for + /// extended functionality + /// @return idProject The id number used to reference this Admin function addProject( string name, string url, @@ -265,15 +279,17 @@ contract LiquidPledgingBase is Owned { event ProjectAdded(uint64 indexed idProject); - /// @notice `updateProject` allows for basic update operation to change the address, - /// name or commitTime associated with a specific project. - /// @param idProject This is the internal ID used to specify the admin lookup - /// that coresponds to the project. - /// @param newAddr This parameter specifies an address to change the given - /// correspondance between the project's internal ID and an external address. - /// @param newName This is the name used to identify the project. - /// @param newUrl This is a link to the projects profile or a representative site. - /// @param newCommitTime Set the default commit time period for this project. + + /// @notice Updates a Project's info to change the address, name, url, or + /// commitTime, it cannot be used to change a plugin or a parentProject, + /// and it must be called by the current address of the Project + /// @param idProject The Admin id number used to specify the Project + /// @param newAddr The new address that represents this Project + /// @param newName The new name used to identify the Project + /// @param newUrl The new link to the Project's profile often an IPFS hash + /// @param newCommitTime Sets the length of time in seconds the Project has + /// to veto when the Project delegates to a Delegate and they pledge those + /// funds to a project function updateProject( uint64 idProject, address newAddr, @@ -298,15 +314,17 @@ contract LiquidPledgingBase is Owned { // Public constant functions ////////// - /// @notice `numberOfPledges` is a constant getter that simply returns - /// the number of pledges. + /// @notice A constant getter that returns the total number of pledges + /// @return The total number of Pledges in the system function numberOfPledges() constant returns (uint) { return pledges.length - 1; } - /// @notice `getPledge` is a constant getter that simply returns - /// the amount, owner, the number of delegates, the intended project, - /// the current commit time and the previous pledge attached to a specific pledge. + /// @notice A getter that returns the details of the specified pledge + /// @param idPledge the id number of the pledge being queried + /// @return the amount, owner, the number of delegates (but not the actual + /// delegates, the intendedProject (if any), the current commit time and + /// the previous pledge this pledge was derived from function getPledge(uint64 idPledge) constant returns( uint amount, uint64 owner, @@ -326,10 +344,9 @@ contract LiquidPledgingBase is Owned { paymentState = n.paymentState; } - /// @notice `getPledgeDelegate` returns a single delegate given the pledge ID - /// and the delegate ID. - /// @param idPledge The ID internally representing the pledge. - /// @param idxDelegate The ID internally representing the delegate. + /// @notice Getter to find Delegate w/ the Pledge ID & the Delegate index + /// @param idPledge The id number representing the pledge being queried + /// @param idxDelegate The index number for the delegate in this Pledge function getPledgeDelegate(uint64 idPledge, uint idxDelegate) constant returns( uint64 idDelegate, address addr, @@ -342,16 +359,25 @@ contract LiquidPledgingBase is Owned { name = delegate.name; } - /// @notice `numberOfPledgeAdmins` is a constant getter that simply returns - /// the number of admins (Givers, Delegates and Projects are all "admins"). + /// @notice A constant getter used to check how many total Admins exist + /// @return The total number of admins (Givers, Delegates and Projects) . function numberOfPledgeAdmins() constant returns(uint) { return admins.length - 1; } - /// @notice `getPledgeAdmin` is a constant getter that simply returns - /// the address, name, url, the current commit time and the previous - /// the parentProject, whether the project has been cancelled - /// and the projects plugin for a specific project. + /// @notice A constant getter to check the details of a specified Admin + /// @return addr Account or contract address for admin + /// @return name Name of the pledgeAdmin + /// @return url The link to the Project's profile often an IPFS hash + /// @return commitTime The length of time in seconds the Admin has to veto + /// when the Admin delegates to a Delegate and that Delegate pledges those + /// funds to a project + /// @return parentProject The Admin id number for the parent Campaign or 0 + /// if there is no parentProject + /// @return canceled 0 for Delegates & Givers, true if a Project has been + /// canceled + /// @return plugin This is Project's liquidPledging plugin allowing for + /// extended functionality function getPledgeAdmin(uint64 idAdmin) constant returns ( PledgeAdminType adminType, address addr, @@ -377,16 +403,22 @@ contract LiquidPledgingBase is Owned { // Private methods /////// - /// @notice All pledges technically exist. If the pledge hasn't been + /// @notice This creates a Pledge with an initial amount of 0 if one is not + /// created already; otherwise it finds the pledge with the specified + /// attributes; all pledges technically exist, if the pledge hasn't been /// created in this system yet it simply isn't in the hash array - /// hPledge2idx[] yet; this creates a Pledge with an initial amount of 0 if one is not - /// created already. Otherwise - /// @param owner The owner of the pledge being looked up. - /// @param delegationChain The array of all delegates. - /// @param intendedProject The intended project is the project this pledge will Fund. - /// @param oldPledge This value is used to store the pledge the current pledge - /// is "coming from." - /// @param paid Based on the payment state this shows whether the pledge has been paid. + /// hPledge2idx[] yet + /// @param owner The owner of the pledge being looked up + /// @param delegationChain The list of delegates in order of authority + /// @param intendedProject The project this pledge will Fund after the + /// commitTime has passed + /// @param commitTime The length of time in seconds the Giver has to + /// veto when the Giver's delegates Pledge funds to a project + /// @param oldPledge This value is used to store the pledge the current + /// pledge was came from, and in the case a Project is canceled, the Pledge + /// will revert back to it's previous state + /// @param paid The payment state: Pledged, Paying, or Paid + /// @return The hPledge2idx index number function findOrCreatePledge( uint64 owner, uint64[] delegationChain, @@ -396,73 +428,80 @@ contract LiquidPledgingBase is Owned { PaymentState paid ) internal returns (uint64) { - bytes32 hPledge = sha3(owner, delegationChain, intendedProject, commitTime, oldPledge, paid); + bytes32 hPledge = sha3( + owner, delegationChain, intendedProject, commitTime, oldPledge, paid); uint64 idx = hPledge2idx[hPledge]; if (idx > 0) return idx; idx = uint64(pledges.length); hPledge2idx[hPledge] = idx; - pledges.push(Pledge(0, owner, delegationChain, intendedProject, commitTime, oldPledge, paid)); + pledges.push(Pledge( + 0, owner, delegationChain, intendedProject, commitTime, oldPledge, paid)); return idx; } - /// @notice `findAdmin` is a basic getter to return a - /// specific admin (giver, delegate, or project) - /// @param idAdmin The admin ID to lookup. + /// @notice A getter to look up a Admin's details + /// @param idAdmin The id for the Admin to lookup + /// @return The PledgeAdmin struct for the specified Admin function findAdmin(uint64 idAdmin) internal returns (PledgeAdmin storage) { require(idAdmin < admins.length); return admins[idAdmin]; } - /// @notice `findPledge` is a basic getter to return a - /// specific pledge - /// @param idPledge The admin ID to pledge. + /// @notice A getter to look up a Pledge's details + /// @param idPledge The id for the Pledge to lookup + /// @return The PledgeA struct for the specified Pledge function findPledge(uint64 idPledge) internal returns (Pledge storage) { require(idPledge < pledges.length); return pledges[idPledge]; } - // a constant for the case that a delegate is requested that is not a delegate in the system + // a constant for when a delegate is requested that is not in the system uint64 constant NOTFOUND = 0xFFFFFFFFFFFFFFFF; - /// @notice `getDelegateIdx` is a helper function that searches the delegationChain - /// for a specific delegate and level of delegation returns their idx in the - /// delegation chain which reflect their level of authority. Returns MAX uint64 - /// if no delegate is found. - /// @param n The pledge that will be searched. - /// @param idxDelegate The internal ID of the delegate that's searched for. + /// @notice A getter that searches the delegationChain for the level of + /// authority a specific delegate has within a Pledge + /// @param n The Pledge that will be searched + /// @param idxDelegate The specified delegate that's searched for + /// @return How many Delegates have more authority than the specified + /// delegate; if the delegate is not in the delegationChain it will return + /// `0xFFFFFFFFFFFFFFFF` function getDelegateIdx(Pledge n, uint64 idxDelegate) internal returns(uint64) { for (uint i=0; i commitTime) commitTime = m.commitTime; } } - /// @notice `getProjectLevel` is a helper function that returns the project - /// level which can be used to check that there are not too many Projects - /// that violate MAX_SUBCAMPAIGNS_LEVEL. + /// @notice A getter to find the level of authority a specific Project has + /// using a self-referential loop + /// @param m The Project being queried + /// @return The level of authority a specific Project has function getProjectLevel(PledgeAdmin m) internal returns(uint) { assert(m.adminType == PledgeAdminType.Project); if (m.parentProject == 0) return(1); @@ -470,9 +509,9 @@ contract LiquidPledgingBase is Owned { return getProjectLevel(parentNM); } - /// @notice `isProjectCanceled` is a basic helper function to check if - /// a project has been cancelled. - /// @param projectId The internal id of the project to lookup. + /// @notice A getter to find if a specified Project has been canceled + /// @param projectId The Admin id number used to specify the Project + /// @return True if the Project has been canceled function isProjectCanceled(uint64 projectId) constant returns (bool) { PledgeAdmin storage m = findAdmin(projectId); if (m.adminType == PledgeAdminType.Giver) return false; @@ -482,10 +521,11 @@ contract LiquidPledgingBase is Owned { return isProjectCanceled(m.parentProject); } - /// @notice `getOldestPledgeNotCanceled` is a helper function to get the oldest pledge - /// that hasn't been cancelled recursively. - /// @param idPledge The starting place to lookup the pledges from - function getOldestPledgeNotCanceled(uint64 idPledge) internal constant returns(uint64) { //todo rename + /// @notice A getter to find the oldest pledge that hasn't been canceled + /// @param idPledge The starting place to lookup the pledges + /// @return The oldest idPledge that hasn't been canceled (DUH!) + function getOldestPledgeNotCanceled(uint64 idPledge + ) internal constant returns(uint64) { if (idPledge == 0) return 0; Pledge storage n = findPledge(idPledge); PledgeAdmin storage admin = findAdmin(n.owner); @@ -498,19 +538,15 @@ contract LiquidPledgingBase is Owned { return getOldestPledgeNotCanceled(n.oldPledge); } - /// @notice `checkAdminOwner` is a helper function designed to throw - /// an error code if the user is not an admin. As PledgeAdmin is an - /// an internal structure this basically works like a modifier check - /// would however using internal data. - /// @dev Looking into whether this can be done with a modifier would be good - /// @param m A PledgeAdmin structure object. + /// @notice A check to see if the msg.sender is the owner or the + /// plugin contract for a specific Admin + /// @param m The Admin being checked function checkAdminOwner(PledgeAdmin m) internal constant { require((msg.sender == m.addr) || (msg.sender == address(m.plugin))); } - -//////// +/////////////////////////// // Plugin Whitelist Methods -/////// +/////////////////////////// function addValidPlugin(bytes32 contractHash) external onlyOwner { pluginWhitelist[contractHash] = true;