January 19, 2026

Brownie(Smart contracts Framework for Ethereum) Basics

Brownie(Smart contracts Framework for Ethereum) Basics

Brownie is a robust, easy to use framework for developing Ethereum smart contracts. Use cases include:

  • Deployment: Automate the deployment of many contracts onto the blockchain, and any transactions needed to initialize or integrate them.
  • Interaction: Write scripts or use the console to interact with your contracts on the mainnet, or for quick testing in a local environment.
  • Debugging: Get detailed information when a transaction reverts, to help you pinpoint the issue quickly.
  • Testing: Write unit tests in python and evaluate test coverage based on stack trace analysis. We make no promises.

Lets create a very simple smart contract in solidity, exposing only two external functions, getValue and setValue. Save this smart contract in a file, smart_contract.sol.

pragma solidity ^0.5.11;contract SimpleContract 
function getValue() external view returns(uint)
}

Lets try to deploy and interact with this smart contract with brownie.

Setup

we will use python3.7 and virtualenv to isolate our environment. if you dont have python3.7 installed, please follow these steps.

sudo add-apt-repository ppa:deadsnakes/ppa          
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt install -y python3.7
sudo apt-get install -y python3.7-dev python3-pip virtualenv python-dev solc

We will use ganache (Personal blockchain for Ethereum development), You can instead install ethereum-testrpc but then, we wouldn’t be able to run the graphical interface. Please follow the steps mentioned here to install Ganache.

Create a virtual environment for your solidity project, I have created it with the name TestBrownie. Install brownie.

pip install eth-brownie

To initialize an empty project, start by creating a new folder. From within that folder, type:

brownie init

Structure of a Project

Every Brownie project includes the following folders:

  • contracts/: Contract sources
  • interfaces/: Interface sources
  • scripts/: Scripts for deployment and interaction
  • tests/: Scripts for testing the project
  • brownie-config.yaml: Configuration file for the project

The following folders are also created, and used internally by Brownie for managing the project. You should not edit or delete files within these folders.

  • build/: Project data such as compiler artifacts and unit test results
  • reports/: JSON report files for use in the GUI

Compile

Copy your smart contract smart_contract.sol in the contracts directory. To compile all of the contract sources within the contracts/ subfolder of a project:

$ brownie compile

Each time the compiler runs, Brownie compares hashes of each contract source against hashes of the existing compiled versions. If a contract has not changed it is not recompiled. If you wish to force a recompile of the entire project, use brownie compile --all.

if you want to compile solidity contract with a different version just mention it in your pragma of .sol file, It will be installed automatically if not already present. One thing to notice here,

Settings for the compiler are found in brownie-config.yaml:

evm_version: null
minify_source: false
solc:
version: 0.6.0
optimize: true
runs: 200

Modifying any compiler settings will result in a full recompile of the project.

If a compiler version is set in the configuration file, all contracts in the project are compiled using that version. The version should be given as a string in the format 0.x.x.

If the version is set to null, Brownie looks at the version pragma of each contract and uses the latest matching compiler version that has been installed.

About evm_version, brownie sets the ruleset based on the compiler.

  • byzantium: Solidity <=0.5.4
  • petersburg: Solidity >=0.5.5 <=0.5.12
  • istanbul: Solidity >=0.5.13, Vyper

You can also set the EVM version manually. Valid options are byzantium, constantinople, petersburg and istanbul. You can also use the Ethereum Classic rulesets atlantis and agharta, which are converted to their Ethereum equivalents prior to being passed to the compiler.

Note:Brownie supports Solidity versions >=0.4.22 and Vyper version 0.1.0-b16.

After successful compile, brownie will create a SimpleContract.json in

builds/contract folder.

Deploy

if you open brownie-config.yaml it has a section for network. You can customize the exisiting networks or you can create a new block under networks. I am using ganache UI which runs on port 7545.

I have created a private block under networks.

network:
default: development # the default network that brownie connects to
settings:
gas_limit: "auto"
gas_price: "auto"
persist: true
reverting_tx_gas_limit: false # if false, reverting tx's will raise without broadcasting
networks:
# any settings given here will replace the defaults
private:
host: http://127.0.0.1:7545/
gas_price: 0
persist: false

save this file. Now to deploy our compiled smart contract we will use brownie console.The console is useful when you want to interact directly with contracts deployed on a non-local chain, or for quick testing as you develop. It’s also a great starting point to familiarize yourself with Brownie’s functionality.

The console feels very similar to a regular python interpreter. From inside a project folder, load it by typing:

$ brownie console
##if you want to use a specific network entioned in your config file, use
$ brownie console --network private
##this will connect your brownie console with your ganache private ##network.
Brownie v1.5.1 - Python development framework for Ethereum
Project is the active project.
Brownie environment is ready.

Lets explore

You can cross checks accounts in output with the accounts visible on ganacheUI.

>>> from brownie import accounts
>>> accounts
[<Account '0xd5373B59FDF14e9F1f5cc858eCAE0e6662FfedC1'>, <Account '0x533D7aa17435Ee227FdC30BA94fF8a509532D776'>, <Account '0x40E29Ca2269785f2F53d7E41006FC83eb3df4D0a'>, <Account '0x537f82751024Ed22F9f943e32A30e47B5A1Da6Df'>, <Account '0x28556574cfE7331738FadEE2fb6eC2630A9C142b'>, <Account '0xfe96534827B237951d4Ab4018Ff8c014B8918521'>, <Account '0xF32D5DfeCf6e1F6Fb2b29DF29Aba8fBd6bCB9D9E'>, <Account '0x88fdA9f0938A1fB5C5C902aeA8Bf28dE76d5467f'>, <Account '0xf6FAdCF3e805E61B1051A610a38365c74310ecCc'>, <Account '0x42904B9429E8d0599b90d6E24dF578684c0E03d3'>]

Each individual account is represented by an Account object that can perform actions such as querying a balance or sending ETH.

>>> accounts[0]
<Account '0xd5373B59FDF14e9F1f5cc858eCAE0e6662FfedC1'>
>>> dir(accounts[0])
[address, balance, deploy, estimate_gas, nonce, transfer]
>>> accounts[1].balance()
100000000000000000000
>>> accounts[0].transfer(accounts[1], "10 ether")
Transaction sent: 0xb9738009af0a8b721bca854572ce21622ebfeb2aca5d89eccfc55dfd42a5d202
Gas price: 0.0 gwei Gas limit: 21000
Transaction confirmed - Block: 1 Gas used: 21000 (100.00%)
<Transaction '0xb9738009af0a8b721bca854572ce21622ebfeb2aca5d89eccfc55dfd42a5d202'>
>>> accounts[1].balance()
110000000000000000000

Each deployable contract and library has a ContractContainer class, used to deploy new contracts and access already existing ones. All the contracts that were compiled will be available as a variable of the same name.

>>> type(SimpleContract)
<class 'brownie.network.contract.ContractContainer'>
>>> SimpleContract
[]
>>> SimpleContract.abi
[

],
'payable': False,
'stateMutability': "view",
'type': "function"
},

],
'name': "setValue",
'outputs': [],
'payable': False,
'stateMutability': "nonpayable",
'type': "function"
}
]
>>> accounts[0]
<Account '0xd5373B59FDF14e9F1f5cc858eCAE0e6662FfedC1'>

To deploy a contract with account 0.

>>> accounts[0].deploy(SimpleContract)
Transaction sent: 0xf0681bafbeae7e36de5a944fe247b6a8e08289906b602e986a5a8ca2c39d0df3
Gas price: 0.0 gwei Gas limit: 100127
SimpleContract.constructor confirmed - Block: 2 Gas used: 100127 (100.00%)
SimpleContract deployed at: 0x531afb27345047755741513b4dC70AD35e6F986b
<SimpleContract Contract '0x531afb27345047755741513b4dC70AD35e6F986b'>

if you type SimepleContract, you can see a list of deployed instances of SmartContract which is a ContractContainer object.

>>> SimpleContract
[<SimpleContract Contract '0x531afb27345047755741513b4dC70AD35e6F986b'>]

Interaction

To see the available methods on this contract.

>>> SimpleContract.signatures

Lets start by setting a variable in our smart contract.

>>> tx = SimpleContract[0].setValue(10000)
Transaction sent: 0x8efb92f53c3995294597b13b81c2b067e1cece2c29333accde7e9e7f61ee1acc
Gas price: 0.0 gwei Gas limit: 41717
SimpleContract.setValue confirmed - Block: 4 Gas used: 41717 (100.00%)

Each transaction returns a TransactionReceipt object. This object contains all relevant information about the transaction, as well as various methods to aid in debugging if it reverted.

To get human-readable information on a transaction, use TransactionReceipt.info().

>>> tx.info()
Transaction was Mined
---------------------
Tx Hash: 0x8efb92f53c3995294597b13b81c2b067e1cece2c29333accde7e9e7f61ee1acc
From: 0xd5373B59FDF14e9F1f5cc858eCAE0e6662FfedC1
To: 0x531afb27345047755741513b4dC70AD35e6F986b
Value: 0
Function: SimpleContract.setValue
Block: 4
Gas Used: 41717 / 41717 (100.0%)

To check

>>> SimpleContract[0].getValue()
10000

In the next section, I will try to explore Tests in Brownie. Brownie has lot to offer.

Published at Fri, 31 Jan 2020 20:48:51 +0000

{flickr|100|campaign}

Previous Article

Upcoming Social Platform Voice Will Seemingly Require KYC Verification » The Merkle Hash

Next Article

OKEx is set to Add Options Trading to its suite of products

You might be interested in …