parent
84be690f03
commit
8b629d3bd7
|
@ -1,6 +1,7 @@
|
|||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./ILiquidPledgingPlugin.sol";
|
||||
import "../node_modules/giveth-common-contracts/contracts/Owned.sol";
|
||||
|
||||
/// @dev This is declares a few functions from `Vault` so that the
|
||||
/// `LiquidPledgingBase` contract can interface with the `Vault` contract
|
||||
|
@ -9,7 +10,7 @@ contract Vault {
|
|||
function () payable;
|
||||
}
|
||||
|
||||
contract LiquidPledgingBase {
|
||||
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;
|
||||
|
@ -47,6 +48,9 @@ contract LiquidPledgingBase {
|
|||
|
||||
// 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
|
||||
mapping (bytes32 => bool) pluginWhitelist;
|
||||
|
||||
bool public usePluginWhitelist = true;
|
||||
|
||||
|
||||
/////
|
||||
|
@ -73,12 +77,13 @@ contract LiquidPledgingBase {
|
|||
|
||||
|
||||
///////
|
||||
// Adminss functions
|
||||
// Admin functions
|
||||
//////
|
||||
|
||||
/// @notice Creates a giver.
|
||||
function addGiver(string name, string url, uint64 commitTime, ILiquidPledgingPlugin plugin
|
||||
) returns (uint64 idGiver) {
|
||||
require(isValidPlugin(plugin));
|
||||
|
||||
idGiver = uint64(admins.length);
|
||||
|
||||
|
@ -119,6 +124,7 @@ contract LiquidPledgingBase {
|
|||
|
||||
/// @notice Creates a new Delegate
|
||||
function addDelegate(string name, string url, uint64 commitTime, ILiquidPledgingPlugin plugin) returns (uint64 idDelegate) { //TODO return index number
|
||||
require(isValidPlugin(plugin));
|
||||
|
||||
idDelegate = uint64(admins.length);
|
||||
|
||||
|
@ -158,6 +164,8 @@ contract LiquidPledgingBase {
|
|||
|
||||
/// @notice Creates a new Project
|
||||
function addProject(string name, string url, address projectAdmin, uint64 parentProject, uint64 commitTime, ILiquidPledgingPlugin plugin) returns (uint64 idProject) {
|
||||
require(isValidPlugin(plugin));
|
||||
|
||||
if (parentProject != 0) {
|
||||
PledgeAdmin storage pa = findAdmin(parentProject);
|
||||
require(pa.adminType == PledgeAdminType.Project);
|
||||
|
@ -373,4 +381,46 @@ contract LiquidPledgingBase {
|
|||
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;
|
||||
}
|
||||
|
||||
function removeValidPlugin(bytes32 contractHash) external onlyOwner {
|
||||
pluginWhitelist[contractHash] = false;
|
||||
}
|
||||
|
||||
function useWhitelist(bool useWhitelist) external onlyOwner {
|
||||
usePluginWhitelist = useWhitelist;
|
||||
}
|
||||
|
||||
function isValidPlugin(address addr) public returns(bool) {
|
||||
if (!usePluginWhitelist || addr == 0x0) return true;
|
||||
|
||||
bytes32 contractHash = getCodeHash(addr);
|
||||
|
||||
return pluginWhitelist[contractHash];
|
||||
}
|
||||
|
||||
function getCodeHash(address addr) public returns(bytes32) {
|
||||
bytes memory o_code;
|
||||
assembly {
|
||||
// retrieve the size of the code, this needs assembly
|
||||
let size := extcodesize(addr)
|
||||
// allocate output byte array - this could also be done without assembly
|
||||
// by using o_code = new bytes(size)
|
||||
o_code := mload(0x40)
|
||||
// new "memory end" including padding
|
||||
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||
// store length in memory
|
||||
mstore(o_code, size)
|
||||
// actually retrieve the code, this needs assembly
|
||||
extcodecopy(addr, add(o_code, 0x20), 0, size)
|
||||
}
|
||||
return keccak256(o_code);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
pragma solidity ^0.4.11;
|
||||
|
||||
import "../LiquidPledging.sol";
|
||||
|
||||
// simple liquidPledging plugin contract for testing whitelist
|
||||
contract TestSimpleProjectPlugin {
|
||||
|
||||
uint64 public idProject;
|
||||
bool initPending;
|
||||
|
||||
event BeforeTransfer(uint64 pledgeAdmin, uint64 pledgeFrom, uint64 pledgeTo, uint64 context, uint amount);
|
||||
event AfterTransfer(uint64 pledgeAdmin, uint64 pledgeFrom, uint64 pledgeTo, uint64 context, uint amount);
|
||||
|
||||
function TestSimpleProjectPlugin() {
|
||||
require(msg.sender != tx.origin); // Avoids being created directly by mistake.
|
||||
initPending = true;
|
||||
}
|
||||
|
||||
function init(
|
||||
LiquidPledging liquidPledging,
|
||||
string name,
|
||||
string url,
|
||||
uint64 parentProject
|
||||
) {
|
||||
require(initPending);
|
||||
idProject = liquidPledging.addProject(name, url, address(this), parentProject, 0, ILiquidPledgingPlugin(this));
|
||||
initPending = false;
|
||||
}
|
||||
|
||||
function beforeTransfer(
|
||||
uint64 pledgeAdmin,
|
||||
uint64 pledgeFrom,
|
||||
uint64 pledgeTo,
|
||||
uint64 context,
|
||||
uint amount
|
||||
) external returns (uint maxAllowed) {
|
||||
require(!initPending);
|
||||
BeforeTransfer(pledgeAdmin, pledgeFrom, pledgeTo, context, amount);
|
||||
}
|
||||
|
||||
function afterTransfer(
|
||||
uint64 pledgeAdmin,
|
||||
uint64 pledgeFrom,
|
||||
uint64 pledgeTo,
|
||||
uint64 context,
|
||||
uint amount
|
||||
) external {
|
||||
require(!initPending);
|
||||
AfterTransfer(pledgeAdmin, pledgeFrom, pledgeTo, context, amount);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
pragma solidity ^0.4.11;
|
||||
|
||||
import "./TestSimpleProjectPlugin.sol";
|
||||
import "../LiquidPledging.sol";
|
||||
|
||||
// simple factory for deploying TestSimpleProjectPlugin.sol contract
|
||||
contract TestSimpleProjectPluginFactory {
|
||||
|
||||
function deploy(
|
||||
LiquidPledging liquidPledging,
|
||||
string name,
|
||||
string url,
|
||||
uint64 parentProject
|
||||
) {
|
||||
TestSimpleProjectPlugin p = new TestSimpleProjectPlugin();
|
||||
p.init(liquidPledging, name, url, parentProject);
|
||||
}
|
||||
|
||||
}
|
|
@ -7,8 +7,8 @@
|
|||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "solcpiler",
|
||||
"test": "solcpiler; mocha --harmony"
|
||||
"build": "solcpiler -i './contracts/**/*.sol'",
|
||||
"test": "npm run build; mocha --harmony"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -38,13 +38,14 @@
|
|||
"lerna": "^2.2.0",
|
||||
"random-bytes": "^1.0.0",
|
||||
"mocha": "^3.5.0",
|
||||
"solcpiler": "0.0.4",
|
||||
"solcpiler": "0.0.7",
|
||||
"web3": "1.0.0-beta.24"
|
||||
},
|
||||
"homepage": "https://github.com/Giveth/liquidpledging#readme",
|
||||
"dependencies": {
|
||||
"async": "^2.4.0",
|
||||
"chai": "^4.1.0",
|
||||
"eth-contract-class": "0.0.6"
|
||||
"eth-contract-class": "0.0.6",
|
||||
"giveth-common-contracts": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* eslint-env mocha */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
const TestRPC = require('ethereumjs-testrpc');
|
||||
const Web3 = require('web3');
|
||||
const chai = require('chai');
|
||||
const liquidpledging = require('../index.js');
|
||||
const assertFail = require('./helpers/assertFail');
|
||||
|
||||
const LiquidPledging = liquidpledging.LiquidPledgingMock;
|
||||
const LiquidPledgingState = liquidpledging.LiquidPledgingState;
|
||||
const simpleProjectPluginFactoryAbi = require('../build/TestSimpleProjectPluginFactory.sol').TestSimpleProjectPluginFactoryAbi;
|
||||
const simpleProjectPluginFactoryByteCode = require('../build/TestSimpleProjectPluginFactory.sol').TestSimpleProjectPluginFactoryByteCode;
|
||||
const simpleProjectPluginRuntimeByteCode = require('../build/TestSimpleProjectPluginFactory.sol').TestSimpleProjectPluginRuntimeByteCode;
|
||||
const Vault = liquidpledging.Vault;
|
||||
const assert = chai.assert;
|
||||
|
||||
const printState = async (liquidPledgingState) => {
|
||||
const st = await liquidPledgingState.getState();
|
||||
console.log(JSON.stringify(st, null, 2));
|
||||
};
|
||||
|
||||
describe('LiquidPledging plugins test', function () {
|
||||
this.timeout(0);
|
||||
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
let liquidPledging;
|
||||
let liquidPledgingState;
|
||||
let vault;
|
||||
let giver1;
|
||||
let adminProject1;
|
||||
let adminDelegate1;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
ws: true,
|
||||
gasLimit: 6500000,
|
||||
total_accounts: 10,
|
||||
});
|
||||
|
||||
testrpc.listen(8546, '127.0.0.1');
|
||||
|
||||
web3 = new Web3('ws://localhost:8546');
|
||||
accounts = await web3.eth.getAccounts();
|
||||
giver1 = accounts[ 1 ];
|
||||
adminProject1 = accounts[ 2 ];
|
||||
adminDelegate1 = accounts[ 3 ];
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledging contract', async function() {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 6500000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
});
|
||||
|
||||
it('Should create create giver with no plugin', async function() {
|
||||
await liquidPledging.addGiver('Giver1', '', 0, '0x0', { from: adminProject1 });
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 1);
|
||||
});
|
||||
|
||||
it('Should fail to create giver with invalid plugin', async function() {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.addGiver('Giver2', '', 0, vault.$address, { from: giver1 });
|
||||
});
|
||||
});
|
||||
|
||||
it('Should fail to create delegate with invalid plugin', async function() {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.addDelegate('delegate1', '', 0, liquidPledging.$address, { from: adminDelegate1});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should fail to create project with invalid plugin', async function() {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.addProject('Project1', '', giver1, 0, 0, vault.$address, { from: adminProject1});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should deploy TestSimpleProjectPlugin and add project', async function() {
|
||||
// add plugin as valid plugin
|
||||
const codeHash = web3.utils.soliditySha3(simpleProjectPluginRuntimeByteCode);
|
||||
console.log(codeHash);
|
||||
await liquidPledging.addValidPlugin(codeHash);
|
||||
|
||||
// deploy new plugin
|
||||
const factoryContract = await new web3.eth.Contract(simpleProjectPluginFactoryAbi)
|
||||
.deploy({
|
||||
data: simpleProjectPluginFactoryByteCode,
|
||||
arguments: []
|
||||
}).send({ from: adminProject1, gas: 5000000 });
|
||||
|
||||
await factoryContract.methods
|
||||
.deploy(liquidPledging.$address, "SimplePlugin1", "", 0)
|
||||
.send({ from: adminProject1, gas: 4000000 });
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 2);
|
||||
});
|
||||
|
||||
it('Should allow all plugins', async function() {
|
||||
await liquidPledging.useWhitelist(false, { gas: 100000 });
|
||||
|
||||
await liquidPledging.addGiver('Giver2', '', 0, vault.$address, { from: giver1, gas: 200000 });
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 3);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue