Compare commits

..

17 Commits

Author SHA1 Message Date
eecb129bd5 Try to run bootstrap on travis
This basically tests the whole setup process
2019-08-09 18:54:52 +02:00
ddeeb5ffd7 Merge pull request #162 from 67P/dev/aragon_truffle
Remove Aragon CLI, document system deps
2019-08-09 18:38:40 +02:00
ae71691c5b Install Aragon CLI and Truffle on Travis 2019-08-09 18:26:38 +02:00
819fbc547a Add contract publish options
This removes most of the features we don't need/want and minimizes
prompts during the bootstrap process.
2019-08-09 18:18:36 +02:00
7236b04b4b Remove Aragon CLI, document system deps
In order to prevent regular issues with the notoriously npm-issue-ridden
Aragon CLI module, this removes it as a direct dependency and requires
it to be installed as a system dependency.

Also adds Truffle as a system dependency to the docs (which was missing
before).
2019-08-09 18:04:21 +02:00
f746470cf6 Merge pull request #161 from 67P/fix_typos
Fix a few typos in the README
2019-08-07 16:42:01 +02:00
Greg Karékinian
5452cf2dad Fix a few typos 2019-08-07 15:55:11 +02:00
3c08e3ecfc Merge pull request #160 from 67P/bugfix/packages-install-scripts
Fix package script command deploy:kit
2019-08-04 19:42:42 +02:00
6e8c994a0a Fix package script command deploy:kit 2019-08-04 19:37:31 +02:00
Haythem Sellami
fd844a00fd Test token app (#157)
* test token app
* update travis config
2019-07-31 15:17:38 +00:00
Haythem Sellami
eb4e06edf1 Contributor app tests (#143)
Adds tests for the contributor contract
2019-07-22 06:55:22 +00:00
4ae17aa36f Merge pull request #156 from haythem96/refactor-get-contract
Refactor get apps contract functions
2019-07-22 06:54:05 +00:00
e14cb0a77d refactor get apps contract functions 2019-07-20 15:06:17 +01:00
d92ad83379 Merge pull request #155 from 67P/bugfix/send-for-new-web3
Fix send-funds script to use new web3 API
2019-07-19 09:11:55 +00:00
fa3e99d404 Fix send-funds script to use new web3 API
The API changed with the recent aragon/truffle update.
2019-07-18 16:25:06 +02:00
4aa5f3aa89 Merge pull request #151 from 67P/chore/remove-ipfs-pinner
Remove IPFS pinner
2019-07-03 12:50:59 +02:00
2316e8f15a Remove IPFS pinner
The pinner now lives in its own npm package
2019-07-02 19:09:26 +02:00
28 changed files with 873 additions and 26261 deletions

View File

@@ -28,5 +28,6 @@ module.exports = {
named: 'always',
asyncArrow: 'always',
}],
'indent': ['error', 2]
}
}

View File

@@ -6,13 +6,29 @@ node_js:
sudo: false
dist: xenial
cache:
directories:
- node_modules
- apps/contribution/node_modules
- apps/contributor/node_modules
- apps/proposal/node_modules
- apps/token/node_modules
- apps/vault/node_modules
install:
- npm install -g @aragon/cli
- npm install -g truffle
- npm install
before_script:
- npm run devchain &
- ipfs daemon --offline &
script:
- npm run lint:wrapper
- npm run lint:contract-tests
# - yarn lint:contracts
- npm run test
- npm run bootstrap
branches:
only:

View File

@@ -14,6 +14,8 @@ framework](http://truffleframework.com/) for some things.
### Installation
#### App dependencies
All requirements are defined in `package.json`.
$ npm install
@@ -25,13 +27,20 @@ Each of the aragon apps are separate packages:
You can use `npm run install-all` to install all app dependencies at once.
#### Sytem dependencies
Aragon CLI and Truffle need to be installed on your sytem as well:
npm install -g @aragon/cli
npm install -g truffle
### Local development chain
For local development it is recommended to use
[ganache](http://truffleframework.com/ganache/) to run a local development
chain. Using the ganache simulator no full Ethereum node is required.
We use the default aragon-cli devchain command to confgure and run a local
We use the default aragon-cli devchain command to configure and run a local
development ganache.
$ npm run devchain (or aragon devchain --port 7545)
@@ -60,7 +69,7 @@ Ethereum RPC port.
$ npm run deploy:kit
$ npm run deploy:dao
4. Execute seeds to create demo contributors, contributons, etc. (optional)
4. Execute seeds to create demo contributors, contributions, etc. (optional)
$ npm run seeds
@@ -163,7 +172,7 @@ Creates and configures a new DAO instance.
or
$ npm run deploy:dao
KreditsKit address is load from `lib/addresses/KreditsKit.json` or can be
KreditsKit address is loaded from `lib/addresses/KreditsKit.json` or can be
configured through the `KREDITS_KIT` environment variable.
### deploy-apps.sh
@@ -198,7 +207,7 @@ make sure all apps and the KreditsKit are deployed, then create a new DAO:
## Upgradeable contracts
We use aragonOS for upgradeablity of the different contracts. Refer to the
We use aragonOS for upgradeability of the different contracts. Refer to the
[aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro)
for more details.

View File

@@ -60,23 +60,18 @@ contract Contribution is AragonApp {
initialized();
}
// TODO refactor into a single function
function getTokenContract() public view returns (address) {
function getContract(uint8 appId) public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
}
function getContributorContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[appId]);
}
function getContributorIdByAddress(address contributorAccount) public view returns (uint32) {
address contributor = getContributorContract();
address contributor = getContract(uint8(Apps.Contributor));
return ContributorInterface(contributor).getContributorIdByAddress(contributorAccount);
}
function getContributorAddressById(uint32 contributorId) public view returns (address) {
address contributor = getContributorContract();
address contributor = getContract(uint8(Apps.Contributor));
return ContributorInterface(contributor).getContributorAddressById(contributorId);
}
@@ -198,14 +193,14 @@ contract Contribution is AragonApp {
require(block.number >= c.confirmedAtBlock, 'NOT_CLAIMABLE');
c.claimed = true;
address token = getTokenContract();
address token = getContract(uint8(Apps.Token));
address contributorAccount = getContributorAddressById(c.contributorId);
uint256 amount = uint256(c.amount);
IToken(token).mintFor(contributorAccount, amount, contributionId);
emit ContributionClaimed(contributionId, c.contributorId, c.amount);
}
function exists(uint32 contributionId) view public returns (bool) {
function exists(uint32 contributionId) public view returns (bool) {
return contributions[contributionId].exists;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
"@aragon/cli": "^5.9.6"
},
"devDependencies": {
"@aragon/test-helpers": "^1.1.0",
"@aragon/test-helpers": "^2.0.0",
"eth-gas-reporter": "^0.2.0",
"ganache-cli": "^6.4.3",
"solidity-coverage": "^0.5.11"
@@ -26,10 +26,7 @@
"publish:minor": "aragon apm publish minor",
"publish:major": "aragon apm publish major",
"versions": "aragon apm versions",
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
"test:gas": "GAS_REPORTER=true npm test",
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
"test": "aragon contracts test"
},
"keywords": []
}

View File

@@ -41,19 +41,12 @@ contract Contributor is AragonApp {
initialized();
}
function getTokenContract() public view returns (address) {
function getContract(uint8 appId) public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[appId]);
}
function getContributionContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
}
function coreContributorsCount() view public returns (uint32) {
function coreContributorsCount() public view returns (uint32) {
uint32 count = 0;
for (uint32 i = 1; i <= contributorsCount; i++) {
if (isCoreTeam(i)) {
@@ -64,10 +57,13 @@ contract Contributor is AragonApp {
}
function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public auth(MANAGE_CONTRIBUTORS_ROLE) {
require(newAccount != address(0), "invalid new account address");
require(getContributorAddressById(id) == oldAccount, "contributor does not exist");
contributorIds[oldAccount] = 0;
contributorIds[newAccount] = id;
contributors[id].account = newAccount;
ContributorAccountUpdated(id, oldAccount, newAccount);
emit ContributorAccountUpdated(id, oldAccount, newAccount);
}
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
@@ -136,9 +132,9 @@ contract Contributor is AragonApp {
hashFunction = c.hashFunction;
hashSize = c.hashSize;
isCore = isCoreTeam(id);
address token = getTokenContract();
address token = getContract(uint8(Apps.Token));
balance = ITokenBalance(token).balanceOf(c.account);
address contribution = getContributionContract();
address contribution = getContract(uint8(Apps.Contribution));
totalKreditsEarned = IContributionBalance(contribution).totalKreditsEarnedByContributor(_id, true);
contributionsCount = IContributionBalance(contribution).balanceOf(c.account);
exists = c.exists;

View File

@@ -0,0 +1,16 @@
pragma solidity ^0.4.24;
import "@aragon/os/contracts/acl/ACL.sol";
import "@aragon/os/contracts/kernel/Kernel.sol";
import "@aragon/os/contracts/factory/DAOFactory.sol";
// You might think this file is a bit odd, but let me explain.
// We only use for now those imported contracts in our tests, which
// means Truffle will not compile them for us, because they are from
// an external dependency.
// solium-disable-next-line no-empty-blocks
contract Spoof {
// ...
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,10 +7,10 @@
"@aragon/cli": "^5.9.6"
},
"devDependencies": {
"@aragon/test-helpers": "^1.1.0",
"eth-gas-reporter": "^0.2.0",
"ganache-cli": "^6.4.3",
"solidity-coverage": "^0.5.11"
"solidity-coverage": "^0.5.11",
"@aragon/test-helpers": "^2.0.0"
},
"scripts": {
"start": "npm run start:aragon:ipfs",
@@ -26,10 +26,7 @@
"publish:minor": "aragon apm publish minor",
"publish:major": "aragon apm publish major",
"versions": "aragon apm versions",
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
"test:gas": "GAS_REPORTER=true npm test",
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
"test": "aragon contracts test"
},
"keywords": []
}

View File

@@ -1,5 +0,0 @@
// const Contributor = artifacts.require('Contributor.sol');
contract('Contributor', (_accounts) => {
it('should be tested');
});

View File

@@ -0,0 +1,170 @@
const namehash = require('ethers').utils.namehash;
// eslint-disable-next-line no-undef
const Contributor = artifacts.require("Contributor.sol");
// eslint-disable-next-line no-undef
const getContract = name => artifacts.require(name);
const { assertRevert } = require('@aragon/test-helpers/assertThrow');
const ZERO_ADDR = '0x0000000000000000000000000000000000000000';
contract('Contributor app', (accounts) => {
let kernelBase, aclBase, daoFactory, r, dao, acl, contributor;
const root = accounts[0];
const member1 = accounts[1];
// eslint-disable-next-line no-undef
before(async () => {
kernelBase = await getContract('Kernel').new(true); // petrify immediately
aclBase = await getContract('ACL').new();
daoFactory = await getContract('DAOFactory').new(kernelBase.address, aclBase.address, ZERO_ADDR);
r = await daoFactory.newDAO(root);
dao = getContract('Kernel').at(r.logs.filter(l => l.event == 'DeployDAO')[0].args.dao);
acl = getContract('ACL').at(await dao.acl());
//create dao mamnager permission for coin owner
await acl.createPermission(
root,
dao.address,
await dao.APP_MANAGER_ROLE(),
root,
{ from: root }
);
//get new app instance from DAO
const receipt = await dao.newAppInstance(
'0x1234',
(await Contributor.new()).address,
0x0,
false,
{ from: root }
);
contributor = Contributor.at(
receipt.logs.filter(l => l.event == 'NewAppProxy')[0].args.proxy
);
//apps id
let appsId = [];
appsId[0] = namehash("kredits-contribution");
appsId[1] = namehash("kredits-contributor");
appsId[2] = namehash("kredits-proposal");
appsId[3] = namehash("kredits-token");
//init contributor (app)
await contributor.initialize(root, appsId);
//create manage contributors role
await acl.createPermission(
root,
contributor.address,
await contributor.MANAGE_CONTRIBUTORS_ROLE(),
root,
{ from: root }
);
});
describe("Owner default permissions", async () => {
it('check owner is contributors manager', async () => {
let manageContributorPermission = await acl.hasPermission(root, contributor.address, await contributor.MANAGE_CONTRIBUTORS_ROLE());
// eslint-disable-next-line no-undef
assert.equal(manageContributorPermission, true);
});
});
describe("Add contributor", async () => {
let account = root;
let hashDigest = '0x0';
let hashFunction = 0;
let hashSize = 0;
it("should revert when add contributor from an address that does not have permission", async () => {
return assertRevert(async () => {
await contributor.addContributor(account, hashDigest, hashFunction, hashSize, { from: member1});
'sender does not have permission';
});
});
it('add contributor', async () => {
let contributorCount = await contributor.coreContributorsCount();
await contributor.addContributor(account, hashDigest, hashFunction, hashSize);
// eslint-disable-next-line no-undef
assert.equal(await contributor.addressExists(account), true);
let contributorCountAfter = await contributor.coreContributorsCount();
// eslint-disable-next-line no-undef
assert.equal(await contributorCountAfter.toNumber(), parseInt(contributorCount)+1);
});
it("should revert when add contributor with an address that already exist", async () => {
return assertRevert(async () => {
await contributor.addContributor(account, hashDigest, hashFunction, hashSize, { from: member1});
'address already exist';
});
});
});
describe("Update contributor", async () => {
let id;
let oldAccount;
let newAccount;
let hashDigest;
let hashFunction;
let hashSize;
// eslint-disable-next-line no-undef
before(async () => {
id = await contributor.coreContributorsCount();
oldAccount = root;
newAccount = member1;
hashDigest = '0x1000000000000000000000000000000000000000000000000000000000000000';
hashFunction = 1;
hashSize = 1;
});
it('update contributor account', async () => {
await contributor.updateContributorAccount(id.toNumber(), oldAccount, newAccount);
let contributorId = await contributor.getContributorIdByAddress(oldAccount);
// eslint-disable-next-line no-undef
assert.equal(contributorId.toNumber(), 0);
});
it("should revert when update contributor account from address that does not have permission", async () => {
return assertRevert(async () => {
await contributor.updateContributorAccount(id.toNumber(), oldAccount, newAccount, {from: member1});
'sender does not have permission';
});
});
it("should revert when update contributor account that does not exist", async () => {
return assertRevert(async () => {
await contributor.updateContributorAccount(id.toNumber(), accounts[3], newAccount);
'contributor does not exist';
});
});
it("should revert when update contributor account with address(0)", async () => {
return assertRevert(async () => {
await contributor.updateContributorAccount(id.toNumber(), oldAccount, ZERO_ADDR);
'contributor does not exist';
});
});
it('update contributor profile hash', async () => {
await contributor.updateContributorProfileHash(id.toNumber(), hashDigest, hashFunction, hashSize);
let contributorProfile = await contributor.contributors(id.toNumber());
assert.equal(hashDigest, contributorProfile[1]); // eslint-disable-line no-undef
assert.equal(hashFunction, contributorProfile[2].toNumber()); // eslint-disable-line no-undef
assert.equal(hashSize, contributorProfile[3].toNumber()); // eslint-disable-line no-undef
});
it("should revert when update contributor profile hash from address that does not have permission", async () => {
return assertRevert(async () => {
await contributor.updateContributorProfileHash(id.toNumber(), hashDigest, hashFunction, hashSize, {from: member1});
'sender does not have permission';
});
});
});
});

View File

@@ -51,16 +51,13 @@ contract Proposal is AragonApp {
initialized();
}
function getContributorContract() public view returns (address) {
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
}
function getContributionContract() public view returns (address) {
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
function getContract(uint8 appId) public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[appId]);
}
function addProposal(uint32 contributorId, uint32 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) {
require(IContributor(getContributorContract()).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND');
require(IContributor(getContract(uint8(Apps.Contributor))).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND');
uint32 proposalId = proposalsCount + 1;
uint16 _votesNeeded = 1; //contributorsContract().coreContributorsCount() / 100 * 75;
@@ -69,10 +66,10 @@ contract Proposal is AragonApp {
p.creatorAccount = msg.sender;
p.contributorId = contributorId;
p.amount = amount;
p.hashDigest = hashDigest;
p.hashDigest = hashDigest;
p.hashFunction = hashFunction;
p.hashSize = hashSize;
p.votesCount = 0;
p.hashSize = hashSize;
p.votesCount = 0;
p.votesNeeded = _votesNeeded;
p.exists = true;
@@ -102,7 +99,7 @@ contract Proposal is AragonApp {
function vote(uint32 proposalId) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
Proposal storage p = proposals[proposalId];
require(!p.executed, 'ALREADY_EXECUTED');
uint32 voterId = IContributor(getContributorContract()).getContributorIdByAddress(msg.sender);
uint32 voterId = IContributor(getContract(uint8(Apps.Contributor))).getContributorIdByAddress(msg.sender);
require(p.votes[voterId] != true, 'ALREADY_VOTED');
p.voterIds.push(voterId);
p.votes[voterId] = true;
@@ -126,7 +123,7 @@ contract Proposal is AragonApp {
require(p.votesCount >= p.votesNeeded, 'MISSING_VOTES');
p.executed = true;
IContribution(getContributionContract()).add(p.amount, p.contributorId, p.hashDigest, p.hashFunction, p.hashSize);
IContribution(getContract(uint8(Apps.Contribution))).add(p.amount, p.contributorId, p.hashDigest, p.hashFunction, p.hashSize);
emit ProposalExecuted(proposalId, p.contributorId, p.amount);
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
"@aragon/cli": "^5.9.6"
},
"devDependencies": {
"@aragon/test-helpers": "^1.1.0",
"@aragon/test-helpers": "^2.0.0",
"eth-gas-reporter": "^0.2.0",
"ganache-cli": "^6.4.3",
"solidity-coverage": "^0.5.11"
@@ -26,10 +26,7 @@
"publish:minor": "aragon apm publish minor",
"publish:major": "aragon apm publish major",
"versions": "aragon apm versions",
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
"test:gas": "GAS_REPORTER=true npm test",
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
"test": "aragon contracts test"
},
"keywords": []
}

View File

@@ -21,6 +21,8 @@ contract Token is ERC20Token, AragonApp {
}
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) {
require(amount > 0, "INVALID_AMOUNT");
uint256 amountInWei = amount.mul(1 ether);
_mint(contributorAccount, amountInWei);
emit LogMint(contributorAccount, amount, contributionId);

View File

@@ -0,0 +1,16 @@
pragma solidity ^0.4.24;
import "@aragon/os/contracts/acl/ACL.sol";
import "@aragon/os/contracts/kernel/Kernel.sol";
import "@aragon/os/contracts/factory/DAOFactory.sol";
// You might think this file is a bit odd, but let me explain.
// We only use for now those imported contracts in our tests, which
// means Truffle will not compile them for us, because they are from
// an external dependency.
// solium-disable-next-line no-empty-blocks
contract Spoof {
// ...
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
"@aragon/cli": "^5.9.6"
},
"devDependencies": {
"@aragon/test-helpers": "^1.1.0",
"@aragon/test-helpers": "^2.0.0",
"eth-gas-reporter": "^0.2.0",
"ganache-cli": "^6.4.3",
"solidity-coverage": "^0.5.11"
@@ -26,10 +26,7 @@
"publish:minor": "aragon apm publish minor",
"publish:major": "aragon apm publish major",
"versions": "aragon apm versions",
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
"test:gas": "GAS_REPORTER=true npm test",
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
"test": "aragon contracts test"
},
"keywords": []
}

View File

@@ -1,5 +0,0 @@
// const Token = artifacts.require('Token.sol');
contract('Token', (_accounts) => {
it('should be tested');
});

123
apps/token/test/token.js Normal file
View File

@@ -0,0 +1,123 @@
const namehash = require('ethers').utils.namehash;
// eslint-disable-next-line no-undef
const Token = artifacts.require("Token.sol");
// eslint-disable-next-line no-undef
const getContract = name => artifacts.require(name);
const { assertRevert } = require('@aragon/test-helpers/assertThrow');
const ZERO_ADDR = '0x0000000000000000000000000000000000000000';
contract('Token app', (accounts) => {
let kernelBase, aclBase, daoFactory, dao, r, acl, token;
const root = accounts[0];
const member1 = accounts[1];
// eslint-disable-next-line no-undef
before(async () => {
kernelBase = await getContract('Kernel').new(true); // petrify immediately
aclBase = await getContract('ACL').new();
daoFactory = await getContract('DAOFactory').new(kernelBase.address, aclBase.address, ZERO_ADDR);
r = await daoFactory.newDAO(root);
dao = getContract('Kernel').at(r.logs.filter(l => l.event == 'DeployDAO')[0].args.dao);
acl = getContract('ACL').at(await dao.acl());
//create dao mamnager permission for coin owner
await acl.createPermission(
root,
dao.address,
await dao.APP_MANAGER_ROLE(),
root,
{ from: root }
);
//get new app instance from DAO
const receipt = await dao.newAppInstance(
'0x1234',
(await Token.new()).address,
0x0,
false,
{ from: root }
);
token = Token.at(
receipt.logs.filter(l => l.event == 'NewAppProxy')[0].args.proxy
);
//apps id
let appsId = [];
appsId[0] = namehash("kredits-contribution");
appsId[1] = namehash("kredits-contributor");
appsId[2] = namehash("kredits-proposal");
appsId[3] = namehash("kredits-token");
//init token (app)
await token.initialize(appsId);
//create token mint permission for coin owner
await acl.createPermission(
root,
token.address,
await token.MINT_TOKEN_ROLE(),
root,
{ from: root }
);
});
describe("Owner default space permissions", async () => {
it('check owner is token issuer', async () => {
let tokenIssuerPermission = await acl.hasPermission(root, token.address, await token.MINT_TOKEN_ROLE());
// eslint-disable-next-line no-undef
assert.equal(tokenIssuerPermission, true);
});
});
describe("Token issuing", async () => {
let name = "Kredits";
let symbol = "₭S";
let decimals = 18;
it("check token properties", async () => {
assert.equal(await token.name(), name); // eslint-disable-line no-undef
assert.equal(await token.symbol(), symbol); // eslint-disable-line no-undef
assert.equal(await token.decimals(), decimals); // eslint-disable-line no-undef
});
});
describe("Token minting", async () => {
let tokenToMint = 250;
let ether = 1000000000000000000;
it("should revert when mint tokens from an address that does not have minting permission", async () => {
return assertRevert(async () => {
await token.mintFor(root, tokenToMint, 1, { from: member1});
'address does not have permission to mint tokens';
});
});
it("should revert when mint tokens to address(0)", async () => {
return assertRevert(async () => {
await token.mintFor(ZERO_ADDR, tokenToMint, 1, { from: root});
'invalid contributor address';
});
});
it("should revert when mint amount of tokens equal to 0", async () => {
return assertRevert(async () => {
await token.mintFor(root, 0, 1, { from: root});
'amount to mint should be greater than zero';
});
});
it("mint tokens", async () => {
await token.mintFor(root, tokenToMint, 1, { from: root });
let ownerBalance = await token.balanceOf(root);
let totalSupply = await token.totalSupply();
assert.equal(ownerBalance.toNumber(), tokenToMint*ether); // eslint-disable-line no-undef
assert.equal(totalSupply.toNumber(), tokenToMint*ether); // eslint-disable-line no-undef
});
});
});

View File

@@ -9,18 +9,6 @@ class Record extends Base {
return Promise.all(records);
});
}
pinIpfsHashes () {
return this.count.then(count => {
let promises = [...Array(count).keys()].map(i => {
let id = i + 1; // 0 => 1 - ids start with 1 and not with 0
return this.getData(id).then(data => {
return this.ipfs.pin(data);
});
});
return Promise.all(promises);
});
}
}
module.exports = Record;

View File

@@ -13,7 +13,7 @@ class Contributor {
Object.keys(attrs).forEach(a => this[a] = attrs[a]);
}
/**
/**
* Serialize object to JSON
*
* @method

View File

@@ -1,32 +0,0 @@
class IpfsPinner {
constructor (kredits) {
this.kredits = kredits;
}
pinAll () {
return Promise.all([
this.kredits.Contributor.pinIpfsHashes(),
this.kredits.Contribution.pinIpfsHashes(),
]);
}
monitor (callback) {
this.kredits.Contribution.on('ContributionAdded', (id) => {
this.kredits.Contribution.getData(id)
.then(data => { return this.kredits.ipfs.pin(data); })
.then(callback);
});
this.kredits.Contributor.on('ContributorAdded', (id) => {
this.kredits.Contribution.getData(id)
.then(data => { return this.kredits.ipfs.pin(data); })
.then(callback);
});
this.kredits.Contributor.on('ContributorProfileUpdated', (id) => {
this.kredits.Contributor.getData(id)
.then(data => { return this.kredits.ipfs.pin(data); })
.then(callback);
});
}
}
module.exports = IpfsPinner;

25417
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,14 +16,15 @@
"bootstrap": "npm run reset:hard && npm run seeds",
"reset": "npm run deploy:kit && npm run deploy:dao",
"reset:hard": "npm run deploy:apps && npm run reset",
"deploy:kit": "npm run compile-contracts && aragon contracts exec scripts/deploy-kit.js",
"deploy:kit": "aragon contracts exec scripts/deploy-kit.js",
"deploy:dao": "aragon contracts exec scripts/new-dao.js",
"deploy:apps": "./scripts/every-app.sh \"aragon apm publish major\"",
"deploy:apps": "./scripts/every-app.sh \"aragon apm publish major --propagate-content=false --build=false --prepublish=false --skip-confirmation\"",
"devchain": "aragon devchain --port 7545",
"dao:address": "truffle exec scripts/current-address.js",
"lint:contracts": "solhint \"contracts/**/*.sol\" \"apps/*/contracts/**/*.sol\"",
"lint:contract-tests": "eslint apps/*/test",
"lint:wrapper": "eslint lib/",
"test": "npm run test:token && npm run test:contributor && npm run test:contribution && npm run test:proposal",
"test:token": "cd apps/token && npm run test",
"test:contributor": "cd apps/contributor && npm run test",
"test:contribution": "cd apps/contribution && npm run test",
@@ -41,7 +42,6 @@
},
"homepage": "https://github.com/67P/truffle-kredits#readme",
"devDependencies": {
"@aragon/cli": "^5.9.6",
"@aragon/kits-base": "^1.0.0",
"@aragon/os": "^4.2.0",
"async-each-series": "^1.1.0",

View File

@@ -1,31 +0,0 @@
const Kredits = require('../lib/kredits');
const IpfsPinner = require('../lib/utils/ipfs-pinner');
const network = process.env.ETH_NETWORK || 'rinkeby';
const rpcUrl = process.env.ETH_RPC_URL;
const apm = process.env.APM_DOMAIN || 'open.aragonpm.eth';
const ipfsConfig = {
host: process.env.IPFS_HOST || 'localhost',
port: process.env.IPFS_PORT || '5001',
protocol: process.env.IPFS_PROTOCOL || 'http',
};
console.log(`Using IPFS:`, ipfsConfig);
(async () => {
try {
const kredits = await Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init();
const ipfsPinner = new IpfsPinner(kredits);
ipfsPinner.pinAll().then(pins => {
console.log('Pinned', JSON.stringify(pins, null, 2));
});
ipfsPinner.monitor((pin) => {
console.log('Pinned', JSON.stringify(pin));
});
console.log(`Subscribed to DAO: ${kredits.Kernel.contract.address}`);
} catch(e) {
console.log(e);
process.exit(1);
}
})();

View File

@@ -5,7 +5,8 @@ module.exports = async function(callback) {
let amount = await promptly.prompt('Amount: ', {default: '1'});
amount = parseInt(amount);
let fromAccount = web3.eth.accounts[0];
const accounts = await web3.eth.personal.getAccounts();
let fromAccount = accounts[0];
let fromBalance = await web3.eth.getBalance(fromAccount);
let recipientBalance = await web3.eth.getBalance(recipient);
@@ -13,11 +14,11 @@ module.exports = async function(callback) {
console.log(`sender account balance ${fromAccount}: ${fromBalance}`);
console.log(`recipient account balance ${recipient}: ${recipientBalance}`);
console.log(`\nsending ${amount} ETH from ${web3.eth.accounts[0]} to ${recipient}`);
console.log(`\nsending ${amount} ETH from ${accounts[0]} to ${recipient}`);
let transaction = await web3.eth.sendTransaction({to: recipient, value: web3.toWei(amount), from: web3.eth.accounts[0]});
let transaction = await web3.eth.sendTransaction({to: recipient, value: web3.utils.toWei(new web3.utils.BN(amount)), from: accounts[0]});
console.log(`transaction id: ${transaction}`);
console.log(`transaction id: ${transaction.transactionHash}`);
recipientBalance = await web3.eth.getBalance(recipient);
console.log(`\nnew recipient account balance ${recipient}: ${recipientBalance}`);