Skip to content

Commit 4ee810b

Browse files
authored
Improve deployment to ease verification and documentation (#439)
* Implement deployment logger helper * Flatten contracts on deployment for verification * Deploy bases individually to avoid problems when submitting many txs * Rename calldata variable name as it makes solidity-parser-antlr crash * Await on logDeploy * Prepare for production: rename scripts and clean up old addresses * Update readme * Use provider account as the default owner * Address review comments * Update readme * Revert path.resolve
1 parent a684791 commit 4ee810b

File tree

8 files changed

+108
-36
lines changed

8 files changed

+108
-36
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ abi/
1717
build/
1818
bytecode/
1919
bytecode_new/
20+
flattened_contracts/

contracts/evmscript/EVMScriptRunner.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstant
3434
require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE);
3535

3636
bytes4 sig = executor.execScript.selector;
37-
bytes memory calldata = abi.encodeWithSelector(sig, _script, _input, _blacklist);
38-
require(address(executor).delegatecall(calldata), ERROR_EXECUTION_REVERTED);
37+
bytes memory data = abi.encodeWithSelector(sig, _script, _input, _blacklist);
38+
require(address(executor).delegatecall(data), ERROR_EXECUTION_REVERTED);
3939

4040
bytes memory output = returnedDataDecoded();
4141

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
"web3-utils": "1.0.0-beta.33"
4848
},
4949
"dependencies": {
50+
"mkdirp": "^0.5.1",
51+
"truffle-flattener": "^1.2.9",
5052
"homedir": "^0.6.0",
5153
"truffle-hdwallet-provider": "0.0.3",
5254
"truffle-hdwallet-provider-privkey": "0.3.0"

readme.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
# aragonOS <img align="right" src="https://raw.githubusercontent.com/aragon/design/master/readme-logo.png" height="80px" /> [![Travis branch](https://img.shields.io/travis/aragon/aragonOS/master.svg?style=for-the-badge)](https://travis-ci.org/aragon/aragonOS) [![Coveralls branch](https://img.shields.io/coveralls/aragon/aragonOS/master.svg?style=for-the-badge)](https://coveralls.io/github/aragon/aragonOS?branch=master) [![npm](https://img.shields.io/npm/v/@aragon/os.svg?style=for-the-badge)](https://www.npmjs.com/package/@aragon/os)
22

3-
This repo contains Aragon's reference implementation for [aragonOS](https://wiki.aragon.one/dev/aragonOS_index/).
3+
This repo contains Aragon's reference implementation for [aragonOS](https://hack.aragon.org/docs/aragonos-intro.html).
44

5-
#### 🚨 Everything in this repo is highly experimental software.
6-
It is not secure to use any of this code in production (mainnet) until proper security audits have been conducted. It can result in irreversible loss of funds.
5+
#### 🚨 Security review status: bug bounty
6+
aragonOS 4 has undergone two independent professional security reviews, and the issues raised have been resolved. However there is a [bug bounty program](https://wiki.aragon.org/dev/bug_bounty/) for rewarding hackers who find security vulnerabilities. There is a bounty pool of $250,000 USD, you can find more information [here](https://wiki.aragon.org/dev/bug_bounty/).
77

8-
#### 🦋 We are using [Status Open Bounty](http://openbounty.status.im/app) to reward open source contributions with Aragon Tokens (ANT)
9-
All issues tagged with **[bounty](https://github.com/aragon/aragonOS/labels/bounty)** are eligible for a bounty on a successfully merged Pull Request that solves the issue. Even if the bounty says 0 ANT, if it has the **bounty** label, it will always be higher than 0 ANT (until we automate it, we may take a bit to fund the bounties manually).
10-
11-
#### 👋 We are tagging tasks that are [good first issues](https://github.com/aragon/aragonOS/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) so you can get started contributing to Aragon Core.
8+
#### 👋 Get started contributing with a [good first issue](https://github.com/aragon/aragonOS/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
129
Don't be shy to contribute even the smallest tweak. Everyone will be especially nice and helpful to beginners to help you get started!
1310

1411
## Documentation
1512

16-
Visit the [Aragon wiki](https://wiki.aragon.one/dev/aragonOS_index/) for in depth documentation on the [architecture](https://wiki.aragon.one/documentation/aragonOS/) and different parts of the system.
13+
Visit the [Aragon Developer Portal](https://hack.aragon.org/docs/aragonos-intro.html) for in depth documentation on the [architecture](https://hack.aragon.org/docs/aragonos-ref.html) and different parts of the system.
1714

1815
## Installing aragonOS
1916

@@ -25,13 +22,23 @@ npm test
2522
npm run lint
2623
```
2724

25+
## Deploying
26+
27+
### APM
28+
```sh
29+
OWNER=[APM owner address] ENS=[ENS registry address] npx truffle exec --network [network] scripts/deploy-apm.js
30+
```
31+
32+
- `ENS`: If no ENS registry address is provided, it will deploy a dummy ENS instance to the network. If the ENS registry is provided, the name `aragonpm.eth` must be owned by the deployer account.
33+
- `OWNER`: The account that will be the initial owner of the APM registry
34+
2835
## Using aragonOS for making Aragon apps
2936

3037
```
3138
npm i --save-dev @aragon/os
3239
```
3340

34-
(section under construction)
41+
Check the [Aragon Developer Portal](https://hack.aragon.org) for detailed documentation and tutorials on how to use aragonOS.
3542

3643
## Contributing
3744

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
const namehash = require('eth-ens-namehash').hash
22
const keccak256 = require('js-sha3').keccak_256
3+
const { promisify } = require('util')
34

4-
const deployENS = require('./deploy-beta-ens')
5+
const deployENS = require('./deploy-test-ens')
56
const deployDaoFactory = require('./deploy-daofactory')
7+
const logDeploy = require('./helpers/deploy-logger')
68

79
const globalArtifacts = this.artifacts // Not injected unless called directly via truffle
810

911
const ZERO_ADDR = '0x0000000000000000000000000000000000000000'
1012

11-
const defaultOwner = process.env.OWNER || '0x4cb3fd420555a09ba98845f0b816e45cfb230983'
13+
const defaultOwner = process.env.OWNER
1214
const defaultDaoFactoryAddress = process.env.DAO_FACTORY
1315
const defaultENSAddress = process.env.ENS
1416

15-
const deployBases = async baseContracts => {
16-
const deployedContracts = await Promise.all(baseContracts.map(c => c.new()))
17-
return deployedContracts.map(c => c.address)
18-
}
19-
2017
module.exports = async (
2118
truffleExecCallback,
2219
{
@@ -47,6 +44,12 @@ module.exports = async (
4744
let ens
4845

4946
log('Deploying APM...')
47+
48+
if (!owner) {
49+
const accounts = await promisify(web3.eth.getAccounts)()
50+
owner = accounts[0]
51+
log('OWNER env variable not found, setting APM owner to the provider\'s first account')
52+
}
5053
log('Owner:', owner)
5154

5255
if (!ensAddress) {
@@ -64,8 +67,13 @@ module.exports = async (
6467

6568
log('=========')
6669
log('Deploying APM bases...')
67-
const apmBases = await deployBases([APMRegistry, Repo, ENSSubdomainRegistrar])
68-
log('Deployed APM bases:', apmBases)
70+
71+
const apmRegistryBase = await APMRegistry.new()
72+
await logDeploy(apmRegistryBase, { verbose })
73+
const apmRepoBase = await Repo.new()
74+
await logDeploy(apmRepoBase, { verbose })
75+
const ensSubdomainRegistrarBase = await ENSSubdomainRegistrar.new()
76+
await logDeploy(ensSubdomainRegistrarBase, { verbose })
6977

7078
let daoFactory
7179
if (daoFactoryAddress) {
@@ -76,12 +84,18 @@ module.exports = async (
7684
} else {
7785
log('Deploying DAOFactory with EVMScripts...')
7886
daoFactory = (await deployDaoFactory(null, { artifacts, withEvmScriptRegistryFactory: true, verbose: false })).daoFactory
79-
log('Deployed DAOFactory:', daoFactory.address)
8087
}
8188

8289
log('Deploying APMRegistryFactory...')
83-
const apmFactory = await APMRegistryFactory.new(daoFactory.address, ...apmBases, ensAddress, '0x00')
84-
log('Deployed APMRegistryFactory:', apmFactory.address)
90+
const apmFactory = await APMRegistryFactory.new(
91+
daoFactory.address,
92+
apmRegistryBase.address,
93+
apmRepoBase.address,
94+
ensSubdomainRegistrarBase.address,
95+
ensAddress,
96+
'0x00'
97+
)
98+
await logDeploy(apmFactory, { verbose })
8599

86100
log(`Assigning ENS name (${labelName}.${tldName}) to factory...`)
87101
try {
@@ -99,8 +113,10 @@ module.exports = async (
99113

100114
log('=========')
101115
const apmAddr = receipt.logs.filter(l => l.event == 'DeployAPM')[0].args.apm
102-
log('Deployed APM:', apmAddr)
103-
log(apmAddr)
116+
log('# APM:')
117+
log('Address:', apmAddr)
118+
log('Transaction hash:', receipt.tx)
119+
log('=========')
104120

105121
if (typeof truffleExecCallback === 'function') {
106122
// Called directly via `truffle exec`
@@ -113,5 +129,3 @@ module.exports = async (
113129
}
114130
}
115131
}
116-
117-
// Rinkeby APM: 0x700569b6c99b8b5fa17b7976a26ae2f0d5fd145c

scripts/deploy-daofactory.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const logDeploy = require('./helpers/deploy-logger')
2+
13
const globalArtifacts = this.artifacts // Not injected unless called directly via truffle
24

35
const ZERO_ADDR = '0x0000000000000000000000000000000000000000'
@@ -10,31 +12,30 @@ module.exports = async (
1012
verbose = true
1113
} = {}
1214
) => {
13-
const log = (...args) => {
14-
if (verbose) { console.log(...args) }
15-
}
16-
1715
const ACL = artifacts.require('ACL')
1816
const Kernel = artifacts.require('Kernel')
1917

2018
const DAOFactory = artifacts.require('DAOFactory')
2119

22-
log('Deploying DAOFactory with bases...')
2320
const kernelBase = await Kernel.new(true) // immediately petrify
21+
await logDeploy(kernelBase, { verbose })
22+
2423
const aclBase = await ACL.new()
24+
await logDeploy(aclBase, { verbose })
2525

2626
let evmScriptRegistryFactory
2727
if (withEvmScriptRegistryFactory) {
2828
const EVMScriptRegistryFactory = artifacts.require('EVMScriptRegistryFactory')
2929
evmScriptRegistryFactory = await EVMScriptRegistryFactory.new()
30+
await logDeploy(evmScriptRegistryFactory, { verbose })
3031
}
3132
const daoFactory = await DAOFactory.new(
3233
kernelBase.address,
3334
aclBase.address,
3435
evmScriptRegistryFactory ? evmScriptRegistryFactory.address : ZERO_ADDR
3536
)
3637

37-
log('DAOFactory deployed:', daoFactory.address)
38+
await logDeploy(daoFactory, { verbose })
3839

3940
if (typeof truffleExecCallback === 'function') {
4041
// Called directly via `truffle exec`
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1+
const logDeploy = require('./helpers/deploy-logger')
2+
const { promisify } = require('util')
3+
14
const globalArtifacts = this.artifacts // Not injected unless called directly via truffle
25

3-
const defaultOwner = process.env.OWNER || '0x4cb3fd420555a09ba98845f0b816e45cfb230983'
6+
const defaultOwner = process.env.OWNER
47

58
module.exports = async (truffleExecCallback, { artifacts = globalArtifacts, owner = defaultOwner, verbose = true } = {}) => {
69
const log = (...args) => {
710
if (verbose) { console.log(...args) }
811
}
912

13+
if (!owner) {
14+
const accounts = await promisify(web3.eth.getAccounts)()
15+
owner = accounts[0]
16+
log(`No OWNER environment variable passed, setting ENS owner to provider's account: ${owner}`)
17+
}
18+
1019
const ENS = artifacts.require('ENS')
1120
const ENSFactory = artifacts.require('ENSFactory')
1221

1322
log('Deploying ENSFactory...')
1423
const factory = await ENSFactory.new()
15-
log('ENSFactory deployed:', factory.address)
24+
await logDeploy(factory, { verbose })
1625
const receipt = await factory.newENS(owner)
1726

1827
const ensAddr = receipt.logs.filter(l => l.event == 'DeployENS')[0].args.ens
@@ -32,4 +41,3 @@ module.exports = async (truffleExecCallback, { artifacts = globalArtifacts, owne
3241
}
3342
}
3443

35-
// Rinkeby ENS: 0xfbae32d1cde62858bc45f51efc8cc4fa1415447e

scripts/helpers/deploy-logger.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const flatten = require('truffle-flattener')
2+
const mkdirp = require('mkdirp')
3+
const fs = require('fs')
4+
const path = require('path')
5+
6+
const truffleConfig = require('../../truffle-config')
7+
8+
const FLATTEN_DIR = './flattened_contracts'
9+
10+
module.exports = async (instance, { verbose = true, flattenContracts = true } = {}) => {
11+
const {
12+
contractName,
13+
sourcePath,
14+
updatedAt: compiledAt,
15+
compiler: { name: compilerName, version: compilerVersion }
16+
} = instance.constructor._json
17+
18+
if (flattenContracts) {
19+
const flattenedCode = await flatten([ sourcePath ])
20+
mkdirp.sync(FLATTEN_DIR)
21+
const savePath = path.join(FLATTEN_DIR, `${contractName}.sol`)
22+
fs.writeFileSync(savePath, flattenedCode)
23+
}
24+
25+
const optimizer = truffleConfig.solc.optimizer || null
26+
const optimizerStatus = optimizer && optimizer.enabled ? `${optimizer.runs} runs`: 'Disabled'
27+
28+
if (!verbose) {
29+
console.log(`Deployed ${contractName}: ${instance.address}`)
30+
} else {
31+
console.log('=========')
32+
console.log(`# ${contractName}:`)
33+
console.log(`Address: ${instance.address}`)
34+
console.log(`Transaction hash: ${instance.transactionHash}`)
35+
console.log(`Compiler: ${compilerName}@${compilerVersion} (Optimizer: ${optimizerStatus})`)
36+
console.log(`Compiled at: ${compiledAt}`)
37+
console.log('=========')
38+
}
39+
}

0 commit comments

Comments
 (0)