UNPKG

lpp-dac

Version:

LiquidPledging plugin contract for dacs to issue a custom MiniMe Token for donations.

360 lines (295 loc) 12.2 kB
/* eslint-env mocha */ /* eslint-disable no-await-in-loop */ const Ganache = require('ganache-cli'); const chai = require('chai'); const { LPPDac, LPPDacFactory } = require('../index'); const { Kernel, ACL, test } = require('giveth-liquidpledging'); const { MiniMeToken, MiniMeTokenFactory, MiniMeTokenState } = require('minimetoken'); const Web3 = require('web3'); const { assertFail, deployLP } = test; const assert = chai.assert; describe('LPPDac test', function() { this.timeout(0); let web3; let accounts; let liquidPledging; let liquidPledgingState; let vault; let dac; let dac2; let minime; let minime2; let minimeTokenState; let giver1; let giver2; let project1; let project2; let project3; let dacOwner1; let dacOwner2; let ganache; let acl; let kernel; before(async () => { ganache = Ganache.server({ ws: true, gasLimit: 9700000, total_accounts: 10, }); ganache.listen(8545, '127.0.0.1', err => {}); web3 = new Web3('ws://localhost:8545'); accounts = await web3.eth.getAccounts(); project1 = accounts[2]; dacOwner1 = accounts[3]; dacOwner2 = accounts[4]; project2 = accounts[5]; giver2 = accounts[6]; project3 = accounts[7]; const deployment = await deployLP(web3); giver1 = deployment.giver1; vault = deployment.vault; liquidPledging = deployment.liquidPledging; liquidPledgingState = deployment.liquidPledgingState; giverToken = deployment.token; // set permissions kernel = new Kernel(web3, await liquidPledging.kernel()); acl = new ACL(web3, await kernel.acl()); await acl.createPermission( accounts[0], vault.$address, await vault.CANCEL_PAYMENT_ROLE(), accounts[0], { $extraGas: 200000 }, ); await acl.createPermission( accounts[0], vault.$address, await vault.CONFIRM_PAYMENT_ROLE(), accounts[0], { $extraGas: 200000 }, ); await giverToken.mint(giver2, web3.utils.toWei('1000')); await giverToken.approve(liquidPledging.$address, '0xFFFFFFFFFFFFFFFF', { from: giver2 }); }); after(done => { ganache.close(); done(); setTimeout(process.exit, 2000); }); it('Should deploy LPPDac contract and add delegate to liquidPledging', async () => { const tokenFactory = await MiniMeTokenFactory.new(web3, { gas: 3000000 }); factory = await LPPDacFactory.new(web3, kernel.$address, tokenFactory.$address, { gas: 6000000, }); await acl.grantPermission(factory.$address, acl.$address, await acl.CREATE_PERMISSIONS_ROLE(), { $extraGas: 200000, }); await acl.grantPermission( factory.$address, liquidPledging.$address, await liquidPledging.PLUGIN_MANAGER_ROLE(), { $extraGas: 200000 }, ); const dacApp = await LPPDac.new(web3); await kernel.setApp( await kernel.APP_BASES_NAMESPACE(), await factory.DAC_APP_ID(), dacApp.$address, { $extraGas: 200000 }, ); await factory.newDac('DAC 1', 'URL1', 0, 'DAC 1 Token', 'DAC1', { from: dacOwner1, }); // pledgeAdmin #1 const lpState = await liquidPledgingState.getState(); assert.equal(lpState.admins.length, 2); const lpManager = lpState.admins[1]; dac = new LPPDac(web3, lpManager.plugin); assert.isAbove(Number(await dac.getInitializationBlock()), 0); minime = new MiniMeToken(web3, await dac.dacToken()); minimeTokenState = new MiniMeTokenState(minime); assert.equal(lpManager.type, 'Delegate'); assert.equal(lpManager.addr, dac.$address); assert.equal(lpManager.name, 'DAC 1'); assert.equal(lpManager.commitTime, '0'); assert.equal(await dac.liquidPledging(), liquidPledging.$address); const tState = await minimeTokenState.getState(); assert.equal(tState.totalSupply, 0); assert.equal(tState.name, 'DAC 1 Token'); assert.equal(tState.controller, dac.$address); assert.equal(await minime.symbol(), 'DAC1'); }); it('Should not generate tokens when added as pledge delegate', async function() { await liquidPledging.addGiver('Giver1', 'URL', 0, 0x0, { from: giver1 }); // pledgeAdmin #2 await liquidPledging.donate(2, 1, giverToken.$address, 1000, { from: giver1 }); const st = await liquidPledgingState.getState(); assert.equal(st.pledges[2].amount, 1000); assert.equal(st.pledges[2].token, giverToken.$address); assert.equal(st.pledges[2].owner, 2); const giverTokenBal = await minime.balanceOf(giver1); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 0); assert.equal(totalTokenSupply, 0); }); it('Should send tokens to giver when committing to project', async function() { // create project await liquidPledging.addProject('Project1', 'URL', project1, 0, 0, 0x0, { from: project1, $extraGas: 100000, }); // pledgeAdmin #3 // delegate to project1 await dac.transfer(2, 1000, 3, { from: dacOwner1, $extraGas: 100000 }); // set the time const now = Math.floor(new Date().getTime() / 1000); await liquidPledging.setMockedTime(now, { $extraGas: 100000 }); await liquidPledging.normalizePledge(3, { $extraGas: 100000 }); const st = await liquidPledgingState.getState(); assert.equal(st.pledges[4].amount, 1000); assert.equal(st.pledges[4].owner, 3); assert.equal(st.pledges[3].amount, 0); assert.equal(st.pledges[2].amount, 0); const giverTokenBal = await minime.balanceOf(giver1); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 1000); assert.equal(totalTokenSupply, 1000); }); it('Should not send tokens to giver when revoking pledge from delegate', async function() { // donate to delegate1 await liquidPledging.donate(2, 1, giverToken.$address, 1000, { from: giver1, $extraGas: 100000, }); await liquidPledging.transfer(2, 2, 1000, 2, { from: giver1, $extraGas: 100000 }); const st = await liquidPledgingState.getState(); assert.equal(st.pledges[1].amount, 1000); assert.equal(st.pledges[1].owner, 2); const giverTokenBal = await minime.balanceOf(giver1); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 1000); assert.equal(totalTokenSupply, 1000); }); it('Should only generate tokens for first delegate in chain.', async function() { await factory.newDac('DAC 2', 'URL2', 0, 'DAC 2 Token', 'DAC2', { from: dacOwner2, }); // pledgeAdmin #4 const admin = await liquidPledging.getPledgeAdmin(4); dac2 = new LPPDac(web3, admin.plugin); minime2 = new MiniMeToken(web3, await dac2.dacToken()); // add delegate 1 await liquidPledging.transfer(2, 1, 1000, 1, { from: giver1, $extraGas: 100000 }); // add delegate 2 await dac.transfer(2, 1000, 4, { from: dacOwner1, $extraGas: 100000 }); // delegate to project1 await dac2.transfer(5, 1000, 3, { from: dacOwner2, $extraGas: 100000 }); // set the time const now = Math.floor(new Date().getTime() / 1000); await liquidPledging.setMockedTime(now, { $extraGas: 100000 }); await liquidPledging.normalizePledge(6, { $extraGas: 100000 }); const st = await liquidPledgingState.getState(); // console.log(JSON.stringify(st, null, 2)); assert.equal(st.pledges[4].amount, 1000); assert.equal(st.pledges[4].owner, 3); const giverTokenBal = await minime.balanceOf(giver1); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 2000); assert.equal(totalTokenSupply, 2000); const giverToken2Bal = await minime2.balanceOf(giver1); const totalToken2Supply = await minime2.totalSupply(); assert.equal(giverToken2Bal, 0); assert.equal(totalToken2Supply, 0); }); it('Should burn tokens if project is canceled', async function() { await liquidPledging.cancelProject(3, { from: project1, $extraGas: 100000 }); // set the time const now = Math.floor(new Date().getTime() / 1000); await liquidPledging.setMockedTime(now, { $extraGas: 100000 }); await liquidPledging.normalizePledge(4, { $extraGas: 100000 }); const giverTokenBal = await minime.balanceOf(giver1); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 1000); assert.equal(totalTokenSupply, 1000); }); it('Should not burn tokens for paid pledges if project is canceled', async function() { // create project await liquidPledging.addProject('Project2', 'URL', project2, 0, 0, 0x0, { from: project2, $extraGas: 100000, }); // pledgeAdmin #5 await liquidPledging.addGiver('Giver2', '', 0, 0x0, { from: giver2, $extraGas: 100000 }); // pledgeAdmin #6 // donate to delegate1 await liquidPledging.donate(6, 1, giverToken.$address, 1000, { from: giver2, $extraGas: 100000, }); // delegate to project2 await dac.transfer(9, 1000, 5, { from: dacOwner1, $extraGas: 100000 }); // commit to project 2 await liquidPledging.transfer(6, 10, 1000, 5, { from: giver2, $extraGas: 100000 }); // withdraw await liquidPledging.withdraw(11, 1000, { from: project2, $extraGas: 100000 }); // cancel project2 await liquidPledging.cancelProject(5, { from: project2, $extraGas: 100000 }); // set the time const now = Math.floor(new Date().getTime() / 1000); await liquidPledging.setMockedTime(now, { $extraGas: 100000 }); await liquidPledging.normalizePledge(12, { $extraGas: 100000 }); const giverTokenBal = await minime.balanceOf(giver2); const totalTokenSupply = await minime.totalSupply(); assert.equal(giverTokenBal, 1000); assert.equal(totalTokenSupply, 2000); }); it('Should update delegate', async function() { await dac.update('new name', 'new url', 1010, { from: dacOwner1, $extraGas: 100000 }); const d = await liquidPledging.getPledgeAdmin(1); assert.equal(d.name, 'new name'); assert.equal(d.addr, dac.$address); assert.equal(d.url, 'new url'); assert.equal(d.commitTime, 1010); }); it('Should restrict admin to only specified params', async function() { const params = [ // id: 1 (arg 1) op: LTE(6) value: amount '0x0106000000000000000000000000000000000000000000000000000000000010', ]; // grant restricted Admin_Role to dacOwner2 await acl.grantPermissionP(dacOwner2, dac.$address, await dac.ADMIN_ROLE(), params, { from: dacOwner1, $extraGas: 100000, }); // should only be able to transfer <= 10 tokens await assertFail(dac.transfer(2, 100, 4, { from: dacOwner2, gas: 6700000 })); await dac.transfer(2, 10, 4, { from: dacOwner2, $extraGas: 100000 }); const st = await liquidPledgingState.getState(); assert.equal(990, st.pledges[2].amount); assert.equal(10, st.pledges[5].amount); // dacOwner2 should not be able to update dac await assertFail(dac.update('I can update', 'pwned', 0, { from: dacOwner2, gas: 6700000 })); }); it('Should transfer multiple pledges at once', async function() { await liquidPledging.addProject('Project3', 'URL', project1, 0, 0, 0x0, { from: project3, $extraGas: 100000, }); // pledgeAdmin #7 const pledges = [ { amount: 100, id: 2 }, { amount: 10, id: 5 }, { amount: 10, id: 2 }, { amount: 20, id: 2 }, ]; // .substring is to remove the 0x prefix on the toHex result const encodedPledges = pledges.map(p => { return ( '0x' + web3.utils.padLeft(web3.utils.toHex(p.amount).substring(2), 48) + web3.utils.padLeft(web3.utils.toHex(p.id).substring(2), 16) ); }); // dacOwner2 can only transfer < 10 for a given pledge await assertFail(dac.mTransfer(encodedPledges, 7, { from: dacOwner2, gas: 6700000 })); await dac.mTransfer(encodedPledges, 7, { from: dacOwner1, $extraGas: 400000 }); const st = await liquidPledgingState.getState(); const p = st.pledges[13]; assert.equal(p.amount, 140); assert.equal(p.intendedProject, 7); assert.equal(p.delegates[0].id, 1); }); });