2017-06-06 17:40:14 +00:00
pragma solidity ^ 0 . 4 . 11 ;
2017-10-24 04:09:56 +00:00
2017-10-19 21:49:53 +00:00
/*
2017-10-23 00:04:58 +00:00
Copyright 2017 , Jordi Baylina
2017-12-04 01:12:46 +00:00
Contributors : Adrià Massanet < adria @ codecontext . io > , RJ Ewing , Griff
Green , Arthur Lunn
2017-06-06 17:40:14 +00:00
2017-10-19 21:49:53 +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 .
2017-06-06 17:40:14 +00:00
2017-10-19 21:49:53 +00:00
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-10-19 21:49:53 +00:00
import " ./LiquidPledgingBase.sol " ;
2018-02-07 11:52:08 +00:00
/// @dev `LiquidPledging` allows for liquid pledging through the use of
2017-10-24 04:09:56 +00:00
/// internal id structures and delegate chaining. All basic operations for
/// handling liquid pledging are supplied as well as plugin features
/// to allow for expanded functionality.
2017-06-06 17:40:14 +00:00
contract LiquidPledging is LiquidPledgingBase {
2017-12-04 01:12:46 +00:00
/// @notice This is how value enters the system and how pledges are created;
/// the ether is sent to the vault, an pledge for the Giver is created (or
/// found), the amount of ETH donated in wei is added to the `amount` in
/// the Giver's Pledge, and an LP transfer is done to the idReceiver for
/// the full amount
/// @param idGiver The id of the Giver donating; if 0, a new id is created
/// @param idReceiver The Admin receiving the donation; can be any Admin:
/// the Giver themselves, another Giver, a Delegate or a Project
2018-02-12 22:55:11 +00:00
function donate ( uint64 idGiver , uint64 idReceiver )
2018-02-10 14:14:52 +00:00
public payable
{
2017-10-03 10:20:23 +00:00
if ( idGiver == 0 ) {
2017-12-04 01:12:46 +00:00
// default to a 3 day (259200 seconds) commitTime
2018-01-17 01:20:07 +00:00
idGiver = uint64 ( addGiver ( " " , " " , 259200 , ILiquidPledgingPlugin ( 0x0 ) ) ) ;
2017-09-28 15:49:10 +00:00
}
2018-02-10 14:14:52 +00:00
PledgeAdmins . PledgeAdmin storage sender = _findAdmin ( idGiver ) ;
require ( sender . adminType == PledgeAdminType . Giver ) ;
2018-02-12 22:55:11 +00:00
require ( canPerform ( msg . sender , PLEDGE_ADMIN_ROLE , arr ( uint ( idGiver ) ) ) ) ;
2018-01-17 01:20:07 +00:00
2017-06-06 17:40:14 +00:00
uint amount = msg . value ;
2017-07-13 17:12:45 +00:00
require ( amount > 0 ) ;
2018-02-12 22:55:11 +00:00
// Sends the `msg.value` (in wei) to the `vault`
// b/c the vault is a proxy, send & transfer will fail since they only provide 2300
// gas, and the delegateProxy will sub(gas, 10000) before even making the call
require ( vault . call . value ( amount ) . gas ( 16000 ) ( ) ) ;
2018-01-17 01:20:07 +00:00
2018-02-10 14:14:52 +00:00
uint64 idPledge = _findOrCreatePledge (
2017-10-03 10:20:23 +00:00
idGiver ,
2017-12-04 01:12:46 +00:00
new uint64 [ ] ( 0 ) , // Creates empty array for delegationChain
2017-06-06 17:40:14 +00:00
0 ,
0 ,
0 ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Pledged
2017-10-23 00:04:58 +00:00
) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
Pledges . Pledge storage pTo = _findPledge ( idPledge ) ;
pTo . amount += amount ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
Transfer ( 0 , idPledge , amount ) ; // An event
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
transfer ( idGiver , idPledge , amount , idReceiver ) ; // LP accounting
2017-06-06 17:40:14 +00:00
}
2018-01-17 01:20:07 +00:00
/// @notice Transfers amounts between pledges for internal accounting
2017-12-04 01:12:46 +00:00
/// @param idSender Id of the Admin that is transferring the amount from
/// Pledge to Pledge; this admin must have permissions to move the value
2017-10-03 12:42:21 +00:00
/// @param idPledge Id of the pledge that's moving the value
2017-12-04 01:12:46 +00:00
/// @param amount Quantity of ETH (in wei) that this pledge is transferring
/// the authority to withdraw from the vault
2017-12-04 20:33:15 +00:00
/// @param idReceiver Destination of the `amount`, can be a Giver/Project sending
/// to a Giver, a Delegate or a Project; a Delegate sending to another
2017-12-04 01:12:46 +00:00
/// Delegate, or a Delegate pre-commiting it to a Project
function transfer (
2017-10-23 00:04:58 +00:00
uint64 idSender ,
uint64 idPledge ,
uint amount ,
uint64 idReceiver
2018-02-10 14:14:52 +00:00
) authP ( PLEDGE_ADMIN_ROLE , arr ( uint ( idSender ) , amount ) ) public
2018-01-25 16:31:13 +00:00
{
2018-02-10 14:14:52 +00:00
idPledge = normalizePledge ( idPledge ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
PledgeAdmins . PledgeAdmin storage receiver = _findAdmin ( idReceiver ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
require ( p . pledgeState == PledgeState . Pledged ) ;
2017-06-06 17:40:14 +00:00
2017-12-04 01:12:46 +00:00
// If the sender is the owner of the Pledge
2017-12-05 20:47:38 +00:00
if ( p . owner == idSender ) {
2017-12-05 20:55:57 +00:00
2018-02-10 14:14:52 +00:00
if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Giver ) {
_transferOwnershipToGiver ( idPledge , amount , idReceiver ) ;
} else if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Project ) {
_transferOwnershipToProject ( idPledge , amount , idReceiver ) ;
} else if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Delegate ) {
2017-11-10 16:39:58 +00:00
2018-02-10 14:14:52 +00:00
uint recieverDIdx = _getDelegateIdx ( p , idReceiver ) ;
2017-12-05 21:10:15 +00:00
if ( p . intendedProject > 0 && recieverDIdx != NOTFOUND ) {
2017-11-10 16:39:58 +00:00
// if there is an intendedProject and the receiver is in the delegationChain,
// then we want to preserve the delegationChain as this is a veto of the
// intendedProject by the owner
2017-12-05 21:10:15 +00:00
if ( recieverDIdx == p . delegationChain . length - 1 ) {
2018-02-10 14:14:52 +00:00
uint64 toPledge = _findOrCreatePledge (
2017-12-05 21:10:15 +00:00
p . owner ,
p . delegationChain ,
2017-11-10 16:39:58 +00:00
0 ,
0 ,
2017-12-05 21:10:15 +00:00
p . oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Pledged ) ;
2018-02-10 14:14:52 +00:00
_doTransfer ( idPledge , toPledge , amount ) ;
2017-11-10 16:39:58 +00:00
} else {
2018-02-10 14:14:52 +00:00
_undelegate ( idPledge , amount , p . delegationChain . length - receiverDIdx - 1 ) ;
2017-11-10 16:39:58 +00:00
}
} else {
2017-12-05 20:23:56 +00:00
// owner is not vetoing an intendedProject and is transferring the pledge to a delegate,
// so we want to reset the delegationChain
2018-02-12 23:24:26 +00:00
idPledge = _undelegate (
2018-02-10 14:14:52 +00:00
idPledge ,
2017-12-05 21:10:15 +00:00
amount ,
p . delegationChain . length
) ;
2018-02-10 14:14:52 +00:00
_appendDelegate ( idPledge , amount , idReceiver ) ;
2017-11-10 16:39:58 +00:00
}
2018-01-17 01:20:07 +00:00
2017-06-06 17:40:14 +00:00
} else {
2017-12-04 20:33:15 +00:00
// This should never be reached as the reciever.adminType
// should always be either a Giver, Project, or Delegate
assert ( false ) ;
2017-06-06 17:40:14 +00:00
}
return ;
}
2017-12-04 01:12:46 +00:00
// If the sender is a Delegate
2018-02-10 14:14:52 +00:00
uint senderDIdx = _getDelegateIdx ( p , idSender ) ;
2017-06-06 17:40:14 +00:00
if ( senderDIdx != NOTFOUND ) {
2017-12-04 01:12:46 +00:00
// And the receiver is another Giver
2018-02-10 14:14:52 +00:00
if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Giver ) {
2017-12-04 20:33:15 +00:00
// Only transfer to the Giver who owns the pldege
2017-12-05 20:47:38 +00:00
assert ( p . owner == idReceiver ) ;
2018-02-10 14:14:52 +00:00
_undelegate ( idPledge , amount , p . delegationChain . length ) ;
2017-06-06 17:40:14 +00:00
return ;
}
2017-12-04 01:12:46 +00:00
// And the receiver is another Delegate
2018-02-10 14:14:52 +00:00
if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Delegate ) {
uint receiverDIdx = _getDelegateIdx ( p , idReceiver ) ;
2017-07-09 17:04:52 +00:00
2017-12-04 01:12:46 +00:00
// And not in the delegationChain
2017-06-06 17:40:14 +00:00
if ( receiverDIdx == NOTFOUND ) {
2018-02-10 14:14:52 +00:00
idPledge = _undelegate (
idPledge ,
2017-10-23 00:04:58 +00:00
amount ,
2017-12-05 20:47:38 +00:00
p . delegationChain . length - senderDIdx - 1
2017-10-23 00:04:58 +00:00
) ;
2018-02-10 14:14:52 +00:00
_appendDelegate ( idPledge , amount , idReceiver ) ;
2017-07-09 17:04:52 +00:00
2017-12-04 01:12:46 +00:00
// And part of the delegationChain 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 delegationChain
2017-06-06 17:40:14 +00:00
} else if ( receiverDIdx > senderDIdx ) {
2018-02-10 14:14:52 +00:00
idPledge = _undelegate (
idPledge ,
2017-10-23 00:04:58 +00:00
amount ,
2017-12-05 20:47:38 +00:00
p . delegationChain . length - senderDIdx - 1
2017-10-23 00:04:58 +00:00
) ;
2018-02-10 14:14:52 +00:00
_appendDelegate ( idPledge , amount , idReceiver ) ;
2017-07-09 17:04:52 +00:00
2017-12-04 01:12:46 +00:00
// And is already part of the delegate chain but is before the
// sender, then the sender and all of the other delegates after
2018-01-17 01:20:07 +00:00
// the RECEIVER are removed from the delegationChain
} 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?
2018-02-10 14:14:52 +00:00
_undelegate (
idPledge ,
2017-10-23 00:04:58 +00:00
amount ,
2017-12-05 20:47:38 +00:00
p . delegationChain . length - receiverDIdx - 1
2017-10-23 00:04:58 +00:00
) ;
2017-06-06 17:40:14 +00:00
}
return ;
}
2017-12-04 01:12:46 +00:00
// And the receiver is a Project, all the delegates after the sender
// are removed and the amount is pre-committed to the project
2018-02-10 14:14:52 +00:00
if ( receiver . adminType == PledgeAdmins . PledgeAdminType . Project ) {
idPledge = _undelegate (
idPledge ,
2017-10-23 00:04:58 +00:00
amount ,
2017-12-05 20:47:38 +00:00
p . delegationChain . length - senderDIdx - 1
2017-10-23 00:04:58 +00:00
) ;
2018-02-10 14:14:52 +00:00
_proposeAssignProject ( idPledge , amount , idReceiver ) ;
2017-06-06 17:40:14 +00:00
return ;
}
}
2018-01-17 01:20:07 +00:00
assert ( false ) ; // When the sender is not an owner or a delegate
2017-06-06 17:40:14 +00:00
}
2017-12-04 01:12:46 +00:00
/// @notice Authorizes a payment be made from the `vault` can be used by the
2017-12-04 20:33:15 +00:00
/// Giver to veto a pre-committed donation from a Delegate to an
/// intendedProject
2017-12-09 23:24:47 +00:00
/// @param idPledge Id of the pledge that is to be redeemed into ether
2017-12-04 01:12:46 +00:00
/// @param amount Quantity of ether (in wei) to be authorized
2018-02-12 22:55:11 +00:00
function withdraw ( uint64 idPledge , uint amount ) public {
2018-02-10 14:14:52 +00:00
idPledge = normalizePledge ( idPledge ) ; // Updates pledge info
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
require ( p . pledgeState == PledgeState . Pledged ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
PledgeAdmins . PledgeAdmin storage owner = _findAdmin ( p . owner ) ;
2018-02-12 22:55:11 +00:00
require ( canPerform ( msg . sender , PLEDGE_ADMIN_ROLE , arr ( uint ( p . owner ) ) ) ) ;
2018-02-10 14:14:52 +00:00
uint64 idNewPledge = _findOrCreatePledge (
2017-12-05 20:47:38 +00:00
p . owner ,
p . delegationChain ,
2017-06-06 17:40:14 +00:00
0 ,
0 ,
2017-12-05 20:47:38 +00:00
p . oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Paying
2017-06-06 17:40:14 +00:00
) ;
2018-02-10 14:14:52 +00:00
_doTransfer ( idPledge , idNewPledge , amount ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
vault . authorizePayment ( bytes32 ( idNewPledge ) , owner . addr , amount ) ;
2017-06-06 17:40:14 +00:00
}
2018-01-19 18:33:58 +00:00
/// @notice `onlyVault` Confirms a withdraw request changing the Pledges.PledgeState
2017-12-09 23:24:47 +00:00
/// from Paying to Paid
/// @param idPledge Id of the pledge that is to be withdrawn
/// @param amount Quantity of ether (in wei) to be withdrawn
2018-01-15 22:36:17 +00:00
function confirmPayment ( uint64 idPledge , uint amount ) public onlyVault {
2018-02-10 14:14:52 +00:00
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
2017-06-06 17:40:14 +00:00
2018-01-19 18:33:58 +00:00
require ( p . pledgeState == Pledges . PledgeState . Paying ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
uint64 idNewPledge = _findOrCreatePledge (
2017-12-05 20:47:38 +00:00
p . owner ,
p . delegationChain ,
2017-06-06 17:40:14 +00:00
0 ,
0 ,
2017-12-05 20:47:38 +00:00
p . oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Paid
2017-06-06 17:40:14 +00:00
) ;
2018-02-10 14:14:52 +00:00
_doTransfer ( idPledge , idNewPledge , amount ) ;
2017-06-06 17:40:14 +00:00
}
2018-01-19 18:33:58 +00:00
/// @notice `onlyVault` Cancels a withdraw request, changing the Pledges.PledgeState
2017-12-09 23:24:47 +00:00
/// from Paying back to Pledged
/// @param idPledge Id of the pledge that's withdraw is to be canceled
/// @param amount Quantity of ether (in wei) to be canceled
2018-01-15 22:36:17 +00:00
function cancelPayment ( uint64 idPledge , uint amount ) public onlyVault {
2018-02-10 14:14:52 +00:00
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
2017-06-06 17:40:14 +00:00
2018-01-24 17:57:03 +00:00
require ( p . pledgeState == Pledges . PledgeState . Paying ) ;
2017-06-06 17:40:14 +00:00
2017-10-04 23:27:23 +00:00
// When a payment is canceled, never is assigned to a project.
2018-02-10 14:14:52 +00:00
uint64 idOldPledge = _findOrCreatePledge (
2017-12-05 20:47:38 +00:00
p . owner ,
p . delegationChain ,
2017-06-06 17:40:14 +00:00
0 ,
0 ,
2017-12-05 20:47:38 +00:00
p . oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Pledged
2017-06-06 17:40:14 +00:00
) ;
2018-02-10 14:14:52 +00:00
idOldPledge = normalizePledge ( idOldPledge ) ;
2017-06-06 17:40:14 +00:00
2018-02-10 14:14:52 +00:00
_doTransfer ( idPledge , idOldPledge , amount ) ;
2017-06-06 17:40:14 +00:00
}
2017-12-09 23:24:47 +00:00
/// @notice Changes the `project.canceled` flag to `true`; cannot be undone
/// @param idProject Id of the project that is to be canceled
2018-02-10 14:14:52 +00:00
function cancelProject ( uint64 idProject ) authP ( PLEDGE_ADMIN_ROLE , arr ( uint ( idProject ) ) ) public {
PledgeAdmins . PledgeAdmin storage project = _findAdmin ( idProject ) ;
// _checkAdminOwner(project);
project . canceled = true ;
2018-01-25 16:31:13 +00:00
CancelProject ( idProject ) ;
2017-06-06 17:40:14 +00:00
}
2017-12-09 23:24:47 +00:00
/// @notice Transfers `amount` in `idPledge` back to the `oldPledge` that
/// that sent it there in the first place, a Ctrl-z
/// @param idPledge Id of the pledge that is to be canceled
/// @param amount Quantity of ether (in wei) to be transfered to the
/// `oldPledge`
2018-02-12 23:24:26 +00:00
function cancelPledge ( uint64 idPledge , uint amount ) public {
2018-02-10 14:14:52 +00:00
idPledge = normalizePledge ( idPledge ) ;
2017-09-18 13:43:09 +00:00
2018-02-10 14:14:52 +00:00
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
2017-12-05 20:47:38 +00:00
require ( p . oldPledge != 0 ) ;
2017-09-18 13:43:09 +00:00
2018-02-12 22:55:11 +00:00
require ( canPerform ( msg . sender , PLEDGE_ADMIN_ROLE , arr ( uint ( p . owner ) ) ) ) ;
2017-09-18 13:43:09 +00:00
2018-02-10 14:14:52 +00:00
uint64 oldPledge = _getOldestPledgeNotCanceled ( p . oldPledge ) ;
_doTransfer ( idPledge , oldPledge , amount ) ;
2017-09-18 13:43:09 +00:00
}
2017-06-06 17:40:14 +00:00
////////
2017-10-03 12:42:21 +00:00
// Multi pledge methods
2017-06-06 17:40:14 +00:00
////////
2017-10-19 22:40:37 +00:00
// @dev This set of functions makes moving a lot of pledges around much more
2017-07-09 17:04:52 +00:00
// efficient (saves gas) than calling these functions in series
2017-10-19 21:49:53 +00:00
2017-12-10 01:24:39 +00:00
/// @dev Bitmask used for dividing pledge amounts in Multi pledge methods
2017-06-06 17:40:14 +00:00
uint constant D64 = 0x10000000000000000 ;
2017-10-19 21:49:53 +00:00
2017-12-10 01:24:39 +00:00
/// @notice Transfers multiple amounts within multiple Pledges in an
/// efficient single call
/// @param idSender Id of the Admin that is transferring the amounts from
/// all the Pledges; this admin must have permissions to move the value
/// @param pledgesAmounts An array of Pledge amounts and the idPledges with
/// which the amounts are associated; these are extrapolated using the D64
/// bitmask
/// @param idReceiver Destination of the `pledesAmounts`, can be a Giver or
/// Project sending to a Giver, a Delegate or a Project; a Delegate sending
/// to another Delegate, or a Delegate pre-commiting it to a Project
2017-10-23 00:04:58 +00:00
function mTransfer (
uint64 idSender ,
uint [ ] pledgesAmounts ,
uint64 idReceiver
2018-01-25 16:31:13 +00:00
) public
{
2017-10-03 12:42:21 +00:00
for ( uint i = 0 ; i < pledgesAmounts . length ; i ++ ) {
uint64 idPledge = uint64 ( pledgesAmounts [ i ] & ( D64 - 1 ) ) ;
uint amount = pledgesAmounts [ i ] / D64 ;
2017-06-06 17:40:14 +00:00
2017-10-03 12:42:21 +00:00
transfer ( idSender , idPledge , amount , idReceiver ) ;
2017-06-06 17:40:14 +00:00
}
}
2017-12-10 01:24:39 +00:00
/// @notice Authorizes multiple amounts within multiple Pledges to be
/// withdrawn from the `vault` in an efficient single call
/// @param pledgesAmounts An array of Pledge amounts and the idPledges with
/// which the amounts are associated; these are extrapolated using the D64
/// bitmask
2018-01-15 22:36:17 +00:00
function mWithdraw ( uint [ ] pledgesAmounts ) public {
2017-10-03 12:42:21 +00:00
for ( uint i = 0 ; i < pledgesAmounts . length ; i ++ ) {
uint64 idPledge = uint64 ( pledgesAmounts [ i ] & ( D64 - 1 ) ) ;
uint amount = pledgesAmounts [ i ] / D64 ;
2017-06-06 17:40:14 +00:00
2017-10-03 12:42:21 +00:00
withdraw ( idPledge , amount ) ;
2017-06-06 17:40:14 +00:00
}
}
2017-10-23 00:04:58 +00:00
/// @notice `mConfirmPayment` allows for multiple pledges to be confirmed
/// efficiently
2017-11-01 21:03:03 +00:00
/// @param pledgesAmounts An array of pledge amounts and IDs which are extrapolated
2017-10-23 00:04:58 +00:00
/// using the D64 bitmask
2018-01-15 22:36:17 +00:00
function mConfirmPayment ( uint [ ] pledgesAmounts ) public {
2017-10-03 12:42:21 +00:00
for ( uint i = 0 ; i < pledgesAmounts . length ; i ++ ) {
uint64 idPledge = uint64 ( pledgesAmounts [ i ] & ( D64 - 1 ) ) ;
uint amount = pledgesAmounts [ i ] / D64 ;
2017-06-06 17:40:14 +00:00
2017-10-03 12:42:21 +00:00
confirmPayment ( idPledge , amount ) ;
2017-06-06 17:40:14 +00:00
}
}
2017-10-28 08:27:47 +00:00
/// @notice `mCancelPayment` allows for multiple pledges to be canceled
2017-10-23 00:04:58 +00:00
/// efficiently
2017-11-01 21:03:03 +00:00
/// @param pledgesAmounts An array of pledge amounts and IDs which are extrapolated
2017-10-23 00:04:58 +00:00
/// using the D64 bitmask
2018-01-15 22:36:17 +00:00
function mCancelPayment ( uint [ ] pledgesAmounts ) public {
2017-10-03 12:42:21 +00:00
for ( uint i = 0 ; i < pledgesAmounts . length ; i ++ ) {
uint64 idPledge = uint64 ( pledgesAmounts [ i ] & ( D64 - 1 ) ) ;
uint amount = pledgesAmounts [ i ] / D64 ;
2017-06-06 17:40:14 +00:00
2017-10-03 12:42:21 +00:00
cancelPayment ( idPledge , amount ) ;
2017-06-06 17:40:14 +00:00
}
}
2017-10-23 00:04:58 +00:00
/// @notice `mNormalizePledge` allows for multiple pledges to be
/// normalized efficiently
2017-12-03 00:59:30 +00:00
/// @param pledges An array of pledge IDs
2018-01-15 22:36:17 +00:00
function mNormalizePledge ( uint64 [ ] pledges ) public {
2017-10-03 12:42:21 +00:00
for ( uint i = 0 ; i < pledges . length ; i ++ ) {
2017-10-24 17:31:18 +00:00
normalizePledge ( pledges [ i ] ) ;
2017-09-18 13:43:09 +00:00
}
}
2018-01-19 18:33:58 +00:00
/// @notice Only affects pledges with the Pledged Pledges.PledgeState for 2 things:
2017-12-03 04:15:52 +00:00
/// #1: Checks if the pledge should be committed. This means that
/// if the pledge has an intendedProject and it is past the
/// commitTime, it changes the owner to be the proposed project
/// (The UI will have to read the commit time and manually do what
2017-10-23 21:40:51 +00:00
/// this function does to the pledge for the end user
/// at the expiration of the commitTime)
///
/// #2: Checks to make sure that if there has been a cancellation in the
/// chain of projects, the pledge's owner has been changed
/// appropriately.
///
/// This function can be called by anybody at anytime on any pledge.
2017-12-04 01:12:46 +00:00
/// In general it can be called to force the calls of the affected
/// plugins, which also need to be predicted by the UI
2017-10-23 21:40:51 +00:00
/// @param idPledge This is the id of the pledge that will be normalized
2017-12-04 01:12:46 +00:00
/// @return The normalized Pledge!
2018-02-10 14:14:52 +00:00
function normalizePledge ( uint64 idPledge ) public returns ( uint64 ) {
Pledges . Pledge storage p = _findPledge ( idPledge ) ;
2017-07-09 17:04:52 +00:00
2017-10-28 08:27:47 +00:00
// Check to make sure this pledge hasn't already been used
2017-10-24 03:26:31 +00:00
// or is in the process of being used
2018-01-19 18:33:58 +00:00
if ( p . pledgeState != Pledges . PledgeState . Pledged ) {
2018-02-10 14:14:52 +00:00
return idPledge ;
2017-12-03 00:59:30 +00:00
}
2017-06-06 17:40:14 +00:00
2017-10-28 08:27:47 +00:00
// First send to a project if it's proposed and committed
2018-02-10 14:14:52 +00:00
if ( ( p . intendedProject > 0 ) && ( _getTime ( ) > p . commitTime ) ) {
uint64 oldPledge = _findOrCreatePledge (
2017-12-05 20:47:38 +00:00
p . owner ,
p . delegationChain ,
2017-06-06 17:40:14 +00:00
0 ,
0 ,
2017-12-05 20:47:38 +00:00
p . oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Pledged
2017-12-03 00:59:30 +00:00
) ;
2018-02-10 14:14:52 +00:00
uint64 toPledge = _findOrCreatePledge (
2017-12-05 20:47:38 +00:00
p . intendedProject ,
2017-06-06 17:40:14 +00:00
new uint64 [ ] ( 0 ) ,
0 ,
0 ,
2018-02-10 14:14:52 +00:00
oldPledge ,
2018-01-19 18:33:58 +00:00
Pledges . PledgeState . Pledged
2017-12-03 00:59:30 +00:00
) ;
2018-02-10 14:14:52 +00:00
_doTransfer ( idPledge , toPledge , p . amount ) ;
idPledge = toPledge ;
p = _findPledge ( idPledge ) ;
2017-06-06 17:40:14 +00:00
}
2018-02-10 14:14:52 +00:00
toPledge = _getOldestPledgeNotCanceled ( idPledge ) ;
if ( toPledge != idPledge ) {
_doTransfer ( idPledge , toPledge , p . amount ) ;
2017-06-06 17:40:14 +00:00
}
2017-06-26 17:54:28 +00:00
2018-02-10 14:14:52 +00:00
return toPledge ;
2017-06-26 17:54:28 +00:00
}
2017-06-06 17:40:14 +00:00
}