2017-06-06 17:40:14 +00:00
|
|
|
pragma solidity ^0.4.11;
|
2018-01-25 16:31:13 +00:00
|
|
|
|
2017-10-24 04:09:56 +00:00
|
|
|
/*
|
|
|
|
Copyright 2017, Jordi Baylina
|
2017-12-04 01:18:31 +00:00
|
|
|
Contributors: Adrià Massanet <adria@codecontext.io>, RJ Ewing, Griff
|
|
|
|
Green, Arthur Lunn
|
2017-10-24 04:09:56 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2017-06-06 17:40:14 +00:00
|
|
|
|
2017-09-13 12:41:08 +00:00
|
|
|
import "./ILiquidPledgingPlugin.sol";
|
2018-02-10 14:14:52 +00:00
|
|
|
// import "giveth-common-contracts/contracts/Escapable.sol";
|
|
|
|
import "./EscapableApp.sol";
|
2018-01-17 01:20:07 +00:00
|
|
|
import "./PledgeAdmins.sol";
|
2018-01-19 18:33:58 +00:00
|
|
|
import "./Pledges.sol";
|
2017-09-13 12:41:08 +00:00
|
|
|
|
2017-12-04 01:18:31 +00:00
|
|
|
/// @dev This is an interface for `LPVault` which serves as a secure storage for
|
|
|
|
/// the ETH that backs the Pledges, only after `LiquidPledging` authorizes
|
|
|
|
/// payments can Pledges be converted for ETH
|
2018-02-10 14:14:52 +00:00
|
|
|
interface ILPVault {
|
2018-01-15 22:36:17 +00:00
|
|
|
function authorizePayment(bytes32 _ref, address _dest, uint _amount) public;
|
|
|
|
function () public payable;
|
2017-07-13 17:12:45 +00:00
|
|
|
}
|
2017-06-06 17:40:14 +00:00
|
|
|
|
2017-10-24 04:09:56 +00:00
|
|
|
/// @dev `LiquidPledgingBase` is the base level contract used to carry out
|
2017-12-04 01:18:31 +00:00
|
|
|
/// liquidPledging's most basic functions, mostly handling and searching the
|
2017-11-23 15:00:28 +00:00
|
|
|
/// data structures
|
2018-02-10 14:14:52 +00:00
|
|
|
contract LiquidPledgingBase is PledgeAdmins, Pledges, EscapableApp {
|
2017-06-06 17:40:14 +00:00
|
|
|
|
2018-02-12 23:24:26 +00:00
|
|
|
// Event Declarations
|
|
|
|
event Transfer(uint indexed from, uint indexed to, uint amount);
|
|
|
|
event CancelProject(uint indexed idProject);
|
|
|
|
|
2018-02-10 14:14:52 +00:00
|
|
|
ILPVault public vault;
|
2018-01-25 16:31:13 +00:00
|
|
|
|
2017-11-23 15:00:28 +00:00
|
|
|
/////////////
|
2017-06-06 17:40:14 +00:00
|
|
|
// Modifiers
|
2017-11-23 15:00:28 +00:00
|
|
|
/////////////
|
|
|
|
|
|
|
|
/// @dev The `vault`is the only addresses that can call a function with this
|
|
|
|
/// modifier
|
2017-06-06 17:40:14 +00:00
|
|
|
modifier onlyVault() {
|
2017-07-13 17:12:45 +00:00
|
|
|
require(msg.sender == address(vault));
|
2017-06-06 17:40:14 +00:00
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
2017-11-23 15:00:28 +00:00
|
|
|
///////////////
|
2017-06-06 17:40:14 +00:00
|
|
|
// Constructor
|
2017-11-23 15:00:28 +00:00
|
|
|
///////////////
|
2017-06-06 17:40:14 +00:00
|
|
|
|
2018-02-12 22:55:11 +00:00
|
|
|
function initialize(address _escapeHatchDestination) onlyInit public {
|
2018-02-10 14:14:52 +00:00
|
|
|
require(false); // overload the EscapableApp
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @param _vault The vault where the ETH backing the pledges is stored
|
|
|
|
/// @param _escapeHatchDestination The address of a safe location (usu a
|
|
|
|
/// Multisig) to send the ether held in this contract; if a neutral address
|
|
|
|
/// is required, the WHG Multisig is an option:
|
|
|
|
/// 0x8Ff920020c8AD673661c8117f2855C384758C572
|
2018-02-12 22:55:11 +00:00
|
|
|
function initialize(address _vault, address _escapeHatchDestination) onlyInit public {
|
|
|
|
super.initialize(_escapeHatchDestination);
|
2018-02-10 14:14:52 +00:00
|
|
|
require(_vault != 0x0);
|
|
|
|
|
|
|
|
vault = ILPVault(_vault);
|
2018-02-12 22:55:11 +00:00
|
|
|
|
|
|
|
admins.length = 1; // we reserve the 0 admin
|
|
|
|
pledges.length = 1; // we reserve the 0 pledge
|
2018-02-10 14:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-25 16:31:13 +00:00
|
|
|
/////////////////////////////
|
2017-06-06 17:40:14 +00:00
|
|
|
// Public constant functions
|
2018-01-25 16:31:13 +00:00
|
|
|
/////////////////////////////
|
2017-10-27 19:09:55 +00:00
|
|
|
|
2017-11-23 15:00:28 +00:00
|
|
|
/// @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
|
2018-02-10 14:14:52 +00:00
|
|
|
function getPledgeDelegate(uint64 idPledge, uint64 idxDelegate) public view returns(
|
|
|
|
uint64 idDelegate,
|
2017-06-06 17:40:14 +00:00
|
|
|
address addr,
|
|
|
|
string name
|
|
|
|
) {
|
2018-02-10 14:14:52 +00:00
|
|
|
Pledge storage p = _findPledge(idPledge);
|
|
|
|
idDelegate = p.delegationChain[idxDelegate - 1];
|
|
|
|
PledgeAdmin storage delegate = _findAdmin(idDelegate);
|
|
|
|
addr = delegate.addr;
|
|
|
|
name = delegate.name;
|
2017-06-06 17:40:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-25 16:31:13 +00:00
|
|
|
////////////////////
|
|
|
|
// Internal methods
|
|
|
|
////////////////////
|
2017-06-06 17:40:14 +00:00
|
|
|
|
2018-02-12 23:24:26 +00:00
|
|
|
/// @notice `transferOwnershipToProject` allows for the transfer of
|
|
|
|
/// ownership to the project, but it can also be called by a project
|
|
|
|
/// to un-delegate everyone by setting one's own id for the idReceiver
|
|
|
|
/// @param idPledge the id of the pledge to be transfered.
|
|
|
|
/// @param amount Quantity of value that's being transfered
|
|
|
|
/// @param idReceiver The new owner of the project (or self to un-delegate)
|
|
|
|
function _transferOwnershipToProject(
|
|
|
|
uint64 idPledge,
|
|
|
|
uint amount,
|
|
|
|
uint64 idReceiver
|
|
|
|
) internal
|
|
|
|
{
|
|
|
|
Pledges.Pledge storage p = _findPledge(idPledge);
|
|
|
|
|
|
|
|
// Ensure that the pledge is not already at max pledge depth
|
|
|
|
// and the project has not been canceled
|
|
|
|
require(_getPledgeLevel(p) < MAX_INTERPROJECT_LEVEL);
|
|
|
|
require(!_isProjectCanceled(idReceiver));
|
|
|
|
|
|
|
|
uint64 oldPledge = _findOrCreatePledge(
|
|
|
|
p.owner,
|
|
|
|
p.delegationChain,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
p.oldPledge,
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
uint64 toPledge = _findOrCreatePledge(
|
|
|
|
idReceiver, // Set the new owner
|
|
|
|
new uint64[](0), // clear the delegation chain
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
uint64(oldPledge),
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
_doTransfer(idPledge, toPledge, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// @notice `transferOwnershipToGiver` allows for the transfer of
|
|
|
|
/// value back to the Giver, value is placed in a pledged state
|
|
|
|
/// without being attached to a project, delegation chain, or time line.
|
|
|
|
/// @param idPledge the id of the pledge to be transfered.
|
|
|
|
/// @param amount Quantity of value that's being transfered
|
|
|
|
/// @param idReceiver The new owner of the pledge
|
|
|
|
function _transferOwnershipToGiver(
|
|
|
|
uint64 idPledge,
|
|
|
|
uint amount,
|
|
|
|
uint64 idReceiver
|
|
|
|
) internal
|
|
|
|
{
|
|
|
|
uint64 toPledge = _findOrCreatePledge(
|
|
|
|
idReceiver,
|
|
|
|
new uint64[](0),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
_doTransfer(idPledge, toPledge, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `appendDelegate` allows for a delegate to be added onto the
|
|
|
|
/// end of the delegate chain for a given Pledge.
|
|
|
|
/// @param idPledge the id of the pledge thats delegate chain will be modified.
|
|
|
|
/// @param amount Quantity of value that's being chained.
|
|
|
|
/// @param idReceiver The delegate to be added at the end of the chain
|
|
|
|
function _appendDelegate(
|
|
|
|
uint64 idPledge,
|
|
|
|
uint amount,
|
|
|
|
uint64 idReceiver
|
|
|
|
) internal
|
|
|
|
{
|
|
|
|
Pledges.Pledge storage p = _findPledge(idPledge);
|
|
|
|
|
|
|
|
require(p.delegationChain.length < MAX_DELEGATES);
|
|
|
|
uint64[] memory newDelegationChain = new uint64[](
|
|
|
|
p.delegationChain.length + 1
|
|
|
|
);
|
|
|
|
for (uint i = 0; i < p.delegationChain.length; i++) {
|
|
|
|
newDelegationChain[i] = p.delegationChain[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the last item in the array the idReceiver
|
|
|
|
newDelegationChain[p.delegationChain.length] = idReceiver;
|
|
|
|
|
|
|
|
uint64 toPledge = _findOrCreatePledge(
|
|
|
|
p.owner,
|
|
|
|
newDelegationChain,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
p.oldPledge,
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
_doTransfer(idPledge, toPledge, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `appendDelegate` allows for a delegate to be added onto the
|
|
|
|
/// end of the delegate chain for a given Pledge.
|
|
|
|
/// @param idPledge the id of the pledge thats delegate chain will be modified.
|
|
|
|
/// @param amount Quantity of value that's shifted from delegates.
|
|
|
|
/// @param q Number (or depth) of delegates to remove
|
|
|
|
/// @return toPledge The id for the pledge being adjusted or created
|
|
|
|
function _undelegate(
|
|
|
|
uint64 idPledge,
|
|
|
|
uint amount,
|
|
|
|
uint q
|
|
|
|
) internal returns (uint64 toPledge)
|
|
|
|
{
|
|
|
|
Pledges.Pledge storage p = _findPledge(idPledge);
|
|
|
|
uint64[] memory newDelegationChain = new uint64[](
|
|
|
|
p.delegationChain.length - q
|
|
|
|
);
|
|
|
|
|
|
|
|
for (uint i = 0; i < p.delegationChain.length - q; i++) {
|
|
|
|
newDelegationChain[i] = p.delegationChain[i];
|
|
|
|
}
|
|
|
|
toPledge = _findOrCreatePledge(
|
|
|
|
p.owner,
|
|
|
|
newDelegationChain,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
p.oldPledge,
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
_doTransfer(idPledge, toPledge, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `proposeAssignProject` proposes the assignment of a pledge
|
|
|
|
/// to a specific project.
|
|
|
|
/// @dev This function should potentially be named more specifically.
|
|
|
|
/// @param idPledge the id of the pledge that will be assigned.
|
|
|
|
/// @param amount Quantity of value this pledge leader would be assigned.
|
|
|
|
/// @param idReceiver The project this pledge will potentially
|
|
|
|
/// be assigned to.
|
|
|
|
function _proposeAssignProject(
|
|
|
|
uint64 idPledge,
|
|
|
|
uint amount,
|
|
|
|
uint64 idReceiver
|
|
|
|
) internal
|
|
|
|
{
|
|
|
|
Pledges.Pledge storage p = _findPledge(idPledge);
|
|
|
|
|
|
|
|
require(_getPledgeLevel(p) < MAX_INTERPROJECT_LEVEL);
|
|
|
|
require(!_isProjectCanceled(idReceiver));
|
|
|
|
|
|
|
|
uint64 toPledge = _findOrCreatePledge(
|
|
|
|
p.owner,
|
|
|
|
p.delegationChain,
|
|
|
|
idReceiver,
|
|
|
|
uint64(_getTime() + _maxCommitTime(p)),
|
|
|
|
p.oldPledge,
|
|
|
|
Pledges.PledgeState.Pledged
|
|
|
|
);
|
|
|
|
_doTransfer(idPledge, toPledge, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `doTransfer` is designed to allow for pledge amounts to be
|
|
|
|
/// shifted around internally.
|
|
|
|
/// @param from This is the id of the pledge from which value will be transfered.
|
|
|
|
/// @param to This is the id of the pledge that value will be transfered to.
|
|
|
|
/// @param _amount The amount of value that will be transfered.
|
|
|
|
function _doTransfer(uint64 from, uint64 to, uint _amount) internal {
|
|
|
|
uint amount = _callPlugins(true, from, to, _amount);
|
|
|
|
if (from == to) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (amount == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pledges.Pledge storage pFrom = _findPledge(from);
|
|
|
|
Pledges.Pledge storage pTo = _findPledge(to);
|
|
|
|
|
|
|
|
require(pFrom.amount >= amount);
|
|
|
|
pFrom.amount -= amount;
|
|
|
|
pTo.amount += amount;
|
|
|
|
|
|
|
|
Transfer(from, to, amount);
|
|
|
|
_callPlugins(false, from, to, amount);
|
|
|
|
}
|
2017-11-23 15:00:28 +00:00
|
|
|
|
|
|
|
/// @notice A getter to find the longest commitTime out of the owner and all
|
|
|
|
/// the delegates for a specified pledge
|
2017-12-05 20:47:38 +00:00
|
|
|
/// @param p The Pledge being queried
|
2017-11-23 15:00:28 +00:00
|
|
|
/// @return The maximum commitTime out of the owner and all the delegates
|
2018-02-10 14:14:52 +00:00
|
|
|
function _maxCommitTime(Pledge p) internal view returns(uint64 commitTime) {
|
|
|
|
PledgeAdmin storage a = _findAdmin(p.owner);
|
|
|
|
commitTime = a.commitTime; // start with the owner's commitTime
|
2017-09-13 12:41:08 +00:00
|
|
|
|
2018-01-25 16:31:13 +00:00
|
|
|
for (uint i = 0; i < p.delegationChain.length; i++) {
|
2018-02-10 14:14:52 +00:00
|
|
|
a = _findAdmin(p.delegationChain[i]);
|
2017-11-23 15:00:28 +00:00
|
|
|
|
|
|
|
// If a delegate's commitTime is longer, make it the new commitTime
|
2018-02-10 14:14:52 +00:00
|
|
|
if (a.commitTime > commitTime) {
|
|
|
|
commitTime = a.commitTime;
|
2018-01-25 16:31:13 +00:00
|
|
|
}
|
2017-09-13 12:41:08 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-18 16:47:22 +00:00
|
|
|
|
2017-11-23 15:00:28 +00:00
|
|
|
/// @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!)
|
2018-02-10 14:14:52 +00:00
|
|
|
function _getOldestPledgeNotCanceled(
|
2018-01-17 01:20:07 +00:00
|
|
|
uint64 idPledge
|
2018-01-19 18:33:58 +00:00
|
|
|
) internal view returns(uint64)
|
2018-01-17 01:20:07 +00:00
|
|
|
{
|
2018-01-25 16:31:13 +00:00
|
|
|
if (idPledge == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2017-11-16 23:15:32 +00:00
|
|
|
|
2018-02-10 14:14:52 +00:00
|
|
|
Pledge storage p = _findPledge(idPledge);
|
|
|
|
PledgeAdmin storage admin = _findAdmin(p.owner);
|
|
|
|
|
|
|
|
if (admin.adminType == PledgeAdminType.Giver) {
|
2018-01-25 16:31:13 +00:00
|
|
|
return idPledge;
|
|
|
|
}
|
2017-11-16 23:15:32 +00:00
|
|
|
|
2018-02-10 14:14:52 +00:00
|
|
|
assert(admin.adminType == PledgeAdminType.Project);
|
|
|
|
if (!_isProjectCanceled(p.owner)) {
|
2018-01-25 16:31:13 +00:00
|
|
|
return idPledge;
|
2017-11-16 23:15:32 +00:00
|
|
|
}
|
2018-01-25 16:31:13 +00:00
|
|
|
|
2018-02-10 14:14:52 +00:00
|
|
|
return _getOldestPledgeNotCanceled(p.oldPledge);
|
2017-11-16 23:15:32 +00:00
|
|
|
}
|
2018-02-12 23:24:26 +00:00
|
|
|
|
|
|
|
/// @notice `callPlugin` is used to trigger the general functions in the
|
|
|
|
/// plugin for any actions needed before and after a transfer happens.
|
|
|
|
/// Specifically what this does in relation to the plugin is something
|
|
|
|
/// that largely depends on the functions of that plugin. This function
|
|
|
|
/// is generally called in pairs, once before, and once after a transfer.
|
|
|
|
/// @param before This toggle determines whether the plugin call is occurring
|
|
|
|
/// before or after a transfer.
|
|
|
|
/// @param adminId This should be the Id of the *trusted* individual
|
|
|
|
/// who has control over this plugin.
|
|
|
|
/// @param fromPledge This is the Id from which value is being transfered.
|
|
|
|
/// @param toPledge This is the Id that value is being transfered to.
|
|
|
|
/// @param context The situation that is triggering the plugin. See plugin
|
|
|
|
/// for a full description of contexts.
|
|
|
|
/// @param amount The amount of value that is being transfered.
|
|
|
|
function _callPlugin(
|
|
|
|
bool before,
|
|
|
|
uint64 adminId,
|
|
|
|
uint64 fromPledge,
|
|
|
|
uint64 toPledge,
|
|
|
|
uint64 context,
|
|
|
|
uint amount
|
|
|
|
) internal returns (uint allowedAmount)
|
|
|
|
{
|
|
|
|
|
|
|
|
uint newAmount;
|
|
|
|
allowedAmount = amount;
|
|
|
|
PledgeAdmins.PledgeAdmin storage admin = _findAdmin(adminId);
|
|
|
|
|
|
|
|
// Checks admin has a plugin assigned and a non-zero amount is requested
|
|
|
|
if (address(admin.plugin) != 0 && allowedAmount > 0) {
|
|
|
|
// There are two seperate functions called in the plugin.
|
|
|
|
// One is called before the transfer and one after
|
|
|
|
if (before) {
|
|
|
|
newAmount = admin.plugin.beforeTransfer(
|
|
|
|
adminId,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
context,
|
|
|
|
amount
|
|
|
|
);
|
|
|
|
require(newAmount <= allowedAmount);
|
|
|
|
allowedAmount = newAmount;
|
|
|
|
} else {
|
|
|
|
admin.plugin.afterTransfer(
|
|
|
|
adminId,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
context,
|
|
|
|
amount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `callPluginsPledge` is used to apply plugin calls to
|
|
|
|
/// the delegate chain and the intended project if there is one.
|
|
|
|
/// It does so in either a transferring or receiving context based
|
|
|
|
/// on the `p` and `fromPledge` parameters.
|
|
|
|
/// @param before This toggle determines whether the plugin call is occuring
|
|
|
|
/// before or after a transfer.
|
|
|
|
/// @param idPledge This is the id of the pledge on which this plugin
|
|
|
|
/// is being called.
|
|
|
|
/// @param fromPledge This is the Id from which value is being transfered.
|
|
|
|
/// @param toPledge This is the Id that value is being transfered to.
|
|
|
|
/// @param amount The amount of value that is being transfered.
|
|
|
|
function _callPluginsPledge(
|
|
|
|
bool before,
|
|
|
|
uint64 idPledge,
|
|
|
|
uint64 fromPledge,
|
|
|
|
uint64 toPledge,
|
|
|
|
uint amount
|
|
|
|
) internal returns (uint allowedAmount)
|
|
|
|
{
|
|
|
|
// Determine if callPlugin is being applied in a receiving
|
|
|
|
// or transferring context
|
|
|
|
uint64 offset = idPledge == fromPledge ? 0 : 256;
|
|
|
|
allowedAmount = amount;
|
|
|
|
Pledges.Pledge storage p = _findPledge(idPledge);
|
|
|
|
|
|
|
|
// Always call the plugin on the owner
|
|
|
|
allowedAmount = _callPlugin(
|
|
|
|
before,
|
|
|
|
p.owner,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
offset,
|
|
|
|
allowedAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
// Apply call plugin to all delegates
|
|
|
|
for (uint64 i = 0; i < p.delegationChain.length; i++) {
|
|
|
|
allowedAmount = _callPlugin(
|
|
|
|
before,
|
|
|
|
p.delegationChain[i],
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
offset + i + 1,
|
|
|
|
allowedAmount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is an intended project also call the plugin in
|
|
|
|
// either a transferring or receiving context based on offset
|
|
|
|
// on the intended project
|
|
|
|
if (p.intendedProject > 0) {
|
|
|
|
allowedAmount = _callPlugin(
|
|
|
|
before,
|
|
|
|
p.intendedProject,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
offset + 255,
|
|
|
|
allowedAmount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @notice `callPlugins` calls `callPluginsPledge` once for the transfer
|
|
|
|
/// context and once for the receiving context. The aggregated
|
|
|
|
/// allowed amount is then returned.
|
|
|
|
/// @param before This toggle determines whether the plugin call is occurring
|
|
|
|
/// before or after a transfer.
|
|
|
|
/// @param fromPledge This is the Id from which value is being transferred.
|
|
|
|
/// @param toPledge This is the Id that value is being transferred to.
|
|
|
|
/// @param amount The amount of value that is being transferred.
|
|
|
|
function _callPlugins(
|
|
|
|
bool before,
|
|
|
|
uint64 fromPledge,
|
|
|
|
uint64 toPledge,
|
|
|
|
uint amount
|
|
|
|
) internal returns (uint allowedAmount)
|
|
|
|
{
|
|
|
|
allowedAmount = amount;
|
|
|
|
|
|
|
|
// Call the pledges plugins in the transfer context
|
|
|
|
allowedAmount = _callPluginsPledge(
|
|
|
|
before,
|
|
|
|
fromPledge,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
allowedAmount
|
|
|
|
);
|
|
|
|
|
|
|
|
// Call the pledges plugins in the receive context
|
|
|
|
allowedAmount = _callPluginsPledge(
|
|
|
|
before,
|
|
|
|
toPledge,
|
|
|
|
fromPledge,
|
|
|
|
toPledge,
|
|
|
|
allowedAmount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////
|
|
|
|
// Test functions
|
|
|
|
/////////////
|
|
|
|
|
|
|
|
/// @notice Basic helper function to return the current time
|
|
|
|
function _getTime() internal view returns (uint) {
|
|
|
|
return now;
|
|
|
|
}
|
2017-06-06 17:40:14 +00:00
|
|
|
}
|