@daostack/arc-experimental
Version:
A platform for building DAOs
423 lines (385 loc) • 20.1 kB
JavaScript
/**
helpers for tests
*/
const Avatar = artifacts.require("./Avatar.sol");
const DAOToken = artifacts.require("./DAOToken.sol");
const Reputation = artifacts.require("./Reputation.sol");
const AbsoluteVote = artifacts.require("./AbsoluteVote.sol");
const constants = require('./constants');
const GenesisProtocol = artifacts.require("./GenesisProtocol.sol");
const DAOFactory = artifacts.require("./DAOFactory.sol");
const SchemeMock = artifacts.require('./test/SchemeMock.sol');
const RewarderMock = artifacts.require('./test/RewarderMock.sol');
const Wallet = artifacts.require('./test/Wallet.sol');
const App = artifacts.require("./App.sol");
const Package = artifacts.require("./Package.sol");
var ImplementationDirectory = artifacts.require("./ImplementationDirectory.sol");
var Controller = artifacts.require("./Controller.sol");
const ContributionReward = artifacts.require("./ContributionReward.sol");
const Competition = artifacts.require("./Competition.sol");
const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol");
const SchemeRegistrar = artifacts.require("./SchemeRegistrar.sol");
const SchemeFactory = artifacts.require("./SchemeFactory.sol");
const UpgradeScheme = artifacts.require("./UpgradeScheme.sol");
const GenericScheme = artifacts.require("./GenericScheme.sol");
const ControllerUpgradeScheme = artifacts.require("./ControllerUpgradeScheme.sol");
const Auction4Reputation = artifacts.require("./Auction4Reputation.sol");
const LockingEth4Reputation = artifacts.require("./LockingEth4Reputation.sol");
const LockingToken4Reputation = artifacts.require("./LockingToken4Reputation.sol");
const ContinuousLocking4Reputation = artifacts.require("./ContinuousLocking4Reputation.sol");
const CL4RRedeemer = artifacts.require("./CL4RRedeemer.sol");
const ExternalLocking4Reputation = artifacts.require("./ExternalLocking4Reputation.sol");
const FixedReputationAllocation = artifacts.require("./FixedReputationAllocation.sol");
const GlobalConstraintRegistrar = artifacts.require("./GlobalConstraintRegistrar.sol");
const SignalScheme = artifacts.require("./SignalScheme.sol");
const ReputationFromToken = artifacts.require("./ReputationFromToken.sol");
const VoteInOrganization = artifacts.require("./VoteInOrganizationScheme.sol");
const ARCVotingMachineCallbacksMock = artifacts.require("./ARCVotingMachineCallbacksMock.sol");
const Join = artifacts.require("./Join.sol");
const FundingRequest = artifacts.require("./FundingRequest.sol");
const Dictator = artifacts.require("./Dictator.sol");
const ReputationAdmin = artifacts.require("./ReputationAdmin.sol");
const TokenTrade = artifacts.require("./TokenTrade.sol");
const ReputationTokenTrade = artifacts.require("./ReputationTokenTrade.sol");
const MAX_UINT_256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
const NULL_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000';
const SOME_HASH = '0x1000000000000000000000000000000000000000000000000000000000000000';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const SOME_ADDRESS = '0x1000000000000000000000000000000000000000';
class TestSetup {
constructor() {
}
}
class VotingMachine {
constructor() {
}
}
class Organization {
constructor() {
}
}
class Registration {
constructor() {
}
}
function getValueFromLogs(tx, arg, eventName, index=0) {
/**
*
* tx.logs look like this:
*
* [ { logIndex: 13,
* transactionIndex: 0,
* transactionHash: '0x999e51b4124371412924d73b60a0ae1008462eb367db45f8452b134e5a8d56c8',
* blockHash: '0xe35f7c374475a6933a500f48d4dfe5dce5b3072ad316f64fbf830728c6fe6fc9',
* blockNumber: 294,
* address: '0xd6a2a42b97ba20ee8655a80a842c2a723d7d488d',
* type: 'mined',
* event: 'NewOrg',
* args: { _avatar: '0xcc05f0cde8c3e4b6c41c9b963031829496107bbb' } } ]
*/
if (!tx.logs || !tx.logs.length) {
throw new Error('getValueFromLogs: Transaction has no logs');
}
if (eventName !== undefined) {
for (let i=0; i < tx.logs.length; i++) {
if (tx.logs[i].event === eventName) {
index = i;
break;
}
}
if (index === undefined) {
let msg = `getValueFromLogs: There is no event logged with eventName ${eventName}`;
throw new Error(msg);
}
} else {
if (index === undefined) {
index = tx.logs.length - 1;
}
}
let result = tx.logs[index].args[arg];
if (!result) {
let msg = `getValueFromLogs: This log does not seem to have a field "${arg}": ${tx.logs[index].args}`;
throw new Error(msg);
}
return result;
}
async function etherForEveryone(accounts) {
// give all web3.eth.accounts some ether
for (let i=0; i < 10; i++) {
await web3.eth.sendTransaction({to: accounts[i], from: accounts[0], value: web3.utils.toWei("0.1", "ether")});
}
}
function assertVMException(error) {
let condition = (
error.message.search('VM Exception') > -1
);
assert.isTrue(condition, 'Expected a VM Exception, got this instead:' + error.message);
}
const registrationAddVersionToPackege = async function (registration,version = [0,1,0]) {
var packageName = "DAOstack";
registration.packageName = packageName;
var implementationDirectory = await ImplementationDirectory.new();
await registration.packageInstance.addVersion(version,implementationDirectory.address,NULL_HASH);
await registration.app.setPackage(packageName,registration.packageInstance.address,version);
registration.daoToken = await DAOToken.new();
registration.reputation = await Reputation.new();
registration.avatar = await Avatar.new();
registration.controller = await Controller.new();
registration.schemeMock = await SchemeMock.new();
registration.wallet = await Wallet.new();
registration.contributionReward = await ContributionReward.new();
registration.competition = await Competition.new();
registration.contributionRewardExt = await ContributionRewardExt.new();
registration.schemeRegistrar = await SchemeRegistrar.new();
registration.schemeFactory = await SchemeFactory.new();
registration.upgradeScheme = await UpgradeScheme.new();
registration.genericScheme = await GenericScheme.new();
registration.controllerUpgradeScheme = await ControllerUpgradeScheme.new();
registration.auction4Reputation = await Auction4Reputation.new();
registration.lockingEth4Reputation = await LockingEth4Reputation.new();
registration.lockingToken4Reputation = await LockingToken4Reputation.new();
registration.continuousLocking4Reputation = await ContinuousLocking4Reputation.new();
registration.cL4RRedeemer = await CL4RRedeemer.new();
registration.externalLocking4Reputation = await ExternalLocking4Reputation.new();
registration.fixedReputationAllocation = await FixedReputationAllocation.new();
registration.globalConstraintRegistrar = await GlobalConstraintRegistrar.new();
registration.signalScheme = await SignalScheme.new();
registration.reputationFromToken = await ReputationFromToken.new();
registration.voteInOrganization = await VoteInOrganization.new();
registration.arcVotingMachineCallbacksMock = await ARCVotingMachineCallbacksMock.new();
registration.join = await Join.new();
registration.fundingRequest = await FundingRequest.new();
registration.rewarderMock = await RewarderMock.new();
registration.dictator = await Dictator.new();
registration.reputationAdmin = await ReputationAdmin.new();
registration.tokenTrade = await TokenTrade.new();
registration.reputationTokenTrade = await ReputationTokenTrade.new();
await implementationDirectory.setImplementation("DAOToken",registration.daoToken.address);
await implementationDirectory.setImplementation("Reputation",registration.reputation.address);
await implementationDirectory.setImplementation("Avatar",registration.avatar.address);
await implementationDirectory.setImplementation("Controller",registration.controller.address);
await implementationDirectory.setImplementation("SchemeMock",registration.schemeMock.address);
await implementationDirectory.setImplementation("RewarderMock",registration.rewarderMock.address);
await implementationDirectory.setImplementation("Wallet",registration.wallet.address);
await implementationDirectory.setImplementation("ContributionReward",registration.contributionReward.address);
await implementationDirectory.setImplementation("Competition",registration.competition.address);
await implementationDirectory.setImplementation("ContributionRewardExt",registration.contributionRewardExt.address);
await implementationDirectory.setImplementation("SchemeRegistrar",registration.schemeRegistrar.address);
await implementationDirectory.setImplementation("SchemeFactory",registration.schemeFactory.address);
await implementationDirectory.setImplementation("UpgradeScheme",registration.upgradeScheme.address);
await implementationDirectory.setImplementation("GenericScheme",registration.genericScheme.address);
await implementationDirectory.setImplementation("ControllerUpgradeScheme",registration.controllerUpgradeScheme.address);
await implementationDirectory.setImplementation("Auction4Reputation",registration.auction4Reputation.address);
await implementationDirectory.setImplementation("LockingEth4Reputation",registration.lockingEth4Reputation.address);
await implementationDirectory.setImplementation("LockingToken4Reputation",registration.lockingToken4Reputation.address);
await implementationDirectory.setImplementation("ContinuousLocking4Reputation",registration.continuousLocking4Reputation.address);
await implementationDirectory.setImplementation("CL4RRedeemer",registration.cL4RRedeemer.address);
await implementationDirectory.setImplementation("ExternalLocking4Reputation",registration.externalLocking4Reputation.address);
await implementationDirectory.setImplementation("FixedReputationAllocation",registration.fixedReputationAllocation.address);
await implementationDirectory.setImplementation("GlobalConstraintRegistrar",registration.globalConstraintRegistrar.address);
await implementationDirectory.setImplementation("SignalScheme",registration.signalScheme.address);
await implementationDirectory.setImplementation("ReputationFromToken",registration.reputationFromToken.address);
await implementationDirectory.setImplementation("VoteInOrganization",registration.voteInOrganization.address);
await implementationDirectory.setImplementation("ARCVotingMachineCallbacksMock",registration.arcVotingMachineCallbacksMock.address);
await implementationDirectory.setImplementation("Join",registration.join.address);
await implementationDirectory.setImplementation("FundingRequest",registration.fundingRequest.address);
await implementationDirectory.setImplementation("Dictator",registration.dictator.address);
await implementationDirectory.setImplementation("ReputationAdmin",registration.reputationAdmin.address);
await implementationDirectory.setImplementation("TokenTrade",registration.tokenTrade.address);
await implementationDirectory.setImplementation("ReputationTokenTrade",registration.reputationTokenTrade.address);
registration.implementationDirectory = implementationDirectory;
return registration;
};
const registerImplementation = async function (version = [0,1,0]) {
var registration = new Registration();
registration.packageInstance = await Package.new();
registration.app = await App.new();
registration = await registrationAddVersionToPackege(registration,version);
registration.daoFactory = await DAOFactory.new();
await registration.daoFactory.initialize(registration.app.address);
return registration;
};
const setupAbsoluteVote = async function (voteOnBehalf=NULL_ADDRESS, precReq=50 ) {
var votingMachine = new VotingMachine();
votingMachine.absoluteVote = await AbsoluteVote.new();
// register some parameters
await votingMachine.absoluteVote.setParameters( precReq, voteOnBehalf);
votingMachine.params = await votingMachine.absoluteVote.getParametersHash( precReq, voteOnBehalf);
return votingMachine;
};
const getSchemeAddress = async function (daoFactoryAddress,daoFactoryTx) {
var daoFactory = await DAOFactory.at(daoFactoryAddress);
var address;
await daoFactory.getPastEvents('SchemeInstance', {
fromBlock: daoFactoryTx.blockNumber,
toBlock: 'latest'
})
.then(function(events){
address = events[0].args._scheme;
});
return address;
};
const setupGenesisProtocol = async function (
accounts,
token,
voteOnBehalf = NULL_ADDRESS,
_queuedVoteRequiredPercentage=50,
_queuedVotePeriodLimit=60,
_boostedVotePeriodLimit=60,
_preBoostedVotePeriodLimit =0,
_thresholdConst=2000,
_quietEndingPeriod=0,
_proposingRepReward=60,
_votersReputationLossRatio=10,
_minimumDaoBounty=15,
_daoBountyConst=10,
_activationTime=0
) {
var votingMachine = new VotingMachine();
votingMachine.genesisProtocol = await GenesisProtocol.new(token,{gas: constants.ARC_GAS_LIMIT});
// set up a reputation system
votingMachine.reputationArray = [20, 10 ,70];
// register some parameters
votingMachine.uintArray = [_queuedVoteRequiredPercentage,
_queuedVotePeriodLimit,
_boostedVotePeriodLimit,
_preBoostedVotePeriodLimit,
_thresholdConst,
_quietEndingPeriod,
_proposingRepReward,
_votersReputationLossRatio,
_minimumDaoBounty,
_daoBountyConst,
_activationTime];
votingMachine.voteOnBehalf = voteOnBehalf;
votingMachine.params = await votingMachine.genesisProtocol.getParametersHash([_queuedVoteRequiredPercentage,
_queuedVotePeriodLimit,
_boostedVotePeriodLimit,
_preBoostedVotePeriodLimit,
_thresholdConst,
_quietEndingPeriod,
_proposingRepReward,
_votersReputationLossRatio,
_minimumDaoBounty,
_daoBountyConst,
_activationTime],voteOnBehalf);
return votingMachine;
};
const setupOrganizationWithArraysDAOFactory = async function (proxyAdmin,
accounts,
registration,
daoFactoryOwner,
founderToken,
founderReputation,
cap=0,
schemesNames,
schemesData,
schemesInitilizeDataLens,
permissions,
metaData) {
var org = new Organization();
var nativeTokenData = await new web3.eth.Contract(registration.daoToken.abi)
.methods
.initialize("TEST","TST",cap,registration.daoFactory.address)
.encodeABI();
var encodedForgeOrgParams = web3.eth.abi.encodeParameters(['string','bytes','address[]','uint256[]','uint256[]','uint64[3]'],
["testOrg",nativeTokenData,daoFactoryOwner,founderToken,founderReputation,[0,0,0]]);
var encodedSetSchemesParams = web3.eth.abi.encodeParameters(['bytes32[]','bytes','uint256[]','bytes4[]','string'],
[schemesNames,schemesData,schemesInitilizeDataLens,permissions,metaData]);
var tx = await registration.daoFactory.forgeOrg(encodedForgeOrgParams,
encodedSetSchemesParams,
{from:proxyAdmin});
assert.equal(tx.logs[4].event, "NewOrg");
var avatarAddress = tx.logs[4].args._avatar;
org.avatar = await Avatar.at(avatarAddress);
var tokenAddress = await org.avatar.nativeToken();
org.token = await DAOToken.at(tokenAddress);
var reputationAddress = await org.avatar.nativeReputation();
org.reputation = await Reputation.at(reputationAddress);
return [org,tx];
};
const checkVoteInfo = async function(absoluteVote,proposalId, voterAddress, _voteInfo) {
let voteInfo;
voteInfo = await absoluteVote.voteInfo(proposalId, voterAddress);
// voteInfo has the following structure
// int256 vote;
assert.equal(voteInfo[0].toNumber(), _voteInfo[0]);
// uint256 reputation;
assert.equal(voteInfo[1].toNumber(), _voteInfo[1]);
};
async function getProposalId(tx,contract,eventName) {
var proposalId;
await contract.getPastEvents(eventName, {
fromBlock: tx.blockNumber,
toBlock: 'latest'
})
.then(function(events){
proposalId = events[0].args._proposalId;
});
return proposalId;
}
// const increaseTime = async function (addSeconds) {
// web3.currentProvider.sendAsync({
// jsonrpc: '2.0',
// method: 'evm_increaseTime',
// params: [addSeconds],
// id: new Date().getSeconds()
// }, (err) => {
// if (!err) {
// web3.currentProvider.send({
// jsonrpc: '2.0',
// method: 'evm_mine',
// params: [],
// id: new Date().getSeconds()
// });
// }
// });
// }
// Increases testrpc time by the passed duration in seconds
const increaseTime = async function(duration) {
const id = await Date.now();
web3.providers.HttpProvider.prototype.sendAsync = web3.providers.HttpProvider.prototype.send;
return new Promise((resolve, reject) => {
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_increaseTime',
params: [duration],
id: id,
}, err1 => {
if (err1) return reject(err1);
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_mine',
id: id + 1,
}, (err2, res) => {
return err2 ? reject(err2) : resolve(res);
});
});
});
};
const concatBytes = function (bytes1, bytes2) {
return bytes1 + (bytes2.slice(2));
};
const getBytesLength = function (bytes) {
return Number(web3.utils.toBN(Number(bytes.slice(2).length) / 2));
};
module.exports = { MAX_UINT_256,
NULL_HASH,
SOME_HASH,
NULL_ADDRESS,
SOME_ADDRESS,
TestSetup,
assertVMException,
registerImplementation,
setupOrganizationWithArraysDAOFactory,
getBytesLength,
getValueFromLogs,
increaseTime,
setupAbsoluteVote,
setupGenesisProtocol,
etherForEveryone,
checkVoteInfo,
registrationAddVersionToPackege,
concatBytes,
getSchemeAddress,
getProposalId};