This commit is contained in:
perissology 2018-02-07 12:52:08 +01:00
parent a79bb5d693
commit 6cdceb62cf
5 changed files with 42 additions and 75 deletions

View File

@ -26,6 +26,10 @@ contract EternalStorage is Escapable {
UIntStorage[record] = value;
}
function incrementUIntValue(bytes32 record) public returns (uint) {
return UIntStorage[record] += 1;
}
/// Int Storage
function getIntValue(bytes32 record) public view returns (int) {
@ -36,6 +40,10 @@ contract EternalStorage is Escapable {
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) {

View File

@ -33,47 +33,27 @@ library EternallyPersistentLib {
function stgObjectGetString(EternalStorage _storage, string class, uint id, string fieldName) internal view returns (string) {
bytes32 record = keccak256(class, id, fieldName);
//Function signature
bytes4 sig = bytes4(keccak256("getStringValue(bytes32)"));
bytes4 sig = 0xa209a29c; // bytes4(keccak256("getStringValue(bytes32)"));
string memory s;
assembly {
let x := mload(0x40) //Find empty storage location using "free memory pointer"
mstore(x, sig) //Place signature at beginning of empty storage
mstore(add(x, 0x04), record) //Place first argument directly next to signature
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 success := call(//This is the critical change (Pop the top stack value)
5000, //5k gas
_storage, //To addr
0, //No value
x, //Inputs are stored at location x
0x24, //Inputs are 36 byes long
x, //Store output over input (saves space)
0x80) //Outputs are 32 bytes long
let result := staticcall(sub(gas, 10000), _storage, ptr, 0x24, 0, 0)
let strL := mload(add(x, 0x20)) // Load the length of the string
let size := returndatasize
returndatacopy(ptr, 0, size) // overwrite ptr to save a bit of gas
jumpi(ask_more, gt(strL, 64))
mstore(0x40, add(x, add(strL, 0x40)))
s := add(x, 0x20)
ask_more :
mstore(x, sig) //Place signature at beginning of empty storage
mstore(add(x, 0x04), record) //Place first argument directly next to signature
success := call(//This is the critical change (Pop the top stack value)
5000, //5k gas
_storage, //To addr
0, //No value
x, //Inputs are stored at location x
0x24, //Inputs are 36 byes long
x, //Store output over input (saves space)
add(0x40, strL)) //Outputs are 32 bytes long
mstore(0x40, add(x, add(strL, 0x40)))
s := add(x, 0x20)
// 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;
@ -111,13 +91,7 @@ library EternallyPersistentLib {
// Array
function stgCollectionAddItem(EternalStorage _storage, bytes32 idArray) internal returns (uint) {
uint length = _storage.getUIntValue(keccak256(idArray, "length"));
// Increment the size of the array
length++;
_storage.setUIntValue(keccak256(idArray, "length"), length);
return length;
return _storage.incrementUIntValue(keccak256(idArray, "length"));
}
function stgCollectionLength(EternalStorage _storage, bytes32 idArray) internal view returns (uint) {

View File

@ -21,7 +21,7 @@ pragma solidity ^0.4.11;
import "./LiquidPledgingBase.sol";
/// @dev `LiquidPleding` allows for liquid pledging through the use of
/// @dev `LiquidPledging` allows for liquid pledging through the use of
/// 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.
@ -106,9 +106,8 @@ contract LiquidPledging is LiquidPledgingBase {
{
checkAdminOwner(idSender);
idPledge = normalizePledge(idPledge);
Pledges.Pledge memory p = normalizePledge(idPledge);
Pledges.Pledge memory p = findPledge(idPledge);
PledgeAdminType receiverAdminType = getAdminType(idReceiver);
require(p.pledgeState == Pledges.PledgeState.Pledged);
@ -229,8 +228,8 @@ contract LiquidPledging is LiquidPledgingBase {
/// @param idPledge Id of the pledge that is to be redeemed into ether
/// @param amount Quantity of ether (in wei) to be authorized
function withdraw(uint64 idPledge, uint amount) public {
idPledge = normalizePledge(idPledge); // Updates pledge info
Pledges.Pledge memory p = findPledge(idPledge);
Pledges.Pledge memory p = normalizePledge(idPledge); // Updates pledge info
// = findPledge(idPledge);
require(p.pledgeState == Pledges.PledgeState.Pledged);
checkAdminOwner(p.owner);
@ -289,7 +288,7 @@ contract LiquidPledging is LiquidPledgingBase {
Pledges.PledgeState.Pledged
);
oldPledge = normalizePledge(oldPledge);
oldPledge = _normalizePledge(oldPledge);
doTransfer(p, oldPledge, amount);
}
@ -310,9 +309,10 @@ contract LiquidPledging is LiquidPledgingBase {
/// `oldPledge`
function cancelPledge(uint64 idPledge, uint amount) public {
//TODO fetch idPledge? OR return Pledge from this call?
idPledge = normalizePledge(idPledge);
// idPledge = normalizePledge(idPledge);
Pledges.Pledge memory p = findPledge(idPledge);
// Pledges.Pledge memory p = findPledge(idPledge);
Pledges.Pledge memory p = normalizePledge(idPledge);
require(p.oldPledge != 0);
checkAdminOwner(p.owner);
@ -604,12 +604,12 @@ contract LiquidPledging is LiquidPledgingBase {
/// plugins, which also need to be predicted by the UI
/// @param idPledge This is the id of the pledge that will be normalized
/// @return The normalized Pledge!
function normalizePledge(uint64 idPledge) public returns(uint64) {
function normalizePledge(uint64 idPledge) public returns(Pledges.Pledge) {
Pledges.Pledge memory p = findPledge(idPledge);
return uint64(normalizePledge(p).id);
return _normalizePledge(p);
}
function normalizePledge(Pledges.Pledge p) internal returns(Pledges.Pledge) {
function _normalizePledge(Pledges.Pledge p) internal returns(Pledges.Pledge) {
// Check to make sure this pledge hasn't already been used
// or is in the process of being used

View File

@ -97,7 +97,7 @@ contract LiquidPledgingBase is LiquidPledgingStorage, PledgeAdmins, Pledges, Esc
/// plugin contract for a specific Admin
/// @param idAdmin The id of the admin being checked
function checkAdminOwner(uint idAdmin) internal constant {
require(msg.sender == getAdminPlugin(idAdmin) || msg.sender == getAdminAddr(idAdmin));
require(msg.sender == getAdminAddr(idAdmin) || msg.sender == getAdminPlugin(idAdmin));
}
/// @notice A getter to find the longest commitTime out of the owner and all

View File

@ -1,6 +1,6 @@
/* eslint-env mocha */
/* eslint-disable no-await-in-loop */
const TestRPC = require("ganache-cli");
const TestRPC = require('ganache-cli');
const Web3 = require('web3');
const chai = require('chai');
const liquidpledging = require('../index.js');
@ -341,26 +341,11 @@ describe('LiquidPledging test', function () {
it('should throw if projectLevel > 20', async () => {
let nAdmins = await liquidPledging.numberOfPledgeAdmins();
await liquidPledging.addProject('ProjectLevel1', '', adminProject1, 0, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel2', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel3', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel4', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel5', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel6', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel7', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel8', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel9', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel10', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel11', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel12', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel13', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel14', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel15', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel16', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel17', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel18', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel19', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel20', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
await liquidPledging.addProject('ProjectLevel0', '', adminProject1, 0, 86400, 0, { from: adminProject1 });
for (let i = 2; i <= 20; i++) {
await liquidPledging.addProject(`ProjectLevel${i}`, '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1 });
}
assertFail(
liquidPledging.addProject('ProjectLevel21', '', adminProject1, ++nAdmins, 86400, 0, { from: adminProject1, gas: 4000000 })