DAOstack Migration
A repo for handling the migration of DAOstack contracts and DAOs. This repo is packaged both as an npm package and a Docker image that exposes a pre-migrated ganache instance and other utilities related to migration.
Migration is separated into two phases:
- Base migration - of universal contracts from the
@daostack/arc
package. - DAO migration - of an example DAO.
Versioning
Both the npm package and the docker image are versioned according to the @daostack/arc
package and the migration
version. Example: @daostack/arc@<arc version>
-> npm: @daostack/ganache@<arcversion>-v<migration version>
and
dockerhub: daostack/ganache:X.Y.Z-v<migration version>
Usage
As a library
npm install --save @daostack/migration
const DAOstackMigration = require('@daostack/migration');
// ganache-core object with already migrated contracts
// options are as specified in https://github.com/trufflesuite/ganache-cli#library
DAOstackMigration.Ganache.server(..);
DAOstackMigration.Ganache.provider(..);
// choose the network to get addressed for. Either private (ganache), kovan, rinkeby, mainnet.
let network = 'private'
// migration result object for ganache
DAOstackMigration.migration(network);
const options = {
// arc version
arcVersion: '0.0.1-rc.32',
// web3 provider url
provider: 'http://localhost:8545',
// gas price in GWei. If not specified, will use an automatically suggested price.
gasPrice: 3.4,
// suppress console output
quiet: true,
// disable confirmation messages
disable-confs: true,
// force deploy everything
force: true,
// delete previous deployment state and starts with clean state
restart: false,
// filepath to output the migration results
output: 'migration.json',
// private key of the account used in migration (overrides the 'mnemonic' option)
privateKey: '0x123...',
// mnemonic used to generate the private key of the account used in migration
mnemonic: 'one two three ...',
// migration parameters
params: {
default: {
// migration params as defined in the "Migration parameters" section below
},
private: {
// override defaults on private network
},
kovan: {
// override defaults on kovan
},
},
};
// migrate base contracts
const migrationBaseResult = await DAOstackMigration.migrateBase(options);
migrationBaseResult.base.GenesisProtocol // migrated genesis protocol address
// migrate an example DAO (requires an existing `output` file with a base migration)
const migrationDAOResult = await DAOstackMigration.migrateDAO(options);
migrationDAOResult.dao.Avatar // DAO avatar address
// migrate an demo test scenario (requires an existing `output` file with a base migration)
const migrationDemoResult = await DAOstackMigration.migrateDemoTest(options);
migrationDemoResult.test.Avatar // Test DAO avatar address
// migrate base, example DAO and demo test contracts
const migrationResult = await DAOstackMigration.migrate(options); // migrate
// run the cli
DAOstackMigration.cli()
As a CLI
npm install --global @daostack/migration
Note: if you encounter an issue which contains this error message EACCES: permission denied, mkdir
please follow this guide and try again
Usage:
Migrate base contracts and an example DAO
Commands:
daostack-migrate Migrate base contracts and an example DAO [default]
daostack-migrate base Migrate base contracts
daostack-migrate dao Migrate an example DAO
daostack-migrate completion generate bash completion script
Options:
--version Show version number [boolean]
--arcversion, -a Use a specific Arc package version [string] [default: latest supported version]
--provider, -p web3 provider url [string] [default: "http://localhost:8545"]
--gas-price, -g gas price in GWei. If not specified, will use an automatically suggested price. [number]
--quiet, -q suppress console output [boolean] [default: false]
--force, -f disable confirmation messages [boolean] [default: false]
--restart, -t delete previous deployment state and starts with clean state restart [boolean] [default: false]
--output, -o filepath to output the migration results [string] [default: "migration.json"]
--params, -i path to the file containing the migration parameters [string] [default: "migration-params.json"]
--private-key, -s private key of the account used in migration (cannot be used with the 'mnemonic' option)
[string] [default: "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"]
--mnemonic, -m mnemonic used to generate the private key of the account used in migration (cannot be used with the
'private-key' option) [string]
--help Show help [boolean]
How to deploying a new DAO:
From CLI:
-
Make sure you have Node.js and NPM installed and updated to a version later than 10.15.3 and 6.0.0 respectively. You can find instructions for installation here, and then verify your version by opening your CMD/ Terminal and type:
node -v
and thennpm -v
. -
In your terminal, use this command to install the DAOstack migration CLI:
npm install --global @daostack/migration
. -
Create a new
your-new-dao-params.json
file, you can also use the samemigration-params.json
from the DAOstack migratio GitHub repo. -
Customize
your-new-dao-params.json
by setting up the DAO name, token, founders, schemes etc. To learn more about the customization options for the parameters please see the Migration parameters section below. -
Obtain a URL of an Ethereum node connected to your desired network. You can also use Infura for that.
-
Get some ether in your Ethereum account to pay for the mining fee of deploying the DAO. Make sure you have the private key for the account.
-
In the terminal window, use this command to deploy your DAO:
daostack-migrate dao --params <YOUR_PARAMS_FILE_LOCATION> --gasPrice <YOUR_DESIRED_VALUE> --provider <YOUR_ETHERUM_NODE> --private-key <YOUR_PRIVATE_KEY>
. Note: You can also use a mnemonic seed instead of a private key by replacing the--private-key
option with--mnemonic <YOUR_MNEMONIC>
. -
This will deploy the DAO for you and output the addresses into a
migration.json
file.
From Javascript
const DAOstackMigration = require('@daostack/migration');
const options = {
// arc version
arcVersion: '0.0.1-rc.32',
// web3 provider url
provider: 'http://localhost:8545',
// gas price in GWei. If not specified, will use an automatically suggested price.
gasPrice: 3.4,
// surpress console output
quiet: true,
// disable confirmation messages
force: true,
// delete previous deployment state and starts with clean state
restart: false,
// filepath to output the migration results
output: 'migration.json',
// private key of the account used in migration (overrides the 'mnemonic' option)
privateKey: '0x123...',
// mnemonic used to generate the private key of the account used in migration
mnemonic: 'one two three ...',
// migration parameters
params: {
default: {
// migration params as defined in the "Migration parameters" section below
},
private: {
// override defaults on private network
},
kovan: {
// override defaults on kovan
}
}
};
const migrationDAOResult = await DAOstackMigration.migrateDAO(options);
migrationDAOResult.dao.Avatar; // DAO avatar address
// migrate an demo test scenario (requires an existing `output` file with a base migration)
const migrationDemoResult = await DAOstackMigration.migrateDemoTest(options);
migrationDemoResult.test.Avatar; // Test DAO avatar address
// migrate base, example DAO and demo test contracts
const migrationResult = await DAOstackMigration.migrate(options); // migrate
// run the cli
DAOstackMigration.cli();
As a docker image
docker pull daostack/migration
- Run:
docker run --rm --name=ganache daostack/migration:0.0.0-alpha.56-v7 <ganache-cli arguments>
- Fetch migration result file:
docker exec ganache cat migration.json
- Fetch migration params file:
docker exec ganache cat migration-params.json
Migration result
Example migration result object:
{
"base": {
"DAOToken": "0x123...",
"ControllerCreator": "0x123...",
"DaoCreator": "0x123...",
"UController": "0x123...",
"GenesisProtocol": "0x123...",
"SchemeRegistrar": "0x123...",
"UpgradeScheme": "0x123...",
"GlobalConstraintRegistrar": "0x123...",
"ContributionReward": "0x123...",
"AbsoluteVote": "0x123...",
"QuorumVote": "0x123...",
"TokenCapGC": "0x123...",
"VestingScheme": "0x123...",
"VoteInOrganizationScheme": "0x123...",
"OrganizationRegister": "0x123...",
"Redeemer": "0x123..."
},
"dao": {
"name": "DAO Jones",
"Avatar": "0x123...",
"NativeToken": "0x123...",
"NativeReputation": "0x123..."
},
"test": {
"name": "0x123...",
"Avatar": "0x123...",
"NativeToken": "0x123...",
"NativeReputation": "0x123...",
"proposalId": "0xabc..."
}
}
Migration parameters
Example migration parameters object:
{
"orgName": "The DAO", // Sets the name of your DAO
"tokenName": "The DAO Token", // Sets the name of your DAO token
"tokenSymbol": "TDT", // Sets the name of your DAO token symbol
// Allow you to deploy and call any contract you might need during the migration
"StandAloneContracts":[
{
"name": "Reputation",
// If the contract is not from Arc you must have the contract data (ABI + Bytecode) as a JSON file with the same name as the scheme
"fromArc": true,
// If the contract should be created as a new contract, NOT a proxy. This is
// useful if the contract is not apart of the OpenZeppelin DAOstack package.
"noProxy": true,
// Add here any calls to the contract you want to execute
"runFunctions": [
{
"functionName": "transferOwnership",
"params": [
"AvatarAddress"
]
}
]
},
{
"name": "RepAllocation",
// If your contract has an initialize / constructor method which accepts arguments please add them here.
// unset constructor if using initialize
"constructor": false,
"params": [
100000,
{ "StandAloneContract": 0 }
],
"fromArc": true,
// Optional. Allows to use a specific Arc version for the StandAloneContract contract, default: Arc version of the DAO.
"arcVersion": "0.0.1-rc.30"
}
],
// Allows you to register and deploy schemes
"Schemes": {
{
"name": "ContributionReward",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 }
],
"permissions": "0x00000000",
"alias" : "ContributionRewardAlias"
},
{
"name": "SchemeRegistrar",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 },
{ "voteParams": 0 }
],
"permissions": "0x0000001F",
"alias" : "SchemeRegistrarAlias"
},
{
"name": "GlobalConstraintRegistrar",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 }
],
"permissions": "0x00000004",
"alias" : "GlobalConstraintRegistrarAlias"
},
{
"name": "UpgradeScheme",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 }
],
"permissions": "0x0000000A",
"alias" : "UpgradeSchemeAlias"
},
{
"name": "GenericScheme",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 },
"0x0000000000000000000000000000000000000000"
],
"permissions": "0x00000010",
"alias" : "GenericSchemeAlias"
},
{
"name": "GenericScheme",
"params": [
"GenesisProtocolAddress",
{ "voteParams": 0 },
"0x0000000000000000000000000000000000000001"
],
"permissions": "0x00000010",
"alias" : "GenericSchemeAlias2"
}
},
// Parameters list your DAO will use with the voting machines
// You can add here either Genesis Protocol parameters which will set the parameters in the GP voting machine or add a pre-set parameters hash to any voting machine
"VotingMachinesParams": [
{
"boostedVotePeriodLimit": 600,
"daoBountyConst": 10,
"minimumDaoBounty": 100,
"queuedVotePeriodLimit": 1800,
"queuedVoteRequiredPercentage": 50,
"preBoostedVotePeriodLimit": 600,
"proposingRepReward": 5,
"quietEndingPeriod": 300,
"thresholdConst": 2000,
"voteOnBehalf": "0x0000000000000000000000000000000000000000",
"votersReputationLossRatio": 1,
"activationTime": 0
},
{
"votingParamsHash": "0x000000000000000000000000000000paramshash" // If you want to use a different voting machine params you can set the parameters hash here
}
],
// List of addresses to mint initial tokens and reputation to
"founders": [
{
"address": "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1",
"tokens": 1000,
"reputation": 1000
},
{
"address": "0xffcf8fdee72ac11b5c542428b35eef5769c409f0",
"tokens": 1000,
"reputation": 1000
},
{
"address": "0x22d491bde2303f2f43325b2108d26f1eaba1e32b",
"tokens": 1000,
"reputation": 1000
},
{
"address": "0xe11ba2b4d45eaed5996cd0823791e0c93114882d",
"tokens": 1000,
"reputation": 1000
},
{
"address": "0xd03ea8624c8c5987235048901fb614fdca89b117",
"tokens": 1000,
"reputation": 1000
},
{
"address": "0x95ced938f7991cd0dfcb48f0a06a40fa1af46ebc",
"tokens": 1000,
"reputation": 1000
}
]
}
Develop
git clone https://github.com/daostack/migration.git && cd migration
npm install
- Install
Docker
andjq
Commands
-
cleandb
- rm the existing local db. -
ganache
- run a ganache instance with local db. -
migrate ...
- run migration (same arguments as cli) -
docker:build
- build the docker image from current directory (make sure all to migrate on a fresh ganache beforehand) -
docker:push
- push docker image to DockerHub. -
release ...
- fully release a version (requires an.env
file withkovan_provider
andkovan_private_key
variables set) (same arguments as cli)
How to release a version?
In order to release a version:
-
In one terminal tab:
-
npm run cleandb
- Clean any existing ganache DB. -
npm run ganache
- Run a ganache, creating a fresh DB.
-
-
In the another terminal tab:
-
Make sure you have the required
.env
variables set (kovan_provider
,kovan_private_key
,rinkeby_provider
,rinkeby_private_key
,mainnet_provider
,mainnet_private_key
). It should look something like this:kovan_provider="https://kovan.infura.io/v3/<YOUR_INFURA_KEY>" kovan_private_key="0x<YOUR_PRIVATE_KEY>" rinkeby_provider="https://rinkeby.infura.io/v3/<YOUR_INFURA_KEY>" rinkeby_private_key="0x<YOUR_PRIVATE_KEY>" mainnet_provider="https://mainnet.infura.io/v3/<YOUR_INFURA_KEY>" mainnet_private_key="0x<YOUR_PRIVATE_KEY>" xdai_provider="https://poa.api.nodesmith.io/v1/dai/jsonrpc?apiKey=<YOUR_XDAI_KEY>" xdai_private_key="0x<YOUR_PRIVATE_KEY>" sokol_provider="https://sokol.poa.network" sokol_private_key="0x<YOUR_PRIVATE_KEY>"
Note: Make sure you have enough ETH(or xDAI for the case of xDai/ SPOA in the case of Sokol) in the account corresponding to the private key you will use to pay the deployment gas costs.
-
Make sure you are not on the
master
branch. If needed, create a new branch for the release process. -
npm run prepare-release
- This will perform all the necessary steps to update version and prepare for a new release. The changes made here will be committed to the git branch. -
Create a PR and merge the new branch with the changes into
master
. -
Make sure that you have a Dockerhub ID with permission to push an image to the
daostack
organization. -
Make sure that you have an
npm
account with permission to push an image to thedaostack
organization. -
Make sure to be on the
master
branch and runnpm run release
- this will publish the new version to NPM and Dockerhub.
-