@dorgtech/migration-experimental

A repo for handling DAOstack contract migrations

Usage no npm install needed!

<script type="module">
  import dorgtechMigrationExperimental from 'https://cdn.skypack.dev/@dorgtech/migration-experimental';
</script>

README

npm (scoped) Docker Pulls Build Status

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:

  1. Base migration - of universal contracts from the @daostack/arc package.
  2. 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

  1. 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

  1. 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:

  1. 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 then npm -v.

  2. In your terminal, use this command to install the DAOstack migration CLI: npm install --global @daostack/migration.

  3. Create a new your-new-dao-params.json file, you can also use the same migration-params.json from the DAOstack migratio GitHub repo.

  4. 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.

  5. Obtain a URL of an Ethereum node connected to your desired network. You can also use Infura for that.

  6. 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.

  7. 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>.

  8. 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

  1. docker pull daostack/migration
  2. Run: docker run --rm --name=ganache daostack/migration:0.0.0-alpha.56-v7 <ganache-cli arguments>
  3. Fetch migration result file: docker exec ganache cat migration.json
  4. 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

  1. git clone https://github.com/daostack/migration.git && cd migration
  2. npm install
  3. Install Docker and jq

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 with kovan_provider and kovan_private_key variables set) (same arguments as cli)

How to release a version?

In order to release a version:

  1. In one terminal tab:

    1. npm run cleandb - Clean any existing ganache DB.
    2. npm run ganache - Run a ganache, creating a fresh DB.
  2. In the another terminal tab:

    1. 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.

    2. Make sure you are not on the master branch. If needed, create a new branch for the release process.

    3. 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.

    4. Create a PR and merge the new branch with the changes into master.

    5. Make sure that you have a Dockerhub ID with permission to push an image to the daostack organization.

    6. Make sure that you have an npm account with permission to push an image to the daostack organization.

    7. Make sure to be on the master branch and run npm run release - this will publish the new version to NPM and Dockerhub.