UNPKG

@daostack/arc-experimental

Version:

A platform for building DAOs

433 lines (378 loc) 20 kB
const helpers = require("./helpers"); const Join = artifacts.require("./Join.sol"); const FundingRequest = artifacts.require("./FundingRequest.sol"); const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); const Redeemer = artifacts.require("./Redeemer.sol"); class JoinParams { constructor() { } } class FundingRequestParams { constructor() { } } const setupJoin = async function( accounts, genesisProtocol, token, _fundingToken, _minFeeToJoin, _memberReputation, _fundingGoal, _fundingGoalDeadline ) { var joinParams = new JoinParams(); if (genesisProtocol === true) { joinParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS); joinParams.initdata = await new web3.eth.Contract(registration.join.abi) .methods .initialize(helpers.NULL_ADDRESS, joinParams.votingMachine.genesisProtocol.address, joinParams.votingMachine.uintArray, joinParams.votingMachine.voteOnBehalf, helpers.NULL_HASH, _fundingToken, _minFeeToJoin, _memberReputation, _fundingGoal, _fundingGoalDeadline) .encodeABI(); } else { joinParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); joinParams.initdata = await new web3.eth.Contract(registration.join.abi) .methods .initialize(helpers.NULL_ADDRESS, joinParams.votingMachine.absoluteVote.address, [1,1,1,1,1,1,1,1,1,1,1], helpers.NULL_ADDRESS, joinParams.votingMachine.params, _fundingToken, _minFeeToJoin, _memberReputation, _fundingGoal, _fundingGoalDeadline) .encodeABI(); } return joinParams; }; const setupFundingRequest = async function( accounts, genesisProtocol, token, externalToken) { var fundingRequestParams = new FundingRequestParams(); if (genesisProtocol === true) { fundingRequestParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS); fundingRequestParams.initdata = await new web3.eth.Contract(registration.fundingRequest.abi) .methods .initialize(helpers.NULL_ADDRESS, fundingRequestParams.votingMachine.genesisProtocol.address, fundingRequestParams.votingMachine.uintArray, fundingRequestParams.votingMachine.voteOnBehalf, helpers.NULL_HASH, externalToken ) .encodeABI(); } else { fundingRequestParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); fundingRequestParams.initdata = await new web3.eth.Contract(registration.fundingRequest.abi) .methods .initialize(helpers.NULL_ADDRESS, fundingRequestParams.votingMachine.absoluteVote.address, [1,1,1,1,1,1,1,1,1,1,1], helpers.NULL_ADDRESS, fundingRequestParams.votingMachine.params, externalToken ) .encodeABI(); } return fundingRequestParams; }; var registration; const setup = async function (accounts, setupJAQProposal=true, ethFunding = false, genesisProtocol = false, tokenAddress=helpers.NULL_ADDRESS, minFeeToJoin = 100, memberReputation = 100, fundingGoal = 1000, fundingGoalDeadline = 3000) { var testSetup = new helpers.TestSetup(); testSetup.standardTokenMock = await ERC20Mock.new(accounts[0],100000); registration = await helpers.registerImplementation(); testSetup.reputationArray = [2000,4000,7000]; testSetup.proxyAdmin = accounts[5]; testSetup.fundingGoalDeadline = (await web3.eth.getBlock("latest")).timestamp + fundingGoalDeadline; testSetup.minFeeToJoin = minFeeToJoin; testSetup.memberReputation = memberReputation; testSetup.fundingGoal = fundingGoal; var fundPath = testSetup.standardTokenMock.address; if (ethFunding === true) { fundPath = helpers.NULL_ADDRESS; } testSetup.joinParams= await setupJoin( accounts, genesisProtocol, tokenAddress, fundPath, minFeeToJoin, memberReputation, fundingGoal, testSetup.fundingGoalDeadline); testSetup.fundingRequestParams = await setupFundingRequest( accounts, genesisProtocol, tokenAddress, fundPath); var permissions = "0x00000000"; [testSetup.org,tx] = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, accounts, registration, [accounts[0], accounts[1], accounts[2]], [1000,0,0], testSetup.reputationArray, 0, [web3.utils.fromAscii("Join"), web3.utils.fromAscii("FundingRequest")], helpers.concatBytes(testSetup.joinParams.initdata, testSetup.fundingRequestParams.initdata), [helpers.getBytesLength(testSetup.joinParams.initdata), helpers.getBytesLength(testSetup.fundingRequestParams.initdata)], [permissions, permissions], "metaData"); testSetup.join = await Join.at(tx.logs[6].args._scheme); testSetup.fundingRequest = await FundingRequest.at(tx.logs[8].args._scheme); if(setupJAQProposal) { await testSetup.standardTokenMock.transfer(accounts[3],10000); await testSetup.standardTokenMock.approve(testSetup.join.address,testSetup.fundingGoal,{from:accounts[3]}); let value = 0; if (ethFunding) { value = testSetup.fundingGoal; } tx = await testSetup.join.proposeToJoin( "description-hash", testSetup.fundingGoal, {value, from:accounts[3]}); var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); if (genesisProtocol === false) { await testSetup.joinParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); } else { await testSetup.joinParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); } } return testSetup; }; contract('FundingRequest', accounts => { it("initialize", async function() { var testSetup = await setup(accounts, false); assert.equal(await testSetup.fundingRequest.votingMachine(),testSetup.fundingRequestParams.votingMachine.absoluteVote.address); assert.equal(await testSetup.fundingRequest.fundingToken(),testSetup.standardTokenMock.address); }); it("can't propose before funded", async() => { var testSetup = await setup(accounts, false); try { await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin-1, "description-hash"); assert(false, "can't propose before funded"); } catch (ex) { helpers.assertVMException(ex); } }); it("propose log", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewFundingProposal"); assert.equal(tx.logs[0].args._avatar, testSetup.org.avatar.address); assert.equal(tx.logs[0].args._beneficiary, accounts[1]); assert.equal(tx.logs[0].args._amount, testSetup.minFeeToJoin-1); assert.equal(tx.logs[0].args._descriptionHash, "description-hash"); }); it("propose log null beneficiary", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( helpers.NULL_ADDRESS, testSetup.minFeeToJoin - 1, "description-hash"); assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewFundingProposal"); assert.equal(tx.logs[0].args._avatar, testSetup.org.avatar.address); assert.equal(tx.logs[0].args._beneficiary, accounts[0]); assert.equal(tx.logs[0].args._amount, testSetup.minFeeToJoin-1); assert.equal(tx.logs[0].args._descriptionHash, "description-hash"); }); it("execute proposal yes", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, (await web3.eth.getBlock("latest")).timestamp); }); it("execute proposal no", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,2,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, 0); }); it("redeem proposal", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, (await web3.eth.getBlock("latest")).timestamp); tx = await testSetup.fundingRequest.redeem(proposalId); assert.equal(tx.logs[0].event, "Redeem"); assert.equal(tx.logs[0].args._avatar, testSetup.org.avatar.address); assert.equal(tx.logs[0].args._proposalId, proposalId); assert.equal(tx.logs[0].args._beneficiary, accounts[1]); assert.equal(tx.logs[0].args._amount, testSetup.minFeeToJoin - 1); assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), testSetup.minFeeToJoin - 1); proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, 0); assert.equal(proposal.amount, 0); }); it("redeem proposal + genesisProtocol", async function() { var testSetup = await setup(accounts,true,false,true); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); var arcUtils = await Redeemer.new(); tx = await arcUtils.redeemFundingRequest(testSetup.fundingRequest.address, testSetup.fundingRequestParams.votingMachine.genesisProtocol.address, proposalId, accounts[2]); await testSetup.fundingRequest.getPastEvents('Redeem', { fromBlock: tx.blockNumber, toBlock: 'latest' }) .then(function(events){ assert.equal(events.length,0); }); await testSetup.fundingRequestParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, (await web3.eth.getBlock("latest")).timestamp); tx = await arcUtils.redeemFundingRequest(testSetup.fundingRequest.address, testSetup.fundingRequestParams.votingMachine.genesisProtocol.address, proposalId, accounts[2]); await testSetup.fundingRequest.getPastEvents('Redeem', { fromBlock: tx.blockNumber, toBlock: 'latest' }) .then(function(events){ assert.equal(events[0].event,"Redeem"); assert.equal(events[0].args._avatar, testSetup.org.avatar.address); assert.equal(events[0].args._proposalId, proposalId); assert.equal(events[0].args._beneficiary, accounts[1]); assert.equal(events[0].args._amount, testSetup.minFeeToJoin - 1); }); assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), testSetup.minFeeToJoin - 1); proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, 0); assert.equal(proposal.amount, 0); }); it("redeem proposal eth", async function() { var testSetup = await setup(accounts, true, true); var balanceBefore = await web3.eth.getBalance(accounts[3]); let tx = await testSetup.fundingRequest.propose( accounts[3], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, (await web3.eth.getBlock("latest")).timestamp); tx = await testSetup.fundingRequest.redeem(proposalId); assert.equal(tx.logs[0].event, "Redeem"); assert.equal(tx.logs[0].args._avatar, testSetup.org.avatar.address); assert.equal(tx.logs[0].args._proposalId, proposalId); assert.equal(tx.logs[0].args._beneficiary, accounts[3]); assert.equal(tx.logs[0].args._amount, testSetup.minFeeToJoin - 1); var BN = web3.utils.BN; var a = new BN(balanceBefore); var b = new BN(testSetup.minFeeToJoin - 1); var expectedBalance = await a.add(b).toString(); assert.equal((await web3.eth.getBalance(accounts[3])).toString(),expectedBalance.toString()); proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, 0); assert.equal(proposal.amount, 0); }); it("can't redeem before proposal passed", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); try { tx = await testSetup.fundingRequest.redeem(proposalId); assert(false, "can't redeem before passed"); } catch (ex) { helpers.assertVMException(ex); } assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), 0); }); it("don't redeem failed proposal", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,2,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, 0); try { tx = await testSetup.fundingRequest.redeem(proposalId); assert(false, "can't redeem failed proposal"); } catch (ex) { helpers.assertVMException(ex); } assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), 0); }); it("can't redeem proposal twice", async function() { var testSetup = await setup(accounts); let tx = await testSetup.fundingRequest.propose( accounts[1], testSetup.minFeeToJoin - 1, "description-hash"); let proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.fundingRequestParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); var proposal = await testSetup.fundingRequest.proposals(proposalId); assert.equal(proposal.executionTime, (await web3.eth.getBlock("latest")).timestamp); tx = await testSetup.fundingRequest.redeem(proposalId); assert.equal(tx.logs[0].event, "Redeem"); assert.equal(tx.logs[0].args._avatar, testSetup.org.avatar.address); assert.equal(tx.logs[0].args._proposalId, proposalId); assert.equal(tx.logs[0].args._beneficiary, accounts[1]); assert.equal(tx.logs[0].args._amount, testSetup.minFeeToJoin - 1); assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), testSetup.minFeeToJoin - 1); try { tx = await testSetup.fundingRequest.redeem(proposalId); assert(false, "can't redeem proposal twice"); } catch (ex) { helpers.assertVMException(ex); } assert.equal((await testSetup.standardTokenMock.balanceOf(accounts[1])), testSetup.minFeeToJoin - 1); }); });