@daostack/arc-experimental
Version:
A platform for building DAOs
406 lines (362 loc) • 18.5 kB
JavaScript
const helpers = require("./helpers");
const { NULL_ADDRESS } = require("./helpers");
const TokenTrade = artifacts.require('./TokenTrade.sol');
const ERC20Mock = artifacts.require("./ERC20Mock.sol");
class TokenTradeParams {
constructor() {
}
}
var registration;
const setupTokenTradeParams = async function(
accounts,
genesisProtocol,
token
) {
var tokenTradeParams = new TokenTradeParams();
if (genesisProtocol === true) {
tokenTradeParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS);
tokenTradeParams.initdata = await new web3.eth.Contract(registration.tokenTrade.abi)
.methods
.initialize(
helpers.NULL_ADDRESS,
tokenTradeParams.votingMachine.genesisProtocol.address,
tokenTradeParams.votingMachine.uintArray,
tokenTradeParams.votingMachine.voteOnBehalf,
helpers.NULL_HASH
).encodeABI();
} else {
tokenTradeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50);
tokenTradeParams.initdata = await new web3.eth.Contract(registration.tokenTrade.abi)
.methods
.initialize(
helpers.NULL_ADDRESS,
tokenTradeParams.votingMachine.absoluteVote.address,
[],
helpers.NULL_ADDRESS,
tokenTradeParams.votingMachine.params
).encodeABI();
}
return tokenTradeParams;
};
const setup = async function (accounts,reputationAccount=0,genesisProtocol = false,tokenAddress=0) {
var testSetup = new helpers.TestSetup();
registration = await helpers.registerImplementation();
testSetup.reputationArray = [20,10,70];
var account2;
if (reputationAccount === 0) {
account2 = accounts[2];
} else {
account2 = reputationAccount;
}
testSetup.proxyAdmin = accounts[5];
testSetup.tokenTradeParams= await setupTokenTradeParams(
accounts,
genesisProtocol,
tokenAddress
);
var permissions = "0x0000001f";
[] = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin,
accounts,
registration,
[],
accounts[1],
account2],
[],
testSetup.reputationArray,
0,
[],
testSetup.tokenTradeParams.initdata,
[],
[],
"metaData"
);
testSetup.tokenTrade = await TokenTrade.at(await helpers.getSchemeAddress(registration.daoFactory.address,tx));
testSetup.standardTokenMock = await ERC20Mock.new(accounts[0],10000);
return testSetup;
};
contract('TokenTrade', function(accounts) {
before(function() {
helpers.etherForEveryone(accounts);
});
it("proposeTokenTrade log", async function() {
var testSetup = await setup(accounts);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 10000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
var tx = await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
assert.equal(tx.logs.length, 1);
assert.equal(tx.logs[0].event, "TokenTradeProposed");
assert.equal(tx.logs[0].args._beneficiary, accounts[0]);
assert.equal(tx.logs[0].args._descriptionHash, helpers.NULL_HASH);
assert.equal(tx.logs[0].args._sendToken, testSetup.standardTokenMock.address);
assert.equal(tx.logs[0].args._sendTokenAmount, 100);
assert.equal(tx.logs[0].args._receiveToken, testSetup.standardTokenMock.address);
assert.equal(tx.logs[0].args._receiveTokenAmount, 101);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 9900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
});
it("proposeTokenTrade should fail if tokens aren't transferred", async function() {
var testSetup = await setup(accounts);
try {
await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
assert(false, "proposing should fail if token transfer fails");
} catch(error) {
helpers.assertVMException(error);
}
});
it("proposeTokenTrade should fail if token not specified or amount is 0", async function() {
var testSetup = await setup(accounts);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
try {
await testSetup.tokenTrade.proposeTokenTrade(
NULL_ADDRESS,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
assert(false, "proposing should fail if send token is null");
} catch(error) {
helpers.assertVMException(error);
}
try {
await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
NULL_ADDRESS,
101,
helpers.NULL_HASH
);
assert(false, "proposing should fail if receive token is null");
} catch(error) {
helpers.assertVMException(error);
}
try {
await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
0,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
assert(false, "proposing should fail if send token amount is 0");
} catch(error) {
helpers.assertVMException(error);
}
try {
await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
0,
helpers.NULL_HASH
);
assert(false, "proposing should fail if send token amount is 0");
} catch(error) {
helpers.assertVMException(error);
}
});
it("execute proposal - fail - proposal should be deleted and funds returned", async function() {
var testSetup = await setup(accounts);
await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address, 5000);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
var tx = await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
var proposalId = await helpers.getValueFromLogs(tx, '_proposalId');
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 4900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
var proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, testSetup.standardTokenMock.address);
await testSetup.tokenTradeParams.votingMachine.absoluteVote.vote(proposalId,0,0,helpers.NULL_ADDRESS,{from:accounts[2]});
tx = await testSetup.tokenTrade.execute(proposalId);
proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, NULL_ADDRESS);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
await testSetup.tokenTrade.getPastEvents("TokenTradeProposalExecuted", {
fromBlock: tx.blockNumber,
toBlock: 'latest'
}).then(function(events){
assert.equal(events.length, 0);
});
});
it("execute proposeVote - pass - proposal executed and deleted", async function() {
var testSetup = await setup(accounts);
await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address, 5000);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
var tx = await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
var proposalId = await helpers.getValueFromLogs(tx, '_proposalId');
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 4900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
var proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, testSetup.standardTokenMock.address);
await testSetup.tokenTradeParams.votingMachine.absoluteVote.vote(proposalId, 1, 0, helpers.NULL_ADDRESS, {from:accounts[2]});
tx = await testSetup.tokenTrade.execute(proposalId);
proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, NULL_ADDRESS);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 4999);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5001);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
await testSetup.tokenTrade.getPastEvents("TokenTradeProposalExecuted", {
fromBlock: tx.blockNumber,
toBlock: 'latest'
}).then(function(events){
assert.equal(events[0].event, "TokenTradeProposalExecuted");
assert.equal(events[0].args._avatar, testSetup.org.avatar.address);
assert.equal(events[0].args._proposalId, proposalId);
assert.equal(events[0].args._beneficiary, accounts[0]);
assert.equal(events[0].args._sendToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._sendTokenAmount, 100);
assert.equal(events[0].args._receiveToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._receiveTokenAmount, 101);
});
});
it("execute proposal - pass - proposal should pass without execution if DAO doesn't have enough tokens", async function() {
var testSetup = await setup(accounts);
await testSetup.standardTokenMock.transfer(accounts[1], 5000);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 0);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
var tx = await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
var proposalId = await helpers.getValueFromLogs(tx, '_proposalId');
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 4900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
var proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, testSetup.standardTokenMock.address);
tx = await testSetup.tokenTradeParams.votingMachine.absoluteVote.vote(proposalId, 1, 0, helpers.NULL_ADDRESS, {from:accounts[2]});
proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.passed, true);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 4900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
await testSetup.tokenTrade.getPastEvents("TokenTradeProposalExecuted", {
fromBlock: tx.blockNumber,
toBlock: 'latest'
}).then(function(events){
assert.equal(events.length, 0);
});
await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address, 5000, {from: accounts[1]});
tx = await testSetup.tokenTrade.execute(proposalId);
proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, NULL_ADDRESS);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 4999);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5001);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
await testSetup.tokenTrade.getPastEvents("TokenTradeProposalExecuted", {
fromBlock: tx.blockNumber,
toBlock: 'latest'
}).then(function(events){
assert.equal(events[0].event, "TokenTradeProposalExecuted");
assert.equal(events[0].args._avatar, testSetup.org.avatar.address);
assert.equal(events[0].args._proposalId, proposalId);
assert.equal(events[0].args._beneficiary, accounts[0]);
assert.equal(events[0].args._sendToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._sendTokenAmount, 100);
assert.equal(events[0].args._receiveToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._receiveTokenAmount, 101);
});
});
it("execute proposal - pass - proposal cannot execute before passed/ twice", async function() {
var testSetup = await setup(accounts);
await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address, 5000);
await testSetup.standardTokenMock.approve(testSetup.tokenTrade.address, 100);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
var tx = await testSetup.tokenTrade.proposeTokenTrade(
testSetup.standardTokenMock.address,
100,
testSetup.standardTokenMock.address,
101,
helpers.NULL_HASH
);
var proposalId = await helpers.getValueFromLogs(tx, '_proposalId');
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 5000);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 4900);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 100);
var proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, testSetup.standardTokenMock.address);
try {
await testSetup.tokenTrade.execute(proposalId);
assert(false, "cannot execute before passed");
} catch(error) {
helpers.assertVMException(error);
}
await testSetup.tokenTradeParams.votingMachine.absoluteVote.vote(proposalId, 1, 0, helpers.NULL_ADDRESS, {from:accounts[2]});
tx = await testSetup.tokenTrade.execute(proposalId);
proposal = await testSetup.tokenTrade.proposals(proposalId);
assert.equal(proposal.sendToken, NULL_ADDRESS);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.org.avatar.address), 4999);
assert.equal(await testSetup.standardTokenMock.balanceOf(accounts[0]), 5001);
assert.equal(await testSetup.standardTokenMock.balanceOf(testSetup.tokenTrade.address), 0);
await testSetup.tokenTrade.getPastEvents("TokenTradeProposalExecuted", {
fromBlock: tx.blockNumber,
toBlock: 'latest'
}).then(function(events){
assert.equal(events[0].event, "TokenTradeProposalExecuted");
assert.equal(events[0].args._avatar, testSetup.org.avatar.address);
assert.equal(events[0].args._proposalId, proposalId);
assert.equal(events[0].args._beneficiary, accounts[0]);
assert.equal(events[0].args._sendToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._sendTokenAmount, 100);
assert.equal(events[0].args._receiveToken, testSetup.standardTokenMock.address);
assert.equal(events[0].args._receiveTokenAmount, 101);
});
try {
await testSetup.tokenTrade.execute(proposalId);
assert(false, "cannot execute twice");
} catch(error) {
helpers.assertVMException(error);
}
});
it("cannot init twice", async function() {
var testSetup = await setup(accounts);
try {
await testSetup.tokenTrade.initialize(
testSetup.org.avatar.address,
accounts[0],
[],
helpers.NULL_ADDRESS,
helpers.SOME_HASH
);
assert(false, "cannot init twice");
} catch(error) {
helpers.assertVMException(error);
}
});
});