Brownie Package Manager

Brownie allows you to install other projects as packages. Some benefits of packages include:

  • Easily importing and building upon code ideas written by others
  • Reducing duplicated code between projects
  • Writing unit tests that verify interactions between your project and another project

The Brownie package manager is available from the commandline:

$ brownie pm

Installing a Package

Brownie supports package installation from ethPM and Github.

Installing from Github

The easiest way to install a package is from a Github repository. Brownie considers a Github repository to be a package if meets the following criteria:

  • The repository must have one or more tagged versions.
  • The repository must include a contracts/ folder containing one or more Solidity or Vyper source files.

A repository does not have to implement Brownie in order to function as a package. Many popular projects using frameworks such as Truffle or Embark can be added as Brownie packages.

To install a package from Github you must use a package ID. A package ID is comprised of the name of an organization, a repository, and a version tag. Package IDs are not not case sensitive.

[ORGANIZATION]/[REPOSITORY]@[VERSION]

Examples

To install OpenZeppelin contracts version 3.0.0:

$ brownie pm install OpenZeppelin/openzeppelin-contracts@3.0.0

To install AragonOS version 4.0.0:

$ brownie pm install aragon/aragonos@4.0.0

Installing from ethPM

The Ethereum Package Manager (ethPM) is a decentralized package manager used to distribute EVM smart contracts and projects.

At its core, an ethPM package is a JSON object containing the ABI, source code, bytecode, deployment data and any other information that combines together to compose the smart contract idea. The ethPM specification defines a schema to store all of this data in a structured JSON format, enabling quick and efficient transportation of smart contract ideas between tools and frameworks which support the specification.

To obtain an ethPM package, you must know both the package name and the address of the registry where it is available. This information is communicated through a registry URI. Registry URIs use the following format:

ethpm://[CONTRACT_ADDRESS]:[CHAIN_ID]/[PACKAGE_NAME]@[VERSION]

The Snake Charmers maintain an ethPM registry explorer where you can obtain registry URIs.

Examples

To install OpenZeppelin’s Math package, served from the Snake Charmers Zeppelin registry:

$ brownie pm install ethpm://zeppelin.snakecharmers.eth:1/math@1.0.0

To install v2 of the Compound Protocol, served from the Snake Charmers DeFi registry:

$ brownie pm install ethpm://defi.snakecharmers.eth:1/compound@1.1.0

Working with Packages

Viewing Installed Packages

Use brownie pm list to view currently installed packages. After installing all of the examples given above, the output looks something like this:

$ brownie pm list
Brownie - Python development framework for Ethereum

The following packages are currently installed:

OpenZeppelin
└─OpenZeppelin/openzeppelin-contracts@3.0.0

aragon
└─aragon/aragonOS@4.0.0

zeppelin.snakecharmers.eth
└─zeppelin.snakecharmers.eth/access@1.0.0

defi.snakecharmers.eth
└─defi.snakecharmers.eth/compound@1.1.0

Exporting a Package

Use brownie pm export to copy the contents of a package into another folder. This is useful for exploring the filestructure of a package, or when you wish to build a project on top of an existing package.

To copy the Aragon package to the current folder:

$ brownie pm export aragon/aragonOS@4.0.0

Using Packages in your Project

Importing Sources from a Package

You can import sources from an installed package in the same way that you would a source within your project. The root path is based on the name of the package and can be obtained via brownie pm list.

For example, to import SafeMath from OpenZeppelin contracts:

import "OpenZeppelin/openzeppelin-contracts@3.0.0/contracts/math/SafeMath.sol";

You can modify the import path with the remappings field in your project configuration file. See Remapping Installed Packages for more information.

Using Packages in Tests

The pm fixture provides access to installed packages during testing. It returns a Project object when called with a project ID:

def test_with_compound_token(pm):
    compound = pm('defi.snakecharmers.eth/compound@1.1.0').CToken

See the unit test documentation for more detailed information.

Declaring Project Dependencies

Dependencies are declared by adding a dependencies field to your project configuration file:

dependencies:
    - aragon/aragonOS@4.0.0
    - defi.snakecharmers.eth/compound@1.1.0

Brownie attempts to install any listed dependencies prior to compiling a project. This is useful when your project may be used outside of your local environment.