Smart contracts for the Brickblock platform


stars 🌟issues ⚠️updated 🛠created 🐣size 🏋️‍♀️
Minified + gzip package size for @brickblock/smart-contracts in KB


Brickblock Smart Contracts


  • This README shows how to work with our smart contracts.
  • ECOSYSTEM.md gives an architectural overview and detailed information about the individual contracts
  • TEST-AGAINST-GETH.md explains how to run the tests against geth instead of truffle's ganache
  • WORST-CASE-SCENARIOS.md analyzes what could go wrong along with potential mitigation steps



  1. Create local .env:

    cp .env.example .env

    This is necessary to configure the right $NODE_PATH for easier pathing, for example.

  2. Install dependencies:

  3. Install mythril, a security analysis tool for Ethereum smart contracts

    # You will need python3 and pip3 for this to work
    pip3 install mythril

Frozen Contracts

The directory frozen/ contains smart contract files and related tests that are considered frozen. The concept of 'frozen contracts' means that these contracts have been deployed to mainnet using a specific Solidity compiler version. Frozen contracts should not be upgraded or can not be upgraded. By filling out parts in our mainnet ecosystem, e.g. rich state that's hard to migrate to new contracts, more and more contracts won't be upgradable anymore. Only logic related to POA Tokens is designed to be upgradable through the delegatecall-pattern we apply. Since Truffle currently supports only one Solidity compiler version for the command truffle compile, we must make sure that all .sol files remain in contracts/. Thus frozen contracts represent a duplicate of contracts with the compiler version with which the contract was deployed to mainnet.

Currently, the following contracts are frozen:

  • BrickblockToken (version 0.4.18): The ICO is over and this contract holds significant state on mainnet. Cannot be upgraded.
  • BrickblockAccount (version 0.4.24): Since the ICO was finalized, this contract holds the company BBKs. Cannot be upgraded.
  • ContractRegistry (version 0.4.24): Holds references to other mainnet contracts. Referenced contracts, including frozen BrickblockAccount have been initialized with the ContractRegistry address. Thus, this contract cannot be upgraded.
  • CustomPOAToken (version 0.4.18): Not used anymore.
  • All other contracts can potentially still be upgraded although being deployed on mainnet. However, upgrades included re-registrations of contract addresses in ContractRegistry.

Generally, the current mainnet code of a smart contract can be found by first checking frozen/. If it's not there, the mainnet code can be found in contracts/.

Note: As the output bytecode changes between Solidity compiler versions, we have no guarantee that our tested contracts in contracts/ (single compiler version) actually behave the same way as the mainnet ecosystem (different compiler versions). This is a risk that we should address when Truffle supports compiling contracts under different compiler versions.


Tests are split in three categories: Main tests, Stress tests and Frozen Contract tests. In development mode we run all tests against truffle's ganache. Before submitting contracts to auditors or deploying contracts to Mainnet we always run the tests against geth, too. TEST-AGAINST-GETH.md explains how this works. It is a heck of a lot slower but it is closer to the production environment in which our contracts will eventually run so it gives as a higher degree of certainty that everything really works as expected.

Main Tests

Unit tests, testing the general functionality of our contracts.

Run them with:

yarn test

Stress Tests

Stress tests are implemented to mimic real world scenarios, such as creating reasonable random transaction amounts with maximum available iterations and users. That's why it is recomended to run these tests using an external ganache with the config mentioned below to assure there is enough money and users to put contracts under pressure. The stress tests throw random values at those contracts where integer division can result in minor inaccuracies. These tests ensure that this "dust" doesn't get too big to be of significance. They are split out of the normal tests because they take a very long time to run due to the amount of transactions being performed.

Run them with:

  • (Optional but recommended step) Run an external ganache with the following config, users: 50, default ether balance: 1000
  • Each stress test should be run individually. To run a stress test:
    yarn test stress-tests/[testFilename.js] --skip-migrations

Frozen Contract Tests

Tests of frozen contracts can be run with:

yarn test:frozen

Security Analysis

You can check for common smart contract vulnerabilities in our code with mythril:

yarn test:mythril


Linting both *.js and *.sol files can be done using:

yarn lint

Lint .sol only:

yarn lint:sol

Lint .js only:

yarn lint:js


Local testnet

Deploying with truffle will execute the migrations/2_deploy_contracts.js which does the following:

  1. Choose the right network configuration (depends on the --network argument)
  2. Deploy registry
  3. Deploy other contracts
  4. Add all contracts to registry
  5. Set ETH/EUR exchange rate
  6. Run finalizeTokenSale on BBK contract in order to activate the BBK/ACT/FMR ecosystem
  7. Distribute BBK tokens to accounts[2-5]

Note: Make sure you have at least 6 accounts on your node setup

  • account[0] is the owner
  • account[1] is the bonus address for BBK
  • account[2-5] are BBK token holders

To deploy in a local truffle session

  1. Run yarn truffle develop --network dev

  2. In the truffle console, run migrate --reset to deploy fresh contract instances

  3. Play around with the contracts, e.g. add an issuer via

        .then(poaManager => {

To deploy eco-system using migrations


There are pre-defined actions you can call with migrations

  • --forceDeploy, --fd: Deploys contracts given as parameters. 'all' means deploy everything. Can be used with --uec to deploy only selected contracts and use the rest from the registry.
  • --register, -r: Registers deployed contracts to Contract Registry
  • --setRate, --sr: Updates ExchangeRate Contract to fetch 'EUR' currency from oraclize api (on ganache it uses a constant value instead of a real one)
  • --finalizeBbk, --fb: on BBK contract:
    • calls changeFountainContractAddress
    • if the network is not mainnet, it distributes BBK token to Accounts[4,6]
    • calls finalizeTokenSale
    • calls unpause
  • --addIssuer, --ab: Adds accounts[1] as issuer to PoaManager
  • --deployPoa, --dp: Deploys a sample PoaToken with Issuer account
  • --addToWhiteList, --aw: Adds accounts[3] to whitelist
  • --default, -a: Executes register, setRate, finalizeBbk, addIssuer, addToWhitelist with the same order.
  • --useExistingContracts, --uec: Uses existing contracts instead of deploy if they exist in "config/deployed-contracts.js"' with the chosen network. If it cannot find a pre-defined address, it deploys a new contract.
  • --changeOwner, --co: Changes owner to NEW_OWNER given in .env file. Only useful if it deploys to mainnet.
  • --help: Displays posible options


  • You have to provide one of --forceDeploy [arguments] or --useExistingContracts to have the essential functionality.
  • Only essential actions are grouped by default action to keep it more flexible
  1. Start the Ganache app (make sure it's running on 8545in the settings!) or run yarn ganache-cli -p 8545
  2. Run yarn migrate:dev --[action name]


# Deploy with default actions
yarn migrate:dev --forceDeploy all --default

# Use pre-deployed contracts
yarn migrate:dev --useExistingContracts --default

# Short version
yarn migrate:dev --uec -def

# Deploy with some actions
yarn migrate:dev --forceDeploy all --register --setRate --finalizeBbk

# Deploy selected contracts only and use the rest from the registry
# Note: If contract addresses are not found in `.env` file for dev network or `config/deployed-contracts.js` for testnets, deployment script deploys a new one
yarn migrate:dev --forceDeploy AccessToken BrickblockAccount --useExistingContracts --register

# Forcing to use a contract outside of registry
# First you need to put it inside `.env` file for dev network or `config/deployed-contracts.js`
# then run:
yarn migrate:dev --useExistingContracts  --other params

# To deploy POA Token
# Make sure everything is deployed, registered, BBK finalized, currency set, issuers added and investors whitelisted
# To customize your token, use --deployPoa-[sub argument name]. See help for the full list.
yarn migrate:dev --useExistingContracts -deployPoa

# To see the full list of commands, ask for help
yarn migrate:dev --help

To deploy on Rinkeby, Kovan or Ropsten

  1. Make sure you set TESTNET_MNEMONIC and INFURA_API_KEY in .env file for your HD wallet
  2. Make sure you set ContractRegistry address field under the right network Id if you don't do a full deployment.
  3. Everything else is the same as local deployment
  4. Run
    yarn migrate:[network name] --def --fd all
    The network name can be rinkeby, kovan, or ropsten

Interacting with deployed contracts

When you'd like to interact with deployed contracts on a local testnet, check that truffle.js setting for dev matches your local testrpc / ganache-cli settings and run:

Using deployment script

  • Make sure you you are running a local testnet and deployed the contracts using deployment script.
  • Make sure you put ContractRegistry address to .env file. (see .env.example for an example)

There are some arguments to know before moving on:

  • --execute, --exec: you have to give a contract name as parameter to this argument. Currently it only supports PoaToken
  • --execute-functionName, --exec-fn: function name to be executed
  • --execute-arguments, --exec-args: function arguments. Any argument with the exact same order the function receives, seperated by comma or space
  • --execute-address, --exec-addr: PoaToken contract address. It can be a real address or index number in PoaManager token list.
  • --execute-txConfig, --exec-tc: tx params for the function to executed. Ex: '{"from":"0x1c34e1325d5193cdf95fc6e863edc789a798a23e", "value": 10000000}'

Example for starting Eth Sale

yarn migrate:dev --uec --exec PoaToken --exec-addr 0x3e5d48f04b942fce33f12eb582aa4364106962f5 --exec-fn startEthSale'

Example for buying poa token

# --exec-addr can be either a real POA token address or an index number on POA Manager token list

yarn migrate:dev --uec --exec PoaToken --exec-addr 0 --exec-fn buy --exec-tc '{"value":100000, "from":"0xb95cb8ffbdf31b9dc19caad6208a49c8248b6249"}'

Using Truffle Console

yarn truffle console --network dev.

This will open a node.js repl session, with all the compiled contracts available as usual (ie. BrickblockToken.deployed() or PoaToken.at(some-address)).

If you'd like to interact with contracts on a public testnet (ie. rinkeby, kovan) then we have a command that also uses truffle console and additionally makes use of the library truffle-hdwallet-provider. This allows us to specify a remote node to connect with and a mnemonic to give access to accounts in that HDWALLET (like MetaMask does).

NOTE: any valid bip39 mnemonic will work fine unless you want to send transactions or ETH, then you will need ETH in the sending account like usual. Feel free to use the example HDWALLET_MNEMONIC below.

An example for rinkeby is:

HDWALLET_MNEMONIC="ridge approve ten planet fever oyster cargo upper frequent humor hen alcohol" INFURA_URL="https://rinkeby.infura.io" yarn repl

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.