Merge branch 'master' of github.com:Giveth/liquidpledging
This commit is contained in:
commit
fdc05b8197
|
@ -1,3 +1,4 @@
|
|||
lib/
|
||||
node_modules/
|
||||
.DS_Store
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
js
|
||||
.babelrc
|
||||
!build
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"custom-rules-filename": null,
|
||||
"rules": {
|
||||
"imports-on-top": true,
|
||||
"variable-declarations": true,
|
||||
"array-declarations": true,
|
||||
"operator-whitespace": true,
|
||||
"lbrace": true,
|
||||
"mixedcase": true,
|
||||
"camelcase": true,
|
||||
"uppercase": true,
|
||||
"no-with": true,
|
||||
"no-empty-blocks": true,
|
||||
"no-unused-vars": true,
|
||||
"double-quotes": true,
|
||||
"blank-lines": true,
|
||||
"indentation": true,
|
||||
"whitespace": true,
|
||||
"deprecated-suicide": true,
|
||||
"pragma-on-top": true
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# Liquid Pledging
|
||||
![Liquid Pledging](readme-header.png)
|
||||
|
||||
> Ethereum contract to delegate donations to projects.
|
||||
|
||||
|
@ -16,7 +16,7 @@ Welcome to the code for the liquidpledging contract, a new way to distribute don
|
|||
- [Help](#help)
|
||||
|
||||
### Install
|
||||
1. Click **Star** on this repo near the top-right corner of this web page.
|
||||
1. Click **Star** on this repo near the top-right corner of this web page (if you want to).
|
||||
2. Join our [slack](http://slack.giveth.io) if you haven't already.
|
||||
3. Fork this repo by clicking **Fork** button in top-right corner of this web page. Continue to follow instruction steps from your own liquidpledging repo.
|
||||
5. The rest of these steps must be done from your machine's command line. Clone your own "liquidpledging" repo:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* This is an autogenerated file. DO NOT EDIT MANUALLY */
|
||||
|
||||
exports.ILiquidPledgingPluginAbi = [{"constant":false,"inputs":[{"name":"pledgeManager","type":"uint64"},{"name":"pledgeFrom","type":"uint64"},{"name":"pledgeTo","type":"uint64"},{"name":"context","type":"uint64"},{"name":"amount","type":"uint256"}],"name":"afterTransfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"pledgeManager","type":"uint64"},{"name":"pledgeFrom","type":"uint64"},{"name":"pledgeTo","type":"uint64"},{"name":"context","type":"uint64"},{"name":"amount","type":"uint256"}],"name":"beforeTransfer","outputs":[{"name":"maxAllowed","type":"uint256"}],"payable":false,"type":"function"}]
|
||||
exports.ILiquidPledgingPluginAbi = [{"constant":false,"inputs":[{"name":"pledgeManager","type":"uint64"},{"name":"pledgeFrom","type":"uint64"},{"name":"pledgeTo","type":"uint64"},{"name":"context","type":"uint64"},{"name":"amount","type":"uint256"}],"name":"afterTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pledgeManager","type":"uint64"},{"name":"pledgeFrom","type":"uint64"},{"name":"pledgeTo","type":"uint64"},{"name":"context","type":"uint64"},{"name":"amount","type":"uint256"}],"name":"beforeTransfer","outputs":[{"name":"maxAllowed","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
||||
exports.ILiquidPledgingPluginByteCode = "0x"
|
||||
exports._solcVersion = "0.4.15+commit.bbb8e64f.Emscripten.clang"
|
||||
exports._solcVersion = "0.4.18+commit.9cf6e910.Emscripten.clang"
|
||||
exports._sha256 = "0xdca1f6e8e45033d2b165904df14f39c39500c42395eabcc79e156346438f3259"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -646,11 +646,13 @@ function donate(uint64 idGiver, uint64 idReceiver) payable {
|
|||
idPledge = normalizePledge(idPledge);
|
||||
|
||||
Pledge storage n = findPledge(idPledge);
|
||||
require(n.oldPledge != 0);
|
||||
|
||||
PledgeAdmin storage m = findAdmin(n.owner);
|
||||
checkAdminOwner(m);
|
||||
|
||||
doTransfer(idPledge, n.oldPledge, amount);
|
||||
uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
|
||||
doTransfer(idPledge, oldPledge, amount);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -646,11 +646,13 @@ function donate(uint64 idGiver, uint64 idReceiver) payable {
|
|||
idPledge = normalizePledge(idPledge);
|
||||
|
||||
Pledge storage n = findPledge(idPledge);
|
||||
require(n.oldPledge != 0);
|
||||
|
||||
PledgeAdmin storage m = findAdmin(n.owner);
|
||||
checkAdminOwner(m);
|
||||
|
||||
doTransfer(idPledge, n.oldPledge, amount);
|
||||
uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
|
||||
doTransfer(idPledge, oldPledge, amount);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* This is an autogenerated file. DO NOT EDIT MANUALLY */
|
||||
|
||||
exports.OwnedAbi = [{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]
|
||||
exports.OwnedByteCode = "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101d18061003c6000396000f300606060405263ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166379ba5097811461005e5780638da5cb5b14610073578063a6f9dae1146100a2578063d4ee1d90146100c3575b600080fd5b341561006957600080fd5b6100716100f2565b005b341561007e57600080fd5b61008661013f565b604051600160a060020a03909116815260200160405180910390f35b34156100ad57600080fd5b610071600160a060020a036004351661014e565b005b34156100ce57600080fd5b610086610196565b604051600160a060020a03909116815260200160405180910390f35b60015433600160a060020a0390811691161461010d57600080fd5b6001546000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555b565b600054600160a060020a031681565b60005433600160a060020a0390811691161461016957600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600154600160a060020a0316815600a165627a7a72305820e68440031004354b3db9d740fb2b8896f5bedd56653beb65edd62e94e414a7ad0029"
|
||||
exports._solcVersion = "0.4.15+commit.bbb8e64f.Emscripten.clang"
|
||||
exports.OwnedAbi = [{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
|
||||
exports.OwnedByteCode = "0x6060604052341561000f57600080fd5b60008054600160a060020a033316600160a060020a03199091161790556101bc8061003b6000396000f3006060604052600436106100615763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166379ba509781146100665780638da5cb5b1461007b578063a6f9dae1146100aa578063d4ee1d90146100c9575b600080fd5b341561007157600080fd5b6100796100dc565b005b341561008657600080fd5b61008e610128565b604051600160a060020a03909116815260200160405180910390f35b34156100b557600080fd5b610079600160a060020a0360043516610137565b34156100d457600080fd5b61008e610181565b60015433600160a060020a039081169116146100f757600080fd5b6001546000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600054600160a060020a031681565b60005433600160a060020a0390811691161461015257600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600154600160a060020a0316815600a165627a7a7230582093915e2078cf23efe265b372c026c6cbc79ddd13f04e6e31d52efe53c70380790029"
|
||||
exports._solcVersion = "0.4.18+commit.9cf6e910.Emscripten.clang"
|
||||
exports._sha256 = "0xf61824cbb7f4765beceba9899e284825b9c60abba4179558d6b40e6976076b6b"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -179,9 +179,6 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
|
||||
require(n.paymentState == PaymentState.Paying);
|
||||
|
||||
// Check the project is not canceled in the while.
|
||||
require(getOldestPledgeNotCanceled(idPledge) == idPledge);
|
||||
|
||||
uint64 idNewPledge = findOrCreatePledge(
|
||||
n.owner,
|
||||
n.delegationChain,
|
||||
|
@ -232,11 +229,13 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
idPledge = normalizePledge(idPledge);
|
||||
|
||||
Pledge storage n = findPledge(idPledge);
|
||||
require(n.oldPledge != 0);
|
||||
|
||||
PledgeAdmin storage m = findAdmin(n.owner);
|
||||
checkAdminOwner(m);
|
||||
|
||||
doTransfer(idPledge, n.oldPledge, amount);
|
||||
uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
|
||||
doTransfer(idPledge, oldPledge, amount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,11 +282,9 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
}
|
||||
}
|
||||
|
||||
function mNormalizePledge(uint[] pledges) returns(uint64) {
|
||||
function mNormalizePledge(uint64[] pledges) {
|
||||
for (uint i = 0; i < pledges.length; i++ ) {
|
||||
uint64 idPledge = uint64( pledges[i] & (D64-1) );
|
||||
|
||||
normalizePledge(idPledge);
|
||||
normalizePledge( pledges[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,10 +92,10 @@ contract Vault is Owned {
|
|||
require(p.state == PaymentStatus.Pending);
|
||||
|
||||
p.state = PaymentStatus.Paid;
|
||||
p.dest.transfer(p.amount); // only ETH denominated in wei
|
||||
|
||||
liquidPledging.confirmPayment(uint64(p.ref), p.amount);
|
||||
|
||||
p.dest.transfer(p.amount); // only ETH denominated in wei
|
||||
|
||||
ConfirmPayment(_idPayment);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
9
index.js
9
index.js
|
@ -1,5 +1,4 @@
|
|||
|
||||
exports.LiquidPledging = require('./js/liquidPledging.js');
|
||||
exports.LiquidPledgingMock = require('./js/liquidPledgingMock.js');
|
||||
exports.LiquidPledgingState = require('./js/liquidPledgingState.js');
|
||||
exports.Vault = require('./js/vault.js');
|
||||
exports.LiquidPledging = require('./lib/liquidPledging.js');
|
||||
exports.LiquidPledgingMock = require('./lib/liquidPledgingMock.js');
|
||||
exports.LiquidPledgingState = require('./lib/liquidPledgingState.js');
|
||||
exports.Vault = require('./lib/vault.js');
|
||||
|
|
19
package.json
19
package.json
|
@ -4,11 +4,15 @@
|
|||
"description": "Liquid Pledging Smart Contract",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "solcpiler",
|
||||
"test": "solcpiler; mocha --harmony"
|
||||
"test": "npm run build; mocha --harmony",
|
||||
"sol-compile": "solcpiler -i './contracts/**/*.sol'",
|
||||
"js-compile": "babel -d lib/ js/",
|
||||
"build": "npm run sol-compile; npm run js-compile",
|
||||
"prepublish": "npm run js-compile"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -29,7 +33,9 @@
|
|||
"url": "https://github.com/Giveth/liquidpledging/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"eslint-config-airbnb": "^15.0.1",
|
||||
"eslint-plugin-import": "^2.6.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
|
@ -38,13 +44,14 @@
|
|||
"lerna": "^2.2.0",
|
||||
"random-bytes": "^1.0.0",
|
||||
"mocha": "^3.5.0",
|
||||
"solcpiler": "0.0.4",
|
||||
"web3": "git://github.com/perissology/web3.js.git#all_fixes",
|
||||
"chai": "^4.1.0"
|
||||
"solcpiler": "0.0.7",
|
||||
"web3": "1.0.0-beta.24"
|
||||
},
|
||||
"homepage": "https://github.com/Giveth/liquidpledging#readme",
|
||||
"dependencies": {
|
||||
"async": "^2.4.0",
|
||||
"eth-contract-class": "0.0.4"
|
||||
"chai": "^4.1.0",
|
||||
"eth-contract-class": "0.0.6",
|
||||
"giveth-common-contracts": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,117 @@
|
|||
/* 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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/* 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 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 cancelPledge normal scenario', function () {
|
||||
this.timeout(0);
|
||||
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
let liquidPledging;
|
||||
let liquidPledgingState;
|
||||
let vault;
|
||||
let giver1;
|
||||
let adminProject1;
|
||||
let adminProject2;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
ws: true,
|
||||
gasLimit: 5800000,
|
||||
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 ];
|
||||
adminProject2 = accounts[ 3 ];
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledging contract', async () => {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
});
|
||||
|
||||
it('Should add project and donate ', async () => {
|
||||
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 0, '0x0', { from: adminProject1 });
|
||||
await liquidPledging.donate(0, 1, { from: giver1, value: '1000', gas: 500000 });
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 2);
|
||||
});
|
||||
|
||||
it('Should only allow pledge owner to cancel pledge', async () => {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.cancelPledge(2, 1000, { from: giver1, gas: 500000 });
|
||||
});
|
||||
});
|
||||
|
||||
it('Should cancel pledge and return to oldPledge', async () => {
|
||||
await liquidPledging.cancelPledge(2, 1000, { from: adminProject1, gas: 500000 });
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
|
||||
assert.equal(st.pledges[1].amount, 1000);
|
||||
assert.equal(st.pledges[2].amount, 0);
|
||||
});
|
||||
|
||||
it('Should not allow to cancel pledge if oldPledge === 0', async () => {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.cancelPledge(1, 1000, { from: giver1, gas: 500000 });
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/* 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 LiquidPledging = liquidpledging.LiquidPledgingMock;
|
||||
const LiquidPledgingState = liquidpledging.LiquidPledgingState;
|
||||
const Vault = liquidpledging.Vault;
|
||||
const assertFail = require('./helpers/assertFail');
|
||||
const assert = chai.assert;
|
||||
|
||||
const printState = async (liquidPledgingState) => {
|
||||
const st = await liquidPledgingState.getState();
|
||||
console.log(JSON.stringify(st, null, 2));
|
||||
};
|
||||
|
||||
describe('DelegationChain test', function () {
|
||||
this.timeout(0);
|
||||
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
let liquidPledging;
|
||||
let liquidPledgingState;
|
||||
let vault;
|
||||
let giver1;
|
||||
let giver2;
|
||||
let delegate1;
|
||||
let delegate2;
|
||||
let delegate3;
|
||||
let adminProject1;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
ws: true,
|
||||
gasLimit: 5800000,
|
||||
total_accounts: 10,
|
||||
});
|
||||
|
||||
testrpc.listen(8546, '127.0.0.1');
|
||||
|
||||
web3 = new Web3('ws://localhost:8546');
|
||||
accounts = await web3.eth.getAccounts();
|
||||
giver1 = accounts[1];
|
||||
delegate1 = accounts[2];
|
||||
delegate2 = accounts[3];
|
||||
delegate3 = accounts[4];
|
||||
adminProject1 = accounts[5];
|
||||
giver2 = accounts[6];
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledging contract', async () => {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
});
|
||||
|
||||
it('Should add pledgeAdmins', async () => {
|
||||
await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1 }); // pledgeAdmin 1
|
||||
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 259200, 0, { from: delegate1 }); // pledgeAdmin 2
|
||||
await liquidPledging.addDelegate('Delegate2', 'URLDelegate2', 0, 0, { from: delegate2 }); // pledgeAdmin 3
|
||||
await liquidPledging.addDelegate('Delegate3', 'URLDelegate3', 0, 0, { from: delegate3 }); // pledgeAdmin 4
|
||||
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 0, 0, { from: adminProject1 }); // pledgeAdmin 5
|
||||
await liquidPledging.addGiver('Giver2', 'URLGiver2', 0, 0, { from: giver2 }); // pledgeAdmin 6
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 6);
|
||||
});
|
||||
|
||||
it('Should allow previous delegate to transfer pledge', async () => {
|
||||
await liquidPledging.donate(1, 2, {from: giver1, value: 1000, $extraGas: 50000});
|
||||
// add delegate2 to chain
|
||||
await liquidPledging.transfer(2, 2, 1000, 3, {from: delegate1, $extraGas: 100000});
|
||||
// delegate 1 transfer pledge back to self, thus undelegating delegate2
|
||||
await liquidPledging.transfer(2, 3, 1000, 2, {from: delegate1, $extraGas: 100000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges[2].amount, 1000);
|
||||
assert.equal(st.pledges[3].amount, 0);
|
||||
});
|
||||
|
||||
it('Should allow any delegate in chain to transfer pledge and undelegate all delegates occurring later in chain', async () => {
|
||||
// add delegate2 to chain
|
||||
await liquidPledging.transfer(2, 2, 1000, 3, {from: delegate1, $extraGas: 100000});
|
||||
// add delegate3 to chain
|
||||
await liquidPledging.transfer(3, 3, 1000, 4, {from: delegate2, $extraGas: 100000});
|
||||
// delegate 1 transfer pledge to project1. should also undelegate all delegates occurring later in chain
|
||||
await liquidPledging.transfer(2, 4, 1000, 5, {from: delegate1, $extraGas: 200000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges[5].amount, 1000);
|
||||
assert.equal(st.pledges[5].intendedProject, 5);
|
||||
assert.equal(st.pledges[5].delegates.length, 1);
|
||||
assert.equal(st.pledges[5].delegates[0].id, 2);
|
||||
assert.equal(st.pledges[3].amount, 0);
|
||||
assert.equal(st.pledges[4].amount, 0);
|
||||
});
|
||||
|
||||
it('Should throw if delegate2 is not in delegationChain', async () => {
|
||||
await assertFail(async () => await liquidPledging.transfer(3, 5, 1000, 1, {from: delegate2}));
|
||||
});
|
||||
|
||||
it('Delegate1 should not be able to transfer to another giver', async () => {
|
||||
await assertFail(async () => await liquidPledging.transfer(2, 5, 1000, 6, {from: delegate1}));
|
||||
});
|
||||
|
||||
it('Delegate1 should be able to transfer pledge back to owner', async () => {
|
||||
await liquidPledging.transfer(2, 5, 1000, 1, {from: delegate1, $extraGas: 100000});
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges[1].amount, 1000);
|
||||
assert.equal(st.pledges[1].delegates.length, 0);
|
||||
assert.equal(st.pledges[5].amount, 0);
|
||||
});
|
||||
|
||||
it('Delegate1 should be able to change delegation', async () => {
|
||||
// add delegate1 to chain
|
||||
await liquidPledging.transfer(1, 1, 1000, 2, {from: giver1, $extraGas: 100000});
|
||||
// delegate1 add delegate2 to chain
|
||||
await liquidPledging.transfer(2, 2, 1000, 3, {from: delegate1, $extraGas: 100000});
|
||||
// delegate1 remove delegate2 and add delegate3 to chain
|
||||
await liquidPledging.transfer(2, 3, 1000, 4, {from: delegate1, $extraGas: 100000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges[1].amount, 0);
|
||||
assert.equal(st.pledges[6].amount, 1000);
|
||||
assert.equal(st.pledges[6].delegates.length, 2);
|
||||
assert.equal(st.pledges[6].delegates[0].id, 2);
|
||||
assert.equal(st.pledges[6].delegates[1].id, 4);
|
||||
});
|
||||
|
||||
it('delegate in chain should be able to delegate to previous delegate, thus undelegating themselves and any delegate after the previous delegate', async () => {
|
||||
// add delegate2 to chain
|
||||
await liquidPledging.transfer(4, 6, 1000, 3, {from: delegate3, $extraGas: 100000});
|
||||
// delegate2 transfer back to delegate1, thus undelegating delegate2 & delegate3
|
||||
await liquidPledging.transfer(3, 7, 1000, 2, {from: delegate2, $extraGas: 100000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges[7].amount, 0);
|
||||
assert.equal(st.pledges[2].amount, 1000);
|
||||
assert.equal(st.pledges[2].delegates.length, 1);
|
||||
assert.equal(st.pledges[2].delegates[0].id, 2);
|
||||
});
|
||||
|
||||
it('Should not append delegate on veto delegation', async () => {
|
||||
// propose the delegation
|
||||
await liquidPledging.transfer(2, 2, 1000, 5, { from: delegate1, $extraGas: 100000 });
|
||||
|
||||
const origPledge = await liquidPledging.getPledge(2);
|
||||
assert.equal(origPledge.amount, '0');
|
||||
|
||||
// veto the delegation
|
||||
await liquidPledging.transfer(1, 5, 1000, 2, { from: giver1, $extraGas: 100000 });
|
||||
|
||||
const currentPledge = await liquidPledging.getPledge(2);
|
||||
|
||||
assert.equal(currentPledge.amount, '1000');
|
||||
assert.equal(currentPledge.nDelegates, 1);
|
||||
});
|
||||
|
||||
it('Pledge should have longest commitTime in delegation chain', async () => {
|
||||
// delegate1 add delegate2 to chain
|
||||
await liquidPledging.transfer(2, 2, 1000, 3, {from: delegate1, $extraGas: 100000});
|
||||
|
||||
// set the time
|
||||
const now = Math.floor(new Date().getTime() / 1000);
|
||||
await liquidPledging.setMockedTime(now);
|
||||
|
||||
// propose project delegation
|
||||
await liquidPledging.transfer(3, 3, 1000, 5, { from: delegate2, $extraGas: 100000 });
|
||||
|
||||
const pledge = await liquidPledging.getPledge(8);
|
||||
assert.equal(pledge.commitTime, now + 259200); // 259200 is longest commitTime in delegationChain
|
||||
})
|
||||
});
|
|
@ -19,7 +19,9 @@ const printState = async (liquidPledgingState) => {
|
|||
console.log(JSON.stringify(st, null, 2));
|
||||
};
|
||||
|
||||
describe('LiquidPledging test', () => {
|
||||
describe('LiquidPledging test', function () {
|
||||
this.timeout(0);
|
||||
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
|
@ -59,12 +61,13 @@ describe('LiquidPledging test', () => {
|
|||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledging contract', async () => {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should create a giver', async () => {
|
||||
await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1 });
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
|
@ -75,13 +78,13 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res[2], 'Giver1');
|
||||
assert.equal(res[3], 'URLGiver1');
|
||||
assert.equal(res[4], 86400);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should make a donation', async () => {
|
||||
await liquidPledging.donate(1, 1, { from: giver1, value: utils.toWei(1) });
|
||||
await liquidPledging.donate(1, 1, { from: giver1, value: utils.toWei('1') });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 1);
|
||||
await liquidPledging.getPledge(1);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should create a delegate', async () => {
|
||||
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 0, 0, { from: delegate1 });
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
|
@ -92,22 +95,22 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res[2], 'Delegate1');
|
||||
assert.equal(res[3], 'URLDelegate1');
|
||||
assert.equal(res[4], 0);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Giver should delegate on the delegate', async () => {
|
||||
await liquidPledging.transfer(1, 1, utils.toWei(0.5), 2, { from: giver1 });
|
||||
await liquidPledging.transfer(1, 1, utils.toWei('0.5'), 2, { from: giver1 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 2);
|
||||
const res1 = await liquidPledging.getPledge(1);
|
||||
assert.equal(res1[0], utils.toWei(0.5));
|
||||
assert.equal(res1[0], utils.toWei('0.5'));
|
||||
const res2 = await liquidPledging.getPledge(2);
|
||||
assert.equal(res2[0], utils.toWei(0.5));
|
||||
assert.equal(res2[0], utils.toWei('0.5'));
|
||||
assert.equal(res2[1], 1); // One delegate
|
||||
|
||||
const d = await liquidPledging.getPledgeDelegate(2, 1);
|
||||
assert.equal(d[0], 2);
|
||||
assert.equal(d[1], delegate1);
|
||||
assert.equal(d[2], 'Delegate1');
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should create a 2 projects', async () => {
|
||||
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 86400, 0, { from: adminProject1 });
|
||||
|
||||
|
@ -134,27 +137,27 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res4[4], 86400);
|
||||
assert.equal(res4[5], 0);
|
||||
assert.equal(res4[6], false);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Delegate should assign to project1', async () => {
|
||||
const n = Math.floor(new Date().getTime() / 1000);
|
||||
await liquidPledging.transfer(2, 2, utils.toWei(0.2), 3, { from: delegate1 });
|
||||
await liquidPledging.transfer(2, 2, utils.toWei('0.2'), 3, { from: delegate1 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 3);
|
||||
const res3 = await liquidPledging.getPledge(3);
|
||||
assert.equal(res3[0], utils.toWei(0.2));
|
||||
assert.equal(res3[0], utils.toWei('0.2'));
|
||||
assert.equal(res3[1], 1); // Owner
|
||||
assert.equal(res3[2], 1); // Delegates
|
||||
assert.equal(res3[3], 3); // Proposed Project
|
||||
assert.isAbove(utils.toDecimal(res3[4]), n + 86000);
|
||||
assert.equal(res3[5], 0); // Old Node
|
||||
assert.equal(res3[6], 0); // Not Paid
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Giver should change his mind and assign half of it to project2', async () => {
|
||||
await liquidPledging.transfer(1, 3, utils.toWei(0.1), 4, { from: giver1 });
|
||||
await liquidPledging.transfer(1, 3, utils.toWei('0.1'), 4, { from: giver1 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 4);
|
||||
const res3 = await liquidPledging.getPledge(3);
|
||||
assert.equal(res3[0], utils.toWei(0.1));
|
||||
assert.equal(res3[0], utils.toWei('0.1'));
|
||||
const res4 = await liquidPledging.getPledge(4);
|
||||
assert.equal(res4[1], 4); // Owner
|
||||
assert.equal(res4[2], 0); // Delegates
|
||||
|
@ -162,15 +165,15 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res4[4], 0);
|
||||
assert.equal(res4[5], 2); // Old Node
|
||||
assert.equal(res4[6], 0); // Not Paid
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('After the time, the project1 should be able to spend part of it', async () => {
|
||||
const n = Math.floor(new Date().getTime() / 1000);
|
||||
await liquidPledging.setMockedTime(n + 86401);
|
||||
await liquidPledging.withdraw(3, utils.toWei(0.05), { from: adminProject1 });
|
||||
await liquidPledging.withdraw(3, utils.toWei('0.05'), { from: adminProject1 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 6);
|
||||
const res5 = await liquidPledging.getPledge(5);
|
||||
assert.equal(res5[0], utils.toWei(0.05));
|
||||
assert.equal(res5[0], utils.toWei('0.05'));
|
||||
assert.equal(res5[1], 3); // Owner
|
||||
assert.equal(res5[2], 0); // Delegates
|
||||
assert.equal(res5[3], 0); // Proposed Project
|
||||
|
@ -178,14 +181,14 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res5[5], 2); // Old Node
|
||||
assert.equal(res5[6], 0); // Not Paid
|
||||
const res6 = await liquidPledging.getPledge(6);
|
||||
assert.equal(res6[0], utils.toWei(0.05));
|
||||
assert.equal(res6[0], utils.toWei('0.05'));
|
||||
assert.equal(res6[1], 3); // Owner
|
||||
assert.equal(res6[2], 0); // Delegates
|
||||
assert.equal(res6[3], 0); // Proposed Project
|
||||
assert.equal(res6[4], 0); // commit time
|
||||
assert.equal(res6[5], 2); // Old Node
|
||||
assert.equal(res6[6], 1); // Peinding paid Paid
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should collect the Ether', async () => {
|
||||
const initialBalance = await web3.eth.getBalance(adminProject1);
|
||||
|
||||
|
@ -199,28 +202,28 @@ describe('LiquidPledging test', () => {
|
|||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 7);
|
||||
const res7 = await liquidPledging.getPledge(7);
|
||||
assert.equal(res7[0], utils.toWei(0.05));
|
||||
assert.equal(res7[0], utils.toWei('0.05'));
|
||||
assert.equal(res7[1], 3); // Owner
|
||||
assert.equal(res7[2], 0); // Delegates
|
||||
assert.equal(res7[3], 0); // Proposed Project
|
||||
assert.equal(res7[4], 0); // commit time
|
||||
assert.equal(res7[5], 2); // Old Node
|
||||
assert.equal(res7[6], 2); // Peinding paid Paid
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Admin of the project1 should be able to cancel project1', async () => {
|
||||
await liquidPledging.cancelProject(3, { from: adminProject1 });
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(st.admins[3].canceled, true);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should not allow to withdraw from a canceled project', async () => {
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(utils.fromWei(st.pledges[5].amount), 0.05);
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.withdraw(5, utils.toWei(0.01), { from: adminProject1 });
|
||||
await liquidPledging.withdraw(5, utils.toWei('0.01'), { from: adminProject1 });
|
||||
});
|
||||
});
|
||||
}).timeout(6000);
|
||||
it('Delegate should send part of this ETH to project2', async () => {
|
||||
await liquidPledging.transfer(2, 5, utils.toWei(0.03), 4, {
|
||||
await liquidPledging.transfer(2, 5, utils.toWei('0.03'), 4, {
|
||||
$extraGas: 100000,
|
||||
from: delegate1,
|
||||
});
|
||||
|
@ -231,57 +234,52 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(st.pledges[8].delegates.length, 1);
|
||||
assert.equal(st.pledges[8].delegates[0].id, 2);
|
||||
assert.equal(st.pledges[8].intendedProject, 4);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Giver should be able to send the remaining to project2', async () => {
|
||||
await liquidPledging.transfer(1, 5, utils.toWei(0.02), 4, { from: giver1, $extraGas: 100000 });
|
||||
await liquidPledging.transfer(1, 5, utils.toWei('0.02'), 4, { from: giver1, $extraGas: 100000 });
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(st.pledges.length, 9);
|
||||
assert.equal(utils.fromWei(st.pledges[5].amount), 0);
|
||||
assert.equal(utils.fromWei(st.pledges[4].amount), 0.12);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('A subproject 2a and a delegate2 is created', async () => {
|
||||
await liquidPledging.addProject('Project2a', 'URLProject2a', adminProject2a, 4, 86400, 0, { from: adminProject2 });
|
||||
await liquidPledging.addDelegate('Delegate2', 'URLDelegate2', 0, 0, { from: delegate2 });
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 6);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Project 2 delegate in delegate2', async () => {
|
||||
await liquidPledging.transfer(4, 4, utils.toWei(0.02), 6, { from: adminProject2 });
|
||||
await liquidPledging.transfer(4, 4, utils.toWei('0.02'), 6, { from: adminProject2 });
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(st.pledges.length, 10);
|
||||
assert.equal(utils.fromWei(st.pledges[9].amount), 0.02);
|
||||
assert.equal(utils.fromWei(st.pledges[4].amount), 0.1);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('delegate2 assigns to projec2a', async () => {
|
||||
await liquidPledging.transfer(6, 9, utils.toWei(0.01), 5, { from: delegate2 });
|
||||
await liquidPledging.transfer(6, 9, utils.toWei('0.01'), 5, { from: delegate2 });
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(st.pledges.length, 11);
|
||||
assert.equal(utils.fromWei(st.pledges[9].amount), 0.01);
|
||||
assert.equal(utils.fromWei(st.pledges[10].amount), 0.01);
|
||||
}).timeout(4000);
|
||||
});
|
||||
it('project2a authorize to spend a litle', async () => {
|
||||
const n = Math.floor(new Date().getTime() / 1000);
|
||||
await liquidPledging.setMockedTime(n + (86401 * 3));
|
||||
await liquidPledging.withdraw(10, utils.toWei(0.005), { from: adminProject2a });
|
||||
await liquidPledging.withdraw(10, utils.toWei('0.005'), { from: adminProject2a });
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
assert.equal(st.pledges.length, 13);
|
||||
assert.equal(utils.fromWei(st.pledges[10].amount), 0);
|
||||
assert.equal(utils.fromWei(st.pledges[11].amount), 0.005);
|
||||
assert.equal(utils.fromWei(st.pledges[12].amount), 0.005);
|
||||
}).timeout(4000);
|
||||
});
|
||||
it('project2 is canceled', async () => {
|
||||
await liquidPledging.cancelProject(4, { from: adminProject2 });
|
||||
}).timeout(6000);
|
||||
it('project2 should not be able to confirm payment', async () => {
|
||||
await assertFail(async () => {
|
||||
await vault.confirmPayment(1);
|
||||
});
|
||||
}).timeout(6000);
|
||||
it('Should not be able to withdraw it', async () => {
|
||||
await assertFail(async () => {
|
||||
await liquidPledging.withdraw(12, utils.toWei(0.005), { from: giver1 });
|
||||
await liquidPledging.withdraw(12, utils.toWei('0.005'), { from: giver1 });
|
||||
});
|
||||
});
|
||||
}).timeout(6000);
|
||||
it('Should be able to cancel payment', async () => {
|
||||
// bug somewhere which will throw invalid op_code if we don't provide gas or extraGas
|
||||
await vault.cancelPayment(1, { $extraGas: 100000 });
|
||||
|
@ -290,14 +288,22 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(utils.fromWei(st.pledges[2].amount), 0.31);
|
||||
assert.equal(utils.fromWei(st.pledges[11].amount), 0);
|
||||
assert.equal(utils.fromWei(st.pledges[12].amount), 0);
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('original owner should recover the remaining funds', async () => {
|
||||
await liquidPledging.withdraw(1, utils.toWei(0.5), { from: giver1 });
|
||||
await liquidPledging.withdraw(2, utils.toWei(0.31), { from: giver1 });
|
||||
await liquidPledging.withdraw(4, utils.toWei(0.1), { $extraGas: 100000, from: giver1 });
|
||||
const pledges = [
|
||||
{ amount: utils.toWei('0.5'), id: 1 },
|
||||
{ amount: utils.toWei('0.31'), id: 2 },
|
||||
{ amount: utils.toWei('0.1'), id: 4 },
|
||||
{ amount: utils.toWei('0.03'), id: 8 },
|
||||
{ amount: utils.toWei('0.01'), id: 9 },
|
||||
];
|
||||
|
||||
await liquidPledging.withdraw(8, utils.toWei(0.03), { $extraGas: 100000, from: giver1 });
|
||||
await liquidPledging.withdraw(9, utils.toWei(0.01), { $extraGas: 100000, from: giver1 });
|
||||
// .substring is to remove the 0x prefix on the toHex result
|
||||
const encodedPledges = pledges.map(p => {
|
||||
return '0x' + utils.padLeft(utils.toHex(p.amount).substring(2), 48) + utils.padLeft(utils.toHex(p.id).substring(2), 16);
|
||||
});
|
||||
|
||||
await liquidPledging.mWithdraw(encodedPledges, { from: giver1, $extraGas: 500000 });
|
||||
|
||||
const initialBalance = await web3.eth.getBalance(giver1);
|
||||
await vault.multiConfirm([2, 3, 4, 5, 6]);
|
||||
|
@ -306,11 +312,11 @@ describe('LiquidPledging test', () => {
|
|||
const collected = utils.fromWei(utils.toBN(finalBalance).sub(utils.toBN(initialBalance)));
|
||||
|
||||
assert.equal(collected, 0.95);
|
||||
}).timeout(12000);
|
||||
});
|
||||
it('Should make a donation and create giver', async () => {
|
||||
const oldNPledges = await liquidPledging.numberOfPledges();
|
||||
const oldNAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
await liquidPledging.donate(0, 1, { from: giver2, value: utils.toWei(1) });
|
||||
await liquidPledging.donate(0, 1, { from: giver2, value: utils.toWei('1') });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(utils.toDecimal(nPledges), utils.toDecimal(oldNPledges) + 1);
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
|
@ -321,11 +327,11 @@ describe('LiquidPledging test', () => {
|
|||
assert.equal(res[2], '');
|
||||
assert.equal(res[3], '');
|
||||
assert.equal(res[4], 259200); // default to 3 day commitTime
|
||||
}).timeout(6000);
|
||||
});
|
||||
it('Should allow childProject with different parentProject owner', async () => {
|
||||
const nAdminsBefore = await liquidPledging.numberOfPledgeAdmins();
|
||||
await liquidPledging.addProject('Project3', 'URLProject3', adminProject3, 4, 86400, 0, { from: adminProject3 });
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, utils.toDecimal(nAdminsBefore) + 1);
|
||||
}).timeout(6000);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/* 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 LiquidPledging = liquidpledging.LiquidPledgingMock;
|
||||
const LiquidPledgingState = liquidpledging.LiquidPledgingState;
|
||||
const Vault = liquidpledging.Vault;
|
||||
const assertFail = require('./helpers/assertFail');
|
||||
const assert = chai.assert;
|
||||
|
||||
const printState = async (liquidPledgingState) => {
|
||||
const st = await liquidPledgingState.getState();
|
||||
console.log(JSON.stringify(st, null, 2));
|
||||
};
|
||||
|
||||
describe('NormalizePledge test', function () {
|
||||
this.timeout(0);
|
||||
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
let liquidPledging;
|
||||
let liquidPledgingState;
|
||||
let vault;
|
||||
let giver1;
|
||||
let giver2;
|
||||
let delegate1;
|
||||
let delegate2;
|
||||
let adminProject1;
|
||||
let adminProject2;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
ws: true,
|
||||
gasLimit: 5800000,
|
||||
total_accounts: 10,
|
||||
});
|
||||
|
||||
testrpc.listen(8546, '127.0.0.1');
|
||||
|
||||
web3 = new Web3('ws://localhost:8546');
|
||||
accounts = await web3.eth.getAccounts();
|
||||
giver1 = accounts[1];
|
||||
delegate1 = accounts[2];
|
||||
delegate2 = accounts[3];
|
||||
adminProject1 = accounts[4];
|
||||
adminProject2 = accounts[5];
|
||||
giver2 = accounts[6];
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledging contract', async () => {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
});
|
||||
|
||||
it('Should add pledgeAdmins', async () => {
|
||||
await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1 }); // pledgeAdmin 1
|
||||
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 259200, 0, { from: delegate1 }); // pledgeAdmin 2
|
||||
await liquidPledging.addDelegate('Delegate2', 'URLDelegate2', 0, 0, { from: delegate2 }); // pledgeAdmin 3
|
||||
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 0, 0, { from: adminProject1 }); // pledgeAdmin 4
|
||||
await liquidPledging.addProject('Project2', 'URLProject2', adminProject2, 0, 0, 0, { from: adminProject2 }); // pledgeAdmin 5
|
||||
await liquidPledging.addGiver('Giver2', 'URLGiver2', 0, 0, { from: giver2 }); // pledgeAdmin 6
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 6);
|
||||
});
|
||||
|
||||
it('Should commit pledges if commitTime has passed', async () => {
|
||||
// commitTime 259200
|
||||
await liquidPledging.donate(1, 2, {from: giver1, value: 1000, $extraGas: 50000});
|
||||
// commitTime 86400
|
||||
await liquidPledging.donate(1, 3, {from: giver1, value: 1000, $extraGas: 50000});
|
||||
// commitTime 0
|
||||
await liquidPledging.donate(6, 3, {from: giver2, value: 1000, $extraGas: 50000});
|
||||
|
||||
// set the time
|
||||
const now = Math.floor(new Date().getTime() / 1000);
|
||||
await liquidPledging.setMockedTime(now);
|
||||
|
||||
// delegate to project
|
||||
await liquidPledging.transfer(2, 2, 1000, 4, {from: delegate1, $extraGas: 100000});
|
||||
await liquidPledging.transfer(3, 3, 1000, 4, {from: delegate2, $extraGas: 100000});
|
||||
await liquidPledging.transfer(3, 5, 1000, 4, {from: delegate2, $extraGas: 100000});
|
||||
|
||||
// advance the time
|
||||
await liquidPledging.setMockedTime( now + 100000 );
|
||||
|
||||
await liquidPledging.mNormalizePledge([6, 7, 8], {$extraGas: 100000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges.length, 11);
|
||||
assert.equal(st.pledges[6].amount, 1000);
|
||||
assert.equal(st.pledges[9].amount, 1000);
|
||||
assert.equal(st.pledges[9].owner, 4);
|
||||
assert.equal(st.pledges[9].oldPledge, 3);
|
||||
assert.equal(st.pledges[10].amount, 1000);
|
||||
assert.equal(st.pledges[10].owner, 4);
|
||||
assert.equal(st.pledges[10].oldPledge, 5);
|
||||
});
|
||||
|
||||
it('Should transfer pledge to oldestPledgeNotCanceled', async () => {
|
||||
await liquidPledging.transfer(4, 10, 1000, 5, {from: adminProject1, $extraGas: 100000});
|
||||
|
||||
// cancel projects
|
||||
await liquidPledging.cancelProject(4, {from: adminProject1});
|
||||
await liquidPledging.cancelProject(5, {from: adminProject2});
|
||||
|
||||
await liquidPledging.mNormalizePledge([9, 11], {$extraGas: 100000});
|
||||
|
||||
const st = await liquidPledgingState.getState();
|
||||
assert.equal(st.pledges.length, 12);
|
||||
assert.equal(st.pledges[3].amount, 1000);
|
||||
assert.equal(st.pledges[5].amount, 1000);
|
||||
assert.equal(st.pledges[9].amount, 0);
|
||||
assert.equal(st.pledges[11].amount, 0);
|
||||
})
|
||||
});
|
|
@ -1,103 +0,0 @@
|
|||
/* 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 LiquidPledging = liquidpledging.LiquidPledgingMock;
|
||||
const LiquidPledgingState = liquidpledging.LiquidPledgingState;
|
||||
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 test', () => {
|
||||
let testrpc;
|
||||
let web3;
|
||||
let accounts;
|
||||
let liquidPledging;
|
||||
let liquidPledgingState;
|
||||
let vault;
|
||||
let giver1;
|
||||
let delegate1;
|
||||
let adminProject1;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
ws: true,
|
||||
gasLimit: 5800000,
|
||||
total_accounts: 10,
|
||||
});
|
||||
|
||||
testrpc.listen(8546, '127.0.0.1');
|
||||
|
||||
web3 = new Web3('ws://localhost:8546');
|
||||
accounts = await web3.eth.getAccounts();
|
||||
giver1 = accounts[1];
|
||||
delegate1 = accounts[2];
|
||||
adminProject1 = accounts[3];
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
testrpc.close();
|
||||
done();
|
||||
});
|
||||
|
||||
it('Should deploy LiquidPledgin contract', async () => {
|
||||
vault = await Vault.new(web3);
|
||||
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
|
||||
await vault.setLiquidPledging(liquidPledging.$address);
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
});
|
||||
|
||||
it('Should create a delegate', async () => {
|
||||
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 0, 0, { from: delegate1 });
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 1);
|
||||
const res = await liquidPledging.getPledgeAdmin(1);
|
||||
assert.equal(res[0], 1); // Giver
|
||||
assert.equal(res[1], delegate1);
|
||||
assert.equal(res[2], 'Delegate1');
|
||||
assert.equal(res[3], 'URLDelegate1');
|
||||
assert.equal(res[4], 0);
|
||||
}).timeout(6000);
|
||||
|
||||
it('Should make a donation and create giver', async () => {
|
||||
await liquidPledging.donate(0, 1, { from: giver1, value: '1000', gas: 2000000 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 2);
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 2);
|
||||
const res = await liquidPledging.getPledgeAdmin(nAdmins);
|
||||
assert.equal(res[0], 0); // Giver
|
||||
assert.equal(res[1], giver1);
|
||||
assert.equal(res[2], '');
|
||||
assert.equal(res[3], '');
|
||||
assert.equal(res[4], 259200); // default to 3 day commitTime
|
||||
});
|
||||
|
||||
it('Should not append delegate on veto delegation', async () => {
|
||||
await liquidPledging.addProject('Project 1', 'url', adminProject1, 0, 0, 0);
|
||||
// propose the delegation
|
||||
await liquidPledging.transfer(1, 2, '1000', 3, { from: delegate1, gas: 400000 });
|
||||
// await liquidPledging.transfer(1, 2, '1000', 5, { from: giver1, gas: 400000 });
|
||||
|
||||
const origPledge = await liquidPledging.getPledge(2);
|
||||
assert.equal(origPledge.amount, '0');
|
||||
|
||||
// await printState(liquidPledgingState);
|
||||
// veto the delegation
|
||||
await liquidPledging.transfer(2, 3, '1000', 1, { from: giver1, gas: 400000 });
|
||||
|
||||
const currentPledge = await liquidPledging.getPledge(2);
|
||||
|
||||
// await printState(liquidPledgingState);
|
||||
|
||||
assert.equal(currentPledge.amount, '1000');
|
||||
assert.equal(currentPledge.nDelegates, 1);
|
||||
});
|
||||
});
|
|
@ -6,7 +6,7 @@ module.exports = async function(callback) {
|
|||
try {
|
||||
await callback();
|
||||
} catch (error) {
|
||||
if (error.message.search("invalid opcode")) web3_error_thrown = true;
|
||||
if (error.message.includes("invalid opcode")) web3_error_thrown = true;
|
||||
}
|
||||
assert.ok(web3_error_thrown, "Transaction should fail");
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue