Fix test issues and merge from master

This commit is contained in:
Arthur L Lunn 2017-11-10 18:54:27 +00:00
commit 8ab1ce5066
16 changed files with 495 additions and 60 deletions

1
.soliumignore Normal file
View File

@ -0,0 +1 @@
node_modules

22
.soliumrc.json Normal file
View File

@ -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
}
}

View File

@ -1,4 +1,4 @@
# Liquid Pledging ![Liquid Pledging](readme-header.png)
> Ethereum contract to delegate donations to projects. > Ethereum contract to delegate donations to projects.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -883,11 +883,13 @@ contract LiquidPledging is LiquidPledgingBase {
idPledge = normalizePledge(idPledge); idPledge = normalizePledge(idPledge);
Pledge storage n = findPledge(idPledge); Pledge storage n = findPledge(idPledge);
require(n.oldPledge != 0);
PledgeAdmin storage m = findAdmin(n.owner); PledgeAdmin storage m = findAdmin(n.owner);
checkAdminOwner(m); checkAdminOwner(m);
doTransfer(idPledge, n.oldPledge, amount); uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
doTransfer(idPledge, oldPledge, amount);
} }

View File

@ -883,11 +883,13 @@ contract LiquidPledging is LiquidPledgingBase {
idPledge = normalizePledge(idPledge); idPledge = normalizePledge(idPledge);
Pledge storage n = findPledge(idPledge); Pledge storage n = findPledge(idPledge);
require(n.oldPledge != 0);
PledgeAdmin storage m = findAdmin(n.owner); PledgeAdmin storage m = findAdmin(n.owner);
checkAdminOwner(m); checkAdminOwner(m);
doTransfer(idPledge, n.oldPledge, amount); uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
doTransfer(idPledge, oldPledge, amount);
} }

View File

@ -119,10 +119,10 @@ contract LPVault is Owned {
require(p.state == PaymentStatus.Pending); require(p.state == PaymentStatus.Pending);
p.state = PaymentStatus.Paid; p.state = PaymentStatus.Paid;
p.dest.transfer(p.amount); // only ETH denominated in wei
liquidPledging.confirmPayment(uint64(p.ref), p.amount); liquidPledging.confirmPayment(uint64(p.ref), p.amount);
p.dest.transfer(p.amount); // only ETH denominated in wei
ConfirmPayment(_idPayment); ConfirmPayment(_idPayment);
} }

View File

@ -238,7 +238,7 @@ contract LiquidPledging is LiquidPledgingBase {
require(n.paymentState == PaymentState.Paying); require(n.paymentState == PaymentState.Paying);
// Check the project is not canceled in the while. // Check the project is not canceled in the while.
require(getOldestPledgeNotCanceled(idPledge) == idPledge); require(!isProjectCanceled(n.owner));
uint64 idNewPledge = findOrCreatePledge( uint64 idNewPledge = findOrCreatePledge(
n.owner, n.owner,
@ -292,11 +292,13 @@ contract LiquidPledging is LiquidPledgingBase {
idPledge = normalizePledge(idPledge); idPledge = normalizePledge(idPledge);
Pledge storage n = findPledge(idPledge); Pledge storage n = findPledge(idPledge);
require(n.oldPledge != 0);
PledgeAdmin storage m = findAdmin(n.owner); PledgeAdmin storage m = findAdmin(n.owner);
checkAdminOwner(m); checkAdminOwner(m);
doTransfer(idPledge, n.oldPledge, amount); uint64 oldPledge = getOldestPledgeNotCanceled(n.oldPledge);
doTransfer(idPledge, oldPledge, amount);
} }
@ -377,11 +379,9 @@ contract LiquidPledging is LiquidPledgingBase {
/// normalized efficiently /// normalized efficiently
/// @param pledges An array of pledge IDs which are extrapolated using /// @param pledges An array of pledge IDs which are extrapolated using
/// the D64 bitmask /// the D64 bitmask
function mNormalizePledge(uint[] pledges) returns(uint64) { function mNormalizePledge(uint[] pledges) {
for (uint i = 0; i < pledges.length; i++ ) { for (uint i = 0; i < pledges.length; i++ ) {
uint64 idPledge = uint64( pledges[i] & (D64-1) ); normalizePledge( pledges[i] );
normalizePledge(idPledge);
} }
} }

View File

@ -39,12 +39,12 @@
"random-bytes": "^1.0.0", "random-bytes": "^1.0.0",
"mocha": "^3.5.0", "mocha": "^3.5.0",
"solcpiler": "0.0.4", "solcpiler": "0.0.4",
"web3": "git://github.com/perissology/web3.js.git#all_fixes" "web3": "1.0.0-beta.24"
}, },
"homepage": "https://github.com/Giveth/liquidpledging#readme", "homepage": "https://github.com/Giveth/liquidpledging#readme",
"dependencies": { "dependencies": {
"async": "^2.4.0", "async": "^2.4.0",
"chai": "^4.1.0", "chai": "^4.1.0",
"eth-contract-class": "0.0.4" "eth-contract-class": "0.0.6"
} }
} }

BIN
readme-header.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

89
test/CancelPledge.js Normal file
View File

@ -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 });
});
})
});

182
test/DelegationChain.js Normal file
View File

@ -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
})
});

View File

@ -19,7 +19,8 @@ const printState = async (liquidPledgingState) => {
console.log(JSON.stringify(st, null, 2)); console.log(JSON.stringify(st, null, 2));
}; };
describe('LiquidPledging Normal Operation', () => { describe('LiquidPledging test', function () {
this.timeout(0);
let testrpc; let testrpc;
let web3; let web3;
let accounts; let accounts;
@ -59,12 +60,13 @@ describe('LiquidPledging Normal Operation', () => {
testrpc.close(); testrpc.close();
done(); done();
}); });
it('Should deploy LiquidPledging contract', async () => { it('Should deploy LiquidPledging contract', async () => {
vault = await LPVault.new(web3); vault = await LPVault.new(web3);
liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 }); liquidPledging = await LiquidPledging.new(web3, vault.$address, { gas: 5800000 });
await vault.setLiquidPledging(liquidPledging.$address); await vault.setLiquidPledging(liquidPledging.$address);
liquidPledgingState = new LiquidPledgingState(liquidPledging); liquidPledgingState = new LiquidPledgingState(liquidPledging);
}).timeout(6000); });
it('Should create a giver', async () => { it('Should create a giver', async () => {
await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1 }); await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1 });
const nAdmins = await liquidPledging.numberOfPledgeAdmins(); const nAdmins = await liquidPledging.numberOfPledgeAdmins();
@ -75,13 +77,13 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res[2], 'Giver1'); assert.equal(res[2], 'Giver1');
assert.equal(res[3], 'URLGiver1'); assert.equal(res[3], 'URLGiver1');
assert.equal(res[4], 86400); assert.equal(res[4], 86400);
}).timeout(6000); });
it('Should make a donation', async () => { 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(); const nPledges = await liquidPledging.numberOfPledges();
assert.equal(nPledges, 1); assert.equal(nPledges, 1);
await liquidPledging.getPledge(1); await liquidPledging.getPledge(1);
}).timeout(6000); });
it('Should create a delegate', async () => { it('Should create a delegate', async () => {
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 0, 0, { from: delegate1 }); await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 0, 0, { from: delegate1 });
const nAdmins = await liquidPledging.numberOfPledgeAdmins(); const nAdmins = await liquidPledging.numberOfPledgeAdmins();
@ -92,7 +94,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res[2], 'Delegate1'); assert.equal(res[2], 'Delegate1');
assert.equal(res[3], 'URLDelegate1'); assert.equal(res[3], 'URLDelegate1');
assert.equal(res[4], 0); assert.equal(res[4], 0);
}).timeout(6000); });
it('Giver should delegate on the delegate', async () => { 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(); const nPledges = await liquidPledging.numberOfPledges();
@ -107,7 +109,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(d[0], 2); assert.equal(d[0], 2);
assert.equal(d[1], delegate1); assert.equal(d[1], delegate1);
assert.equal(d[2], 'Delegate1'); assert.equal(d[2], 'Delegate1');
}).timeout(6000); });
it('Should create a 2 projects', async () => { it('Should create a 2 projects', async () => {
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 86400, 0, { from: adminProject1 }); await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 86400, 0, { from: adminProject1 });
@ -134,7 +136,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res4[4], 86400); assert.equal(res4[4], 86400);
assert.equal(res4[5], 0); assert.equal(res4[5], 0);
assert.equal(res4[6], false); assert.equal(res4[6], false);
}).timeout(6000); });
it('Delegate should assign to project1', async () => { it('Delegate should assign to project1', async () => {
const n = Math.floor(new Date().getTime() / 1000); 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 });
@ -148,7 +150,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.isAbove(utils.toDecimal(res3[4]), n + 86000); assert.isAbove(utils.toDecimal(res3[4]), n + 86000);
assert.equal(res3[5], 0); // Old Node assert.equal(res3[5], 0); // Old Node
assert.equal(res3[6], 0); // Not Paid assert.equal(res3[6], 0); // Not Paid
}).timeout(6000); });
it('Giver should change his mind and assign half of it to project2', async () => { 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(); const nPledges = await liquidPledging.numberOfPledges();
@ -162,7 +164,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res4[4], 0); assert.equal(res4[4], 0);
assert.equal(res4[5], 2); // Old Node assert.equal(res4[5], 2); // Old Node
assert.equal(res4[6], 0); // Not Paid assert.equal(res4[6], 0); // Not Paid
}).timeout(6000); });
it('After the time, the project1 should be able to spend part of it', async () => { it('After the time, the project1 should be able to spend part of it', async () => {
const n = Math.floor(new Date().getTime() / 1000); const n = Math.floor(new Date().getTime() / 1000);
await liquidPledging.setMockedTime(n + 86401); await liquidPledging.setMockedTime(n + 86401);
@ -185,7 +187,7 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res6[4], 0); // commit time assert.equal(res6[4], 0); // commit time
assert.equal(res6[5], 2); // Old Node assert.equal(res6[5], 2); // Old Node
assert.equal(res6[6], 1); // Peinding paid Paid assert.equal(res6[6], 1); // Peinding paid Paid
}).timeout(6000); });
it('Should collect the Ether', async () => { it('Should collect the Ether', async () => {
const initialBalance = await web3.eth.getBalance(adminProject1); const initialBalance = await web3.eth.getBalance(adminProject1);
@ -206,19 +208,19 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res7[4], 0); // commit time assert.equal(res7[4], 0); // commit time
assert.equal(res7[5], 2); // Old Node assert.equal(res7[5], 2); // Old Node
assert.equal(res7[6], 2); // Peinding paid Paid assert.equal(res7[6], 2); // Peinding paid Paid
}).timeout(6000); });
it('Admin of the project1 should be able to cancel project1', async () => { it('Admin of the project1 should be able to cancel project1', async () => {
await liquidPledging.cancelProject(3, { from: adminProject1 }); await liquidPledging.cancelProject(3, { from: adminProject1 });
const st = await liquidPledgingState.getState(liquidPledging); const st = await liquidPledgingState.getState(liquidPledging);
assert.equal(st.admins[3].canceled, true); assert.equal(st.admins[3].canceled, true);
}).timeout(6000); });
it('Should not allow to withdraw from a canceled project', async () => { it('Should not allow to withdraw from a canceled project', async () => {
const st = await liquidPledgingState.getState(liquidPledging); const st = await liquidPledgingState.getState(liquidPledging);
assert.equal(utils.fromWei(st.pledges[5].amount), 0.05); assert.equal(utils.fromWei(st.pledges[5].amount), 0.05);
await assertFail(async () => { 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 () => { 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, $extraGas: 100000,
@ -231,34 +233,34 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(st.pledges[8].delegates.length, 1); assert.equal(st.pledges[8].delegates.length, 1);
assert.equal(st.pledges[8].delegates[0].id, 2); assert.equal(st.pledges[8].delegates[0].id, 2);
assert.equal(st.pledges[8].intendedProject, 4); assert.equal(st.pledges[8].intendedProject, 4);
}).timeout(6000); });
it('Giver should be able to send the remaining to project2', async () => { 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); const st = await liquidPledgingState.getState(liquidPledging);
assert.equal(st.pledges.length, 9); assert.equal(st.pledges.length, 9);
assert.equal(utils.fromWei(st.pledges[5].amount), 0); assert.equal(utils.fromWei(st.pledges[5].amount), 0);
assert.equal(utils.fromWei(st.pledges[4].amount), 0.12); assert.equal(utils.fromWei(st.pledges[4].amount), 0.12);
}).timeout(6000); });
it('A subproject 2a and a delegate2 is created', async () => { it('A subproject 2a and a delegate2 is created', async () => {
await liquidPledging.addProject('Project2a', 'URLProject2a', adminProject2a, 4, 86400, 0, { from: adminProject2 }); await liquidPledging.addProject('Project2a', 'URLProject2a', adminProject2a, 4, 86400, 0, { from: adminProject2 });
await liquidPledging.addDelegate('Delegate2', 'URLDelegate2', 0, 0, { from: delegate2 }); await liquidPledging.addDelegate('Delegate2', 'URLDelegate2', 0, 0, { from: delegate2 });
const nAdmins = await liquidPledging.numberOfPledgeAdmins(); const nAdmins = await liquidPledging.numberOfPledgeAdmins();
assert.equal(nAdmins, 6); assert.equal(nAdmins, 6);
}).timeout(6000); });
it('Project 2 delegate in delegate2', async () => { 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); const st = await liquidPledgingState.getState(liquidPledging);
assert.equal(st.pledges.length, 10); assert.equal(st.pledges.length, 10);
assert.equal(utils.fromWei(st.pledges[9].amount), 0.02); assert.equal(utils.fromWei(st.pledges[9].amount), 0.02);
assert.equal(utils.fromWei(st.pledges[4].amount), 0.1); assert.equal(utils.fromWei(st.pledges[4].amount), 0.1);
}).timeout(6000); });
it('delegate2 assigns to projec2a', async () => { 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); const st = await liquidPledgingState.getState(liquidPledging);
assert.equal(st.pledges.length, 11); assert.equal(st.pledges.length, 11);
assert.equal(utils.fromWei(st.pledges[9].amount), 0.01); assert.equal(utils.fromWei(st.pledges[9].amount), 0.01);
assert.equal(utils.fromWei(st.pledges[10].amount), 0.01); assert.equal(utils.fromWei(st.pledges[10].amount), 0.01);
}).timeout(4000); });
it('project2a authorize to spend a litle', async () => { it('project2a authorize to spend a litle', async () => {
const n = Math.floor(new Date().getTime() / 1000); const n = Math.floor(new Date().getTime() / 1000);
await liquidPledging.setMockedTime(n + (86401 * 3)); await liquidPledging.setMockedTime(n + (86401 * 3));
@ -268,20 +270,20 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(utils.fromWei(st.pledges[10].amount), 0); 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[11].amount), 0.005);
assert.equal(utils.fromWei(st.pledges[12].amount), 0.005); assert.equal(utils.fromWei(st.pledges[12].amount), 0.005);
}).timeout(4000); });
it('project2 is canceled', async () => { it('project2 is canceled', async () => {
await liquidPledging.cancelProject(4, { from: adminProject2 }); await liquidPledging.cancelProject(4, { from: adminProject2 });
}).timeout(6000); });
it('project2 should not be able to confirm payment', async () => { it('project2 should not be able to confirm payment', async () => {
await assertFail(async () => { await assertFail(async () => {
await vault.confirmPayment(1); await vault.confirmPayment(1);
}); });
}).timeout(6000); });
it('Should not be able to withdraw it', async () => { it('Should not be able to withdraw it', async () => {
await assertFail(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 () => { it('Should be able to cancel payment', async () => {
// bug somewhere which will throw invalid op_code if we don't provide gas or extraGas // bug somewhere which will throw invalid op_code if we don't provide gas or extraGas
await vault.cancelPayment(1, { $extraGas: 100000 }); await vault.cancelPayment(1, { $extraGas: 100000 });
@ -290,14 +292,22 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(utils.fromWei(st.pledges[2].amount), 0.31); 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[11].amount), 0);
assert.equal(utils.fromWei(st.pledges[12].amount), 0); assert.equal(utils.fromWei(st.pledges[12].amount), 0);
}).timeout(6000); });
it('original owner should recover the remaining funds', async () => { it('original owner should recover the remaining funds', async () => {
await liquidPledging.withdraw(1, utils.toWei(0.5), { from: giver1 }); const pledges = [
await liquidPledging.withdraw(2, utils.toWei(0.31), { from: giver1 }); { amount: utils.toWei(0.5), id: 1 },
await liquidPledging.withdraw(4, utils.toWei(0.1), { $extraGas: 100000, from: giver1 }); { 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 }); // .substring is to remove the 0x prefix on the toHex result
await liquidPledging.withdraw(9, utils.toWei(0.01), { $extraGas: 100000, from: giver1 }); 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); const initialBalance = await web3.eth.getBalance(giver1);
await vault.multiConfirm([2, 3, 4, 5, 6]); await vault.multiConfirm([2, 3, 4, 5, 6]);
@ -306,7 +316,7 @@ describe('LiquidPledging Normal Operation', () => {
const collected = utils.fromWei(utils.toBN(finalBalance).sub(utils.toBN(initialBalance))); const collected = utils.fromWei(utils.toBN(finalBalance).sub(utils.toBN(initialBalance)));
assert.equal(collected, 0.95); assert.equal(collected, 0.95);
}).timeout(12000); });
it('Should make a donation and create giver', async () => { it('Should make a donation and create giver', async () => {
const oldNPledges = await liquidPledging.numberOfPledges(); const oldNPledges = await liquidPledging.numberOfPledges();
const oldNAdmins = await liquidPledging.numberOfPledgeAdmins(); const oldNAdmins = await liquidPledging.numberOfPledgeAdmins();
@ -321,11 +331,11 @@ describe('LiquidPledging Normal Operation', () => {
assert.equal(res[2], ''); assert.equal(res[2], '');
assert.equal(res[3], ''); assert.equal(res[3], '');
assert.equal(res[4], 259200); // default to 3 day commitTime assert.equal(res[4], 259200); // default to 3 day commitTime
}).timeout(6000); });
it('Should allow childProject with different parentProject owner', async () => { it('Should allow childProject with different parentProject owner', async () => {
const nAdminsBefore = await liquidPledging.numberOfPledgeAdmins(); const nAdminsBefore = await liquidPledging.numberOfPledgeAdmins();
await liquidPledging.addProject('Project3', 'URLProject3', adminProject3, 4, 86400, 0, { from: adminProject3 }); await liquidPledging.addProject('Project3', 'URLProject3', adminProject3, 4, 86400, 0, { from: adminProject3 });
const nAdmins = await liquidPledging.numberOfPledgeAdmins(); const nAdmins = await liquidPledging.numberOfPledgeAdmins();
assert.equal(nAdmins, utils.toDecimal(nAdminsBefore) + 1); assert.equal(nAdmins, utils.toDecimal(nAdminsBefore) + 1);
}).timeout(6000); });
}); });

127
test/NormalizePledge.js Normal file
View File

@ -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);
})
});

View File

@ -6,7 +6,7 @@ module.exports = async function(callback) {
try { try {
await callback(); await callback();
} catch (error) { } 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"); assert.ok(web3_error_thrown, "Transaction should fail");
}; };