Dynamically set AppIds

AppIds are used to lookup the actual contract addresses of each app.
Because of different registry names (open.aragonpm.eth vs. aragonpm.eth)
we have to use different ids in the local dev chain and in the
testnet/mainnet. To allow this we need to set the appids dynamically.

There is an open aragon issue to solve this and also allow to use
open.aragonpm.eth in the devchain by default.
https://github.com/aragon/aragen/issues/10
This commit is contained in:
bumi 2019-03-27 00:21:06 +01:00
parent 9cc237fbf4
commit f5973756c8
17 changed files with 78 additions and 48 deletions

View File

@ -14,7 +14,7 @@
"environments": { "environments": {
"default": { "default": {
"network": "development", "network": "development",
"appName": "kredits-contribution.open.aragonpm.eth" "appName": "kredits-contribution.aragonpm.eth"
}, },
"rinkeby": { "rinkeby": {
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d", "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",

View File

@ -11,7 +11,9 @@ contract Contribution is AragonApp {
bytes32 public constant ADD_CONTRIBUTION_ROLE = keccak256("ADD_CONTRIBUTION_ROLE"); bytes32 public constant ADD_CONTRIBUTION_ROLE = keccak256("ADD_CONTRIBUTION_ROLE");
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb; bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
bytes32 public constant TOKEN_APP_ID = 0x82c0e483537d703bb6f0fc799d2cc60d8f62edcb0f6d26d5571a92be8485b112; // ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds;
struct ContributionData { struct ContributionData {
address contributor; address contributor;
@ -38,10 +40,17 @@ contract Contribution is AragonApp {
event ContributionAdded(uint256 id, address indexed contributor, uint256 amount); event ContributionAdded(uint256 id, address indexed contributor, uint256 amount);
event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount); event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount);
function initialize() public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds;
initialized(); initialized();
} }
function getTokenContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
}
function name() external view returns (string) { function name() external view returns (string) {
return name_; return name_;
} }
@ -116,12 +125,6 @@ contract Contribution is AragonApp {
IToken(token).mintFor(c.contributor, c.amount, contributionId); IToken(token).mintFor(c.contributor, c.amount, contributionId);
emit ContributionClaimed(contributionId, c.contributor, c.amount); emit ContributionClaimed(contributionId, c.contributor, c.amount);
} }
function getTokenContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, TOKEN_APP_ID);
}
function exists(uint256 contributionId) view public returns (bool) { function exists(uint256 contributionId) view public returns (bool) {
return contributions[contributionId].exists; return contributions[contributionId].exists;

View File

@ -9,7 +9,7 @@
"environments": { "environments": {
"default": { "default": {
"network": "development", "network": "development",
"appName": "kredits-contributor.open.aragonpm.eth" "appName": "kredits-contributor.aragonpm.eth"
}, },
"rinkeby": { "rinkeby": {
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d", "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",

View File

@ -18,11 +18,15 @@ contract Contributor is AragonApp {
mapping (uint => Contributor) public contributors; mapping (uint => Contributor) public contributors;
uint256 public contributorsCount; uint256 public contributorsCount;
// ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds;
event ContributorProfileUpdated(uint id, bytes32 oldIpfsHash, bytes32 newIpfsHash); event ContributorProfileUpdated(uint id, bytes32 oldIpfsHash, bytes32 newIpfsHash);
event ContributorAccountUpdated(uint id, address oldAccount, address newAccount); event ContributorAccountUpdated(uint id, address oldAccount, address newAccount);
event ContributorAdded(uint id, address account); event ContributorAdded(uint id, address account);
function initialize(address root) public onlyInit { function initialize(address root,bytes32[4] _appIds) public onlyInit {
uint _id = contributorsCount + 1; uint _id = contributorsCount + 1;
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
c.exists = true; c.exists = true;
@ -31,6 +35,8 @@ contract Contributor is AragonApp {
contributorIds[root] = _id; contributorIds[root] = _id;
contributorsCount += 1; contributorsCount += 1;
appIds = _appIds;
initialized(); initialized();
} }

View File

@ -14,7 +14,7 @@
"environments": { "environments": {
"default": { "default": {
"network": "development", "network": "development",
"appName": "kredits-proposal.open.aragonpm.eth" "appName": "kredits-proposal.aragonpm.eth"
}, },
"rinkeby": { "rinkeby": {
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d", "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",

View File

@ -19,8 +19,9 @@ contract Proposal is AragonApp {
bytes32 public constant VOTE_PROPOSAL_ROLE = keccak256("VOTE_PROPOSAL_ROLE"); bytes32 public constant VOTE_PROPOSAL_ROLE = keccak256("VOTE_PROPOSAL_ROLE");
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb; bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
bytes32 public constant CONTRIBUTOR_APP_ID = 0x8e50972b062e83b48dbb2a68d8a058f2a07227ca183c144dc974e6da3186d7e9; // ensure alphabetic order
bytes32 public constant CONTRIBUTION_APP_ID = 0x09f5274cba299b46c5be722ef672d10eef7a2ef980b612aef529d74fb9da7643; enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds;
struct Proposal { struct Proposal {
address creatorAccount; address creatorAccount;
@ -45,16 +46,17 @@ contract Proposal is AragonApp {
event ProposalVoted(uint256 id, uint256 voterId, uint256 totalVotes); event ProposalVoted(uint256 id, uint256 voterId, uint256 totalVotes);
event ProposalExecuted(uint256 id, uint256 contributorId, uint256 amount); event ProposalExecuted(uint256 id, uint256 contributorId, uint256 amount);
function initialize() public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds;
initialized(); initialized();
} }
function getContributorContract() public view returns (address) { function getContributorContract() public view returns (address) {
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, CONTRIBUTOR_APP_ID); return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
} }
function getContributionContract() public view returns (address) { function getContributionContract() public view returns (address) {
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, CONTRIBUTION_APP_ID); return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
} }
function addProposal(uint contributorId, uint256 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) { function addProposal(uint contributorId, uint256 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) {

View File

@ -9,7 +9,7 @@
"environments": { "environments": {
"default": { "default": {
"network": "development", "network": "development",
"appName": "kredits-token.open.aragonpm.eth" "appName": "kredits-token.aragonpm.eth"
}, },
"rinkeby": { "rinkeby": {
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d", "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",

View File

@ -6,9 +6,14 @@ import "./ERC20Token.sol";
contract Token is ERC20Token, AragonApp { contract Token is ERC20Token, AragonApp {
bytes32 public constant MINT_TOKEN_ROLE = keccak256("MINT_TOKEN_ROLE"); bytes32 public constant MINT_TOKEN_ROLE = keccak256("MINT_TOKEN_ROLE");
// ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds;
event LogMint(address indexed recipient, uint256 amount, uint256 contributionId); event LogMint(address indexed recipient, uint256 amount, uint256 contributionId);
function initialize() public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds;
initialized(); initialized();
} }

View File

@ -32,17 +32,17 @@ contract KreditsKit is KitBase {
acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this); acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this);
Contributor contributor = Contributor(_installApp(dao, appIds[uint8(Apps.Contributor)])); Contributor contributor = Contributor(_installApp(dao, appIds[uint8(Apps.Contributor)]));
contributor.initialize(root); contributor.initialize(root, appIds);
acl.createPermission(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), root); acl.createPermission(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), root);
Token token = Token(_installApp(dao, appIds[uint8(Apps.Token)])); Token token = Token(_installApp(dao, appIds[uint8(Apps.Token)]));
token.initialize(); token.initialize(appIds);
Contribution contribution = Contribution(_installApp(dao, appIds[uint8(Apps.Contribution)])); Contribution contribution = Contribution(_installApp(dao, appIds[uint8(Apps.Contribution)]));
contribution.initialize(); contribution.initialize(appIds);
Proposal proposal = Proposal(_installApp(dao, appIds[uint8(Apps.Proposal)])); Proposal proposal = Proposal(_installApp(dao, appIds[uint8(Apps.Proposal)]));
proposal.initialize(); proposal.initialize(appIds);
acl.createPermission(root, contribution, contribution.ADD_CONTRIBUTION_ROLE(), this); acl.createPermission(root, contribution, contribution.ADD_CONTRIBUTION_ROLE(), this);
acl.grantPermission(proposal, contribution, contribution.ADD_CONTRIBUTION_ROLE()); acl.grantPermission(proposal, contribution, contribution.ADD_CONTRIBUTION_ROLE());

View File

@ -1 +1 @@
{"4":"0xf4f3963718e5c2b426dd5c3ef0ab4b31ffb7a318","14945560":"0x6e0745b6b18d0233708554049eeaab0cb81c4ab0","42097210":"0x15d7adc7d6283d57d45017512567985e3a768b83","51657314":"0x053e2ebaf79eb0ccc5139a40b2a3ddca79409cdc","55632786":"0x4d97bd8efacf46b33c4438ed0b7b6aabfa2359fb","84923523":"0x48c2eac33521070509f9819a824a3d5686ba5ce8"} {"4":"0x948b9e124f1648d75862a5b7f2a72f58440cf242","14945560":"0x6e0745b6b18d0233708554049eeaab0cb81c4ab0","42097210":"0x15d7adc7d6283d57d45017512567985e3a768b83","51657314":"0x053e2ebaf79eb0ccc5139a40b2a3ddca79409cdc","55632786":"0x4d97bd8efacf46b33c4438ed0b7b6aabfa2359fb","74971415":"0xa35aacdfccac54d3d96e0d29050c773b251c2c83","84923523":"0x48c2eac33521070509f9819a824a3d5686ba5ce8","85406806":"0xe47c45da69763807897f446d087d84fe572b04c4"}

View File

@ -1 +1 @@
{"4":"0x8b7c0bec9476ce08d9769a87d272b03b350712e2","14945560":"0x183af3950364390a266edff2a0e7c4c2f95c0691","23827572":"0xe4e0e7fe54d9189df29a80c07ab733fc9a212761","42097210":"0x183af3950364390a266edff2a0e7c4c2f95c0691","51657314":"0xad3a80686847d55d7b14b930bc6db53681ae1b1e","55632786":"0x4fde16c57ddf6d4870d5edd599074bb50dc96f88","65047207":"0xb67567175ac213f6f622b23d3d972d5b877c4813"} {"4":"0x8b7c0bec9476ce08d9769a87d272b03b350712e2","14945560":"0x183af3950364390a266edff2a0e7c4c2f95c0691","23827572":"0xe4e0e7fe54d9189df29a80c07ab733fc9a212761","42097210":"0x183af3950364390a266edff2a0e7c4c2f95c0691","51657314":"0xad3a80686847d55d7b14b930bc6db53681ae1b1e","55632786":"0x4fde16c57ddf6d4870d5edd599074bb50dc96f88","65047207":"0xb67567175ac213f6f622b23d3d972d5b877c4813","74971415":"0x183af3950364390a266edff2a0e7c4c2f95c0691","85406806":"0x192db9a1f757c7c2afd03cb5afe883b27d0d3937"}

1
lib/app_ids.json Normal file
View File

@ -0,0 +1 @@
{"74971415":{"Contribution":"0xe401b988b8af39119004de5c7691a60391d69d873b3120682a8c61306a4883ce","Contributor":"0x7829d33291d6e118d115ce321de9341894a2da120bd35505fc03b98f715c606d","Proposal":"0x15d03d435b24a74317868c24fda4646302076b59272241a122a3868eb5c745da","Token":"0x85b0f626cecde6188d11940904fedeb16a4d49b0e8c878b9d109b23d38062ca7"},"85406806":{"Contribution":"0xe401b988b8af39119004de5c7691a60391d69d873b3120682a8c61306a4883ce","Contributor":"0x7829d33291d6e118d115ce321de9341894a2da120bd35505fc03b98f715c606d","Proposal":"0x15d03d435b24a74317868c24fda4646302076b59272241a122a3868eb5c745da","Token":"0x85b0f626cecde6188d11940904fedeb16a4d49b0e8c878b9d109b23d38062ca7"}}

View File

@ -1,5 +1,5 @@
const AppIds = require('../app_ids.json');
const Base = require('./base'); const Base = require('./base');
KERNEL_APP_ADDR_NAMESPACE = '0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb'; KERNEL_APP_ADDR_NAMESPACE = '0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb';
class Kernel extends Base { class Kernel extends Base {
@ -9,12 +9,7 @@ class Kernel extends Base {
} }
appNamehash(appName) { appNamehash(appName) {
return { return AppIds[this.contract.provider.chainId.toString()][appName];
Contributor: '0x8e50972b062e83b48dbb2a68d8a058f2a07227ca183c144dc974e6da3186d7e9',
Contribution: '0x09f5274cba299b46c5be722ef672d10eef7a2ef980b612aef529d74fb9da7643',
Token: '0x82c0e483537d703bb6f0fc799d2cc60d8f62edcb0f6d26d5571a92be8485b112',
Proposal: '0xb48bc8b4e539823f3be98d67f4130c07b5d29cc998993debcdea15c6faf4cf8a'
}[appName];
} }
} }

View File

@ -5,8 +5,7 @@ const path = require('path');
const argv = require('yargs').argv const argv = require('yargs').argv
const namehash = require('eth-ens-namehash').hash const namehash = require('eth-ens-namehash').hash
const libPath = path.join(__dirname, '..', 'lib'); const fileInject = require('./helpers/file_inject.js')
const addressesPath = path.join(libPath, 'addresses');
const DAOFactory = artifacts.require('DAOFactory') const DAOFactory = artifacts.require('DAOFactory')
const KreditsKit = artifacts.require('KreditsKit') const KreditsKit = artifacts.require('KreditsKit')
@ -48,16 +47,18 @@ module.exports = async function(callback) {
const apps = fs.readdirSync('./apps') const apps = fs.readdirSync('./apps')
console.log(`Found apps: [${apps}].${apm}`) console.log(`Found apps: [${apps}].${apm}`)
const appIds = apps.map(app => namehash(`kredits-${app}.${apm}`)) let appIds = {}
apps.sort().forEach((app) => {
let [first, ...rest] = app;
let contractName = `${first.toUpperCase()}${rest.join('')}`
appIds[contractName] = namehash(`kredits-${app}.${apm}`)
})
KreditsKit.new(daoFactory.address, ensAddr, appIds).then((kreditsKit) => { KreditsKit.new(daoFactory.address, ensAddr, Object.values(appIds)).then((kreditsKit) => {
console.log(`Deployed KreditsKit at: ${kreditsKit.address}`); console.log(`Deployed KreditsKit at: ${kreditsKit.address}`);
let addresseFile = path.join(addressesPath, `KreditsKit.json`); fileInject(path.join(__dirname, '..', 'lib/addresses/KreditsKit.json'), networkId, kreditsKit.address);
let addresses = JSON.parse(fs.readFileSync(addresseFile)); fileInject(path.join(__dirname, '..', 'lib/app_ids.json'), networkId, appIds);
addresses[networkId] = kreditsKit.address;
fs.writeFileSync(addresseFile, JSON.stringify(addresses));
callback(); callback();
}).catch((e) => { }).catch((e) => {

View File

@ -0,0 +1,8 @@
// help, give me a better name
const fs = require('fs');
module.exports = function (file, networkId, data) {
let content = JSON.parse(fs.readFileSync(file));
content[networkId] = data;
fs.writeFileSync(file, JSON.stringify(content));
}

View File

@ -0,0 +1,11 @@
module.exports = function(web3) {
return new Promise((resolve, reject) => {
web3.version.getNetwork((err, network) => {
if (err) {
reject(err);
} else {
resolve(network);
}
})
})
}

View File

@ -1,7 +1,9 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const libPath = path.join(__dirname, '..', 'lib');
const addressesPath = path.join(libPath, 'addresses'); const fileInject = require('./helpers/file_inject.js');
const addressesPath = path.join(__dirname, '..', 'lib/addresses');
const KreditsKit = artifacts.require('KreditsKit') const KreditsKit = artifacts.require('KreditsKit')
@ -39,11 +41,7 @@ module.exports = async function(callback) {
} }
const daoAddress = deployEvents[0].dao; const daoAddress = deployEvents[0].dao;
let addresseFile = path.join(addressesPath, `dao.json`); fileInject(path.join(addressesPath, 'dao.json'), networkId, daoAddress)
let addresses = JSON.parse(fs.readFileSync(addresseFile));
addresses[networkId] = daoAddress;
fs.writeFileSync(addresseFile, JSON.stringify(addresses));
console.log(`\n\nCreated new DAO at: ${daoAddress}`) console.log(`\n\nCreated new DAO at: ${daoAddress}`)