moving things around / cleanup

This commit is contained in:
perissology 2018-02-13 00:24:26 +01:00
parent ece3355c67
commit 4cfebbc5fb
16 changed files with 361 additions and 631 deletions

View File

@ -1,96 +0,0 @@
pragma solidity ^0.4.0;
import "node_modules/giveth-common-contracts/contracts/Escapable.sol";
contract EternalStorage is Escapable {
mapping(bytes32 => uint) UIntStorage;
mapping(bytes32 => int) IntStorage;
mapping(bytes32 => bool) BooleanStorage;
mapping(bytes32 => address) AddressStorage;
mapping(bytes32 => string) StringStorage;
mapping(bytes32 => bytes) BytesStorage;
mapping(bytes32 => bytes32) Bytes32Storage;
function EternalStorage(address _escapeHatchCaller, address _escapeHatchDestination)
Escapable(_escapeHatchCaller, _escapeHatchDestination) public {
}
/// UInt Storage
function getUIntValue(bytes32 record) public view returns (uint) {
return UIntStorage[record];
}
function setUIntValue(bytes32 record, uint value) public onlyOwner {
UIntStorage[record] = value;
}
function incrementUIntValue(bytes32 record) public returns (uint) {
return UIntStorage[record] += 1;
}
/// Int Storage
function getIntValue(bytes32 record) public view returns (int) {
return IntStorage[record];
}
function setIntValue(bytes32 record, int value) public onlyOwner {
IntStorage[record] = value;
}
function incrementIntValue(bytes32 record) public returns (int) {
return IntStorage[record] += int(1);
}
/// Address Storage
function getAddressValue(bytes32 record) public view returns (address) {
return AddressStorage[record];
}
function setAddressValue(bytes32 record, address value) public onlyOwner {
AddressStorage[record] = value;
}
/// String Storage
function getStringValue(bytes32 record) public view returns (string) {
return StringStorage[record];
}
function setStringValue(bytes32 record, string value) public onlyOwner {
StringStorage[record] = value;
}
/// Bytes Storage
function getBytesValue(bytes32 record) public view returns (bytes) {
return BytesStorage[record];
}
function setBytesValue(bytes32 record, bytes value) public onlyOwner {
BytesStorage[record] = value;
}
/// Bytes Storage
function getBytes32Value(bytes32 record) public view returns (bytes32) {
return Bytes32Storage[record];
}
function setBytes32Value(bytes32 record, bytes32 value) public onlyOwner {
Bytes32Storage[record] = value;
}
/// Boolean Storage
function getBooleanValue(bytes32 record) public view returns (bool) {
return BooleanStorage[record];
}
function setBooleanValue(bytes32 record, bool value) public onlyOwner {
BooleanStorage[record] = value;
}
}

View File

@ -1,108 +0,0 @@
pragma solidity ^0.4.0;
import "./EternalStorage.sol";
library EternallyPersistentLib {
// UInt
//TODO if we use assembly here, we can save ~ 600 gas / call, due to skipping the extcodesize check that solidity adds.
function stgObjectGetUInt(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (uint) {
bytes32 record = keccak256(class, id, fieldName);
return _storage.getUIntValue(record);
}
function stgObjectSetUInt(EternalStorage _storage, string class, uint id, string fieldName, uint value) internal {
bytes32 record = keccak256(class, id, fieldName);
return _storage.setUIntValue(record, value);
}
// Boolean
function stgObjectGetBoolean(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (bool) {
bytes32 record = keccak256(class, id, fieldName);
return _storage.getBooleanValue(record);
}
function stgObjectSetBoolean(EternalStorage _storage, string class, uint id, string fieldName, bool value) internal {
bytes32 record = keccak256(class, id, fieldName);
return _storage.setBooleanValue(record, value);
}
// string
function stgObjectGetString(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (string) {
bytes32 record = keccak256(class, id, fieldName);
bytes4 sig = 0xa209a29c; // bytes4(keccak256("getStringValue(bytes32)"));
string memory s;
assembly {
let ptr := mload(0x40) //Find empty storage location using "free memory pointer"
mstore(ptr, sig) //Place signature at beginning of empty storage
mstore(add(ptr, 0x04), record) //Place first argument directly next to signature
let result := staticcall(sub(gas, 10000), _storage, ptr, 0x24, 0, 0)
let size := returndatasize
returndatacopy(ptr, 0, size) // overwrite ptr to save a bit of gas
// revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
// if the call returned error data, forward it
switch result case 0 { revert(ptr, size) }
default {
mstore(0x40, add(ptr, size)) // update free mem location
// We need to skip the first 32 bytes which contains the start offset of the returned byte array
s := add(ptr, 0x20) // set the string
}
}
return s;
}
function stgObjectSetString(EternalStorage _storage, string class, uint id, string fieldName, string value) internal {
bytes32 record = keccak256(class, id, fieldName);
return _storage.setStringValue(record, value);
}
// address
function stgObjectGetAddress(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (address) {
bytes32 record = keccak256(class, id, fieldName);
return _storage.getAddressValue(record);
}
function stgObjectSetAddress(EternalStorage _storage, string class, uint id, string fieldName, address value) internal {
bytes32 record = keccak256(class, id, fieldName);
return _storage.setAddressValue(record, value);
}
// bytes32
function stgObjectGetBytes32(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (bytes32) {
bytes32 record = keccak256(class, id, fieldName);
return _storage.getBytes32Value(record);
}
function stgObjectSetBytes32(EternalStorage _storage, string class, uint id, string fieldName, bytes32 value) internal {
bytes32 record = keccak256(class, id, fieldName);
return _storage.setBytes32Value(record, value);
}
// Array
function stgCollectionAddItem(EternalStorage _storage, bytes32 idArray) internal returns (uint) {
return _storage.incrementUIntValue(keccak256(idArray, "length"));
}
function stgCollectionLength(EternalStorage _storage, bytes32 idArray) internal view returns (uint) {
return _storage.getUIntValue(keccak256(idArray, "length"));
}
function stgCollectionIdFromIdx(EternalStorage _storage, bytes32 idArray, uint idx) internal view returns (bytes32) {
return _storage.getBytes32Value(keccak256(idArray, idx));
}
function stgUpgrade(EternalStorage _storage, address newContract) internal {
_storage.changeOwnership(newContract);
}
}

View File

@ -27,7 +27,6 @@ import "./LiquidPledgingBase.sol";
/// to allow for expanded functionality.
contract LiquidPledging is LiquidPledgingBase {
/// @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
@ -39,7 +38,6 @@ contract LiquidPledging is LiquidPledgingBase {
function donate(uint64 idGiver, uint64 idReceiver)
public payable
{
// TODO: maybe need a separate role here to allow giver creation
if (idGiver == 0) {
// default to a 3 day (259200 seconds) commitTime
idGiver = uint64(addGiver("", "", 259200, ILiquidPledgingPlugin(0x0)));
@ -93,9 +91,7 @@ contract LiquidPledging is LiquidPledgingBase {
Pledges.Pledge storage p = _findPledge(idPledge);
PledgeAdmins.PledgeAdmin storage receiver = _findAdmin(idReceiver);
// PledgeAdmins.PledgeAdmin storage sender = _findAdmin(idSender);
// _checkAdminOwner(sender);
require(p.pledgeState == PledgeState.Pledged);
// If the sender is the owner of the Pledge
@ -128,7 +124,7 @@ contract LiquidPledging is LiquidPledgingBase {
} else {
// owner is not vetoing an intendedProject and is transferring the pledge to a delegate,
// so we want to reset the delegationChain
idPledge = _undelegate(
idPledge = _undelegate(
idPledge,
amount,
p.delegationChain.length
@ -241,7 +237,6 @@ contract LiquidPledging is LiquidPledgingBase {
/// @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) public onlyVault {
//TODO don't fetch entire pledge
Pledges.Pledge storage p = _findPledge(idPledge);
require(p.pledgeState == Pledges.PledgeState.Paying);
@ -297,15 +292,13 @@ contract LiquidPledging is LiquidPledgingBase {
/// @param idPledge Id of the pledge that is to be canceled
/// @param amount Quantity of ether (in wei) to be transfered to the
/// `oldPledge`
function cancelPledge(uint64 idPledge, uint amount) public {//authP(PLEDGE_ADMIN_ROLE, arr(uint(idPledge))) public {
function cancelPledge(uint64 idPledge, uint amount) public {
idPledge = normalizePledge(idPledge);
Pledges.Pledge storage p = _findPledge(idPledge);
require(p.oldPledge != 0);
require(canPerform(msg.sender, PLEDGE_ADMIN_ROLE, arr(uint(p.owner))));
// PledgeAdmins.PledgeAdmin storage a = _findAdmin(p.owner);
// _checkAdminOwner(a);
uint64 oldPledge = _getOldestPledgeNotCanceled(p.oldPledge);
_doTransfer(idPledge, oldPledge, amount);
@ -396,192 +389,6 @@ contract LiquidPledging is LiquidPledgingBase {
}
}
////////
// Private methods
///////
/// @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);
}
/// @notice Only affects pledges with the Pledged Pledges.PledgeState for 2 things:
/// #1: Checks if the pledge should be committed. This means that
/// if the pledge has an intendedProject and it is past the
@ -638,176 +445,4 @@ contract LiquidPledging is LiquidPledgingBase {
return toPledge;
}
/////////////
// Plugins
/////////////
/// @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;
}
function getTime() public view returns(uint) {
return _getTime();
}
// Event Declarations
event Transfer(uint indexed from, uint indexed to, uint amount);
event CancelProject(uint indexed idProject);
}

View File

@ -38,6 +38,10 @@ interface ILPVault {
/// data structures
contract LiquidPledgingBase is PledgeAdmins, Pledges, EscapableApp {
// Event Declarations
event Transfer(uint indexed from, uint indexed to, uint amount);
event CancelProject(uint indexed idProject);
ILPVault public vault;
/////////////
@ -51,7 +55,6 @@ contract LiquidPledgingBase is PledgeAdmins, Pledges, EscapableApp {
_;
}
///////////////
// Constructor
///////////////
@ -99,12 +102,187 @@ contract LiquidPledgingBase is PledgeAdmins, Pledges, EscapableApp {
// Internal methods
////////////////////
/// @notice A check to see if the msg.sender is the owner or the
/// plugin contract for a specific Admin
/// @param a The admin being checked
// function _checkAdminOwner(PledgeAdmin a) internal constant {
// require(msg.sender == a.addr || msg.sender == address(a.plugin));
// }
/// @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);
}
/// @notice A getter to find the longest commitTime out of the owner and all
/// the delegates for a specified pledge
@ -149,4 +327,165 @@ contract LiquidPledgingBase is PledgeAdmins, Pledges, EscapableApp {
return _getOldestPledgeNotCanceled(p.oldPledge);
}
/// @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;
}
}

View File

@ -1,12 +0,0 @@
pragma solidity ^0.4.18;
import "./EternalStorage.sol";
contract LiquidPledgingStorage {
EternalStorage public _storage;
function LiquidPledgingStorage(address _s) public {
_storage = EternalStorage(_s);
}
}

View File

@ -1,4 +1,4 @@
exports.LiquidPledging = require('./lib/liquidPledging.js');
exports.LiquidPledgingMock = require('./lib/liquidPledgingMock.js');
const contracts = require('./build/contracts');
exports.LiquidPledging = contracts.LiquidPledging;
exports.LiquidPledgingState = require('./lib/liquidPledgingState.js');
exports.LPVault = require('./lib/vault.js');
exports.LPVault = contracts.LPVault;

View File

@ -1,6 +0,0 @@
const EternalStorageAbi = require('../build/EternalStorage.sol').EternalStorageAbi;
const EternalStorageCode = require('../build/EternalStorage.sol').EternalStorageByteCode;
const generateClass = require('eth-contract-class').default;
module.exports = generateClass(EternalStorageAbi, EternalStorageCode);

View File

@ -1,6 +0,0 @@
const LiquidPledgingAbi = require('../build/LiquidPledging.sol').LiquidPledgingAbi;
const LiquidPledgingCode = require('../build/LiquidPledging.sol').LiquidPledgingByteCode;
const generateClass = require('eth-contract-class').default;
module.exports = generateClass(LiquidPledgingAbi, LiquidPledgingCode);

View File

@ -1,5 +0,0 @@
const LiquidPledgingMockAbi = require('../build/LiquidPledgingMock.sol').LiquidPledgingMockAbi;
const LiquidPledgingMockCode = require('../build/LiquidPledgingMock.sol').LiquidPledgingMockByteCode;
const generateClass = require('eth-contract-class').default;
module.exports = generateClass(LiquidPledgingMockAbi, LiquidPledgingMockCode);

View File

@ -1,5 +0,0 @@
const LPVaultAbi = require('../build/LPVault.sol').LPVaultAbi;
const LPVaultByteCode = require('../build/LPVault.sol').LPVaultByteCode;
const generateClass = require('eth-contract-class').default;
module.exports = generateClass(LPVaultAbi, LPVaultByteCode);

View File

@ -32,14 +32,13 @@ describe('LiquidPledging plugins test', function () {
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 10,
});
testrpc.listen(8546, '127.0.0.1');
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8546');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[1];
adminProject1 = accounts[2];

View File

@ -29,14 +29,13 @@ describe('LiquidPledging cancelPledge normal scenario', function () {
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 10,
});
testrpc.listen(8546, '127.0.0.1');
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8546');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[ 1 ];
adminProject1 = accounts[ 2 ];

View File

@ -33,14 +33,13 @@ describe('DelegationChain test', function () {
const gasUsage = {};
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 10,
});
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8545');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[1];
delegate1 = accounts[2];

View File

@ -39,14 +39,13 @@ describe('LiquidPledging test', function () {
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 11,
});
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8545');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[1];
delegate1 = accounts[2];

View File

@ -31,14 +31,13 @@ describe('NormalizePledge test', function () {
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 10,
});
testrpc.listen(8546, '127.0.0.1');
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8546');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[1];
delegate1 = accounts[2];

View File

@ -27,14 +27,13 @@ describe('Vault test', function () {
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 6700000,
total_accounts: 10,
});
testrpc.listen(8546, '127.0.0.1');
testrpc.listen(8545, '127.0.0.1');
web3 = new Web3('ws://localhost:8546');
web3 = new Web3('http://localhost:8545');
accounts = await web3.eth.getAccounts();
giver1 = accounts[ 1 ];
adminProject1 = accounts[ 2 ];