Subscribe to our free newsletter

To make sure you won't miss any valuable content we share with our community.

Using Brownie to Switch between Different Networks

In this article, we are going to switch between the different available networks we can connect to, using Brownie. Then, we’ll write a statement in the Deploy.py to connect to the network requested in the terminal by the user (the developer). This kind of script for network management makes it easy for us to connect to any network that we want at any time it is required for testing and other purposes.

How to Switch between Networks

As you know, we have different networks to work with. We have already used some of them for deploying our contracts. Sometimes we need to write our deploy.py file in a way that we can switch between different networks and accounts and the deploy.py must understand which ones are available.

Switch between Different Networks

Before we get started with this task, we can check the keywords when we want to connect to different accounts. To look up the keyword related to any network, we write:

brownie networks list

Result:

Brownie v1.18.1 - Python development framework for Ethereum The following networks are declared: Ethereum ├─Mainnet (Infura): mainnet ├─Ropsten (Infura): ropsten ├─Rinkeby (Infura): rinkeby ├─Goerli (Infura): goerli └─Kovan (Infura): kovan Ethereum Classic ├─Mainnet: etc └─Kotti: kotti Arbitrum └─Mainnet: arbitrum-main Avalanche ├─Mainnet: avax-main └─Testnet: avax-test Aurora ├─Mainnet: aurora-main └─Testnet: aurora-test Binance Smart Chain ├─Testnet: bsc-test └─Mainnet: bsc-main Fantom Opera ├─Testnet: ftm-test └─Mainnet: ftm-main Harmony └─Mainnet (Shard 0): harmony-main Moonbeam └─Mainnet: moonbeam-main Optimistic Ethereum ├─Mainnet: optimism-main └─Kovan: optimism-test Polygon ├─Mainnet (Infura): polygon-main └─Mumbai Testnet (Infura): polygon-test XDai ├─Mainnet: xdai-main └─Testnet: xdai-test Development ├─Ganache-CLI: development ├─Geth Dev: geth-dev ├─Hardhat: hardhat ├─Hardhat (Mainnet Fork): hardhat-fork ├─Ganache-CLI (Mainnet Fork): mainnet-fork ├─Ganache-CLI (BSC-Mainnet Fork): bsc-main-fork ├─Ganache-CLI (FTM-Mainnet Fork): ftm-main-fork ├─Ganache-CLI (Polygon-Mainnet Fork): polygon-main-fork ├─Ganache-CLI (XDai-Mainnet Fork): xdai-main-fork ├─Ganache-CLI (Avax-Mainnet Fork): avax-main-fork └─Ganache-CLI (Aurora-Mainnet Fork): aurora-main-fork

As you can remember, we have used Rinkeby from Infura a number of times and here the keyword for Rinkeby (Infura) is Rinkeby. Here, when we work with Brownie, in order to define the Infura RPC URL on the .env file, we need to write it in a different format:
export WEB3_INFURA_PROJECT_ID=80ca094b614b44b3b647ceb01a2b70d0
Notice that if you write any word other than WEB3_INFURA_PROJECT_ID, you will have a problem working with the Rinkeby or other networks of Infura, because Brownie has some built-in scripts that read from the ID with only this name.

Swtich Between Networks via Network Management in Deploy.py

The next thing we should do when we want to check for networks available for deployment is to add the following function to our deploy.py file:


def get_account():
	if network.show_active() == "development":
		return accounts[0]
	else:
		return accounts.add(config["wallets"]["from_key"])


And whenever we want to define our account, we write:
Account = get_account()
It is also necessary to import the network from Brownie:
from Brownie import network
The above code checks whether we want to use our Ganache CLI test accounts or use any other accounts that we have defined its a private key to our .env file and introduced to Brownie.
In order to connect to Rinkeby account in our Metamask wallet (that we entered its private key in the .env file), and the Rinkeby test network, in the terminal we should type:

brownie run scripts/deploy.py --network rinkeby

Result:

Brownie v1.18.1 - Python development framework for Ethereum BrownieSimpleStorageProject is the active project. Running 'scripts/deploy.py::main'... Transaction sent: 0xbfe6fb9f152eeda4fc880fc5a5cb6f74b0d73b440ada91e8bef71fb7fccf1ccd Gas price: 1.000000012 gwei Gas limit: 367598 Nonce: 48 SimpleStorage.constructor confirmed Block: 10426128 Gas used: 334180 (90.91%) SimpleStorage deployed at: 0x1570258Ee66a921A3f5fdEA48f5ba54bE657AA8b 0 Transaction sent: 0x0a5d8886732d99e6045eede0958894a033e48225d6818c312491b178195576ed Gas price: 1.000000012 gwei Gas limit: 47842 Nonce: 49 SimpleStorage.store confirmed Block: 10426129 Gas used: 43493 (90.91%) SimpleStorage.store confirmed Block: 10426129 Gas used: 43493 (90.91%) 38

And you can see the transaction related to contract deployment and storing a value inside the contract has been successfully completed on the Rinkeby network. Because we are working with Rinkeby, the transaction is trackable on this link. To be able to track it, simply copy and paste the address of the transaction into the search bar of the Etherscan.

Etherscan

Reading from the Contracts

One of the useful and necessary steps in writing an application related to a smart contract is being able to read from the transaction. The following steps will help you retrieve the different properties of the deployed smart contracts.
First, create a file in the scripts folder and name it read_value.py then write the following code in it.


from brownie import SimpleStorage, accounts, config

def read_contract():
	print(SimpleStorage)

def main():
	read_contract()


The above code, reads the contract deployments and their transactions. Let’s see the result by typing in the terminal:

brownie run scripts/read_value.py --network rinkeby

Result:

Brownie v1.18.1 - Python development framework for Ethereum BrownieSimpleStorageProject is the active project. Running 'scripts/read_value.py::main'...

The above result shows an array inside which we can retrieve the first member by changing the code to:


from brownie import SimpleStorage, accounts, config

def read_contract():
	print(SimpleStorage[0])

def main():
	read_contract()


brownie run scripts/read_value.py --network rinkeby

Result:

Brownie v1.18.1 - Python development framework for Ethereum BrownieSimpleStorageProject is the active project. Running 'scripts/read_value.py::main'... 0x1570258Ee66a921A3f5fdEA48f5ba54bE657AA8b

If you take a closer look, you will see that the address given here, is just the same address that we saw on Etherscan (the address of the contract deployment). It is worth knowing that if you want to retrieve the latest address contract that has been deployed, instead of print(SimpleStorage[0]) you can write print (SimpleStorage[-1]).
Notice that Brownie already knows the address and the ABI of our smart contract because it has saved it in a .json file. Also, if we want to retrieve a number again without asking the blockchain for it, we can retrieve it in the read_value.py file by writing:


print(SimpleStorage[-1].retrieve()

Result:

38

Summing Up

In this article, we have managed to write a script that makes it easy to switch between different networks such as Testnet (like Rinkeby), Mainnet, and local (like Ganache CLI) for the users and the developers. With this script written in the deploy.py, we can choose the network at the time of running Brownie by simply calling the network’s name in the terminal.

Download this Article in PDF format

web developement

Check Out Our Services

In Arashtad, we’re working on 3D games, metaverses, and other types of WebGL and 3D applications with our 3D web development team. However, our services are not limited to these. Back-end developments, front-end developments, 3d modeling, and animations are in our arsenal too.

Arashtad Serivces
Drop us a message and tell us about your ideas.
Tell Us What You Need
Blockchain Development

Testing Deploy.py Script Using Brownie: A Full Analysis

In this post, we will complete testing our deploy.py script using Brownie in more detail so that we can see if there is any problem at all. And if there is, we can analyze it in more detail. This kind of detailed test and code analysis becomes handy, especially when the code is too long and complex that we cannot so easily understand where the unexpected result originates from.

Detailed Testing Deploy.py Using Brownie

For more detailed testing, we can write in the terminal:

brownie test -k

Which in our case will be:

brownie test -k test_updating_storage

And the result will be:

Brownie v1.18.1 - Python development framework for Ethereum ===================================================== test session starts ===================================================== platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: /home/mohamad/Desktop/solidity/Solidity and web3 codes/brownie_simple_storage plugins: eth-brownie-1.18.1, web3-5.27.0, xdist-1.34.0, forked-1.4.0, hypothesis-6.27.3 collected 2 items / 1 deselected / 1 selected Launching 'ganache-cli --chain.vmErrorsOnRPCResponse true --server.port 8545 --miner.blockGasLimit 12000000 --wallet.totalAccounts 10 --hardfork istanbul --wallet.mnemonic brownie'... tests/test_simple_storage.py . [100%] =============================================== 1 passed, 1 deselected in 1.85s =============================================== Terminating local RPC client...

And if we write anything wrong in our code, by running:

brownie test --pdb

In the terminal, we will see:

Brownie v1.18.1 - Python development framework for Ethereum ===================================================== test session starts ===================================================== platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: /home/mohamad/Desktop/solidity/Solidity and web3 codes/brownie_simple_storage plugins: eth-brownie-1.18.1, web3-5.27.0, xdist-1.34.0, forked-1.4.0, hypothesis-6.27.3 collected 2 items Launching 'ganache-cli --chain.vmErrorsOnRPCResponse true --server.port 8545 --miner.blockGasLimit 12000000 --wallet.totalAccounts 10 --hardfork istanbul --wallet.mnemonic brownie'... tests/test_simple_storage.py F >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> def test_deploy(): account = accounts[0] simple_storage = SimpleStorage.deploy({"from": account}) starting_value = simple_storage.retrieve() expected = 38 > assert starting_value == expected E assert 0 == 38 tests/test_simple_storage.py:10: AssertionError >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> > /home/mohamad/Desktop/solidity/Solidity and web3 codes/brownie_simple_storage/tests/test_simple_storage.py(10)test_deploy() -> assert starting_value == expected

This shows that in the first function we mistakenly expected the stored value to be 38 which was 0 at first. We can also do some sort of debugging next to PDB in the terminal for example we can write:

(Pdb) expected >> 38

Which shows 38 as the number stored in expected, or:

(Pdb) simple_storage.retrieve() >>0

By understanding the difference between the expected number and the retrieved one, we will be able to debug the code.

(Pdb) simple_storage

The better way to fully understand the problems and be able to find it, is to type in the terminal:

brownie test -s Brownie v1.18.1 - Python development framework for Ethereum ===================================================== test session starts ===================================================== platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /home/mohamad/.local/pipx/venvs/eth-brownie/bin/python cachedir: .pytest_cache hypothesis profile 'brownie-verbose' -> verbosity=2, deadline=None, max_examples=50, stateful_step_count=10, report_multiple_bugs=False, database=DirectoryBasedExampleDatabase(PosixPath('/home/mohamad/.brownie/hypothesis')) rootdir: /home/mohamad/Desktop/solidity/Solidity and web3 codes/brownie_simple_storage plugins: eth-brownie-1.18.1, web3-5.27.0, xdist-1.34.0, forked-1.4.0, hypothesis-6.27.3 collected 2 items Launching 'ganache-cli --chain.vmErrorsOnRPCResponse true --server.port 8545 --miner.blockGasLimit 12000000 --wallet.totalAccounts 10 --hardfork istanbul --wallet.mnemonic brownie'... tests/test_simple_storage.py::test_deploy FAILED tests/test_simple_storage.py::test_updating_storage PASSED ========================================================== FAILURES =========================================================== _________________________________________________________ test_deploy _________________________________________________________ def test_deploy(): account = accounts[0] simple_storage = SimpleStorage.deploy({"from": account}) starting_value = simple_storage.retrieve() expected = 38 > assert starting_value == expected E assert 0 == 38 E +0 E -38 tests/test_simple_storage.py:10: AssertionError =================================================== short test summary info =================================================== FAILED tests/test_simple_storage.py::test_deploy - assert 0 == 38 ================================================= 1 failed, 1 passed in 1.94s ================================================= Terminating local RPC client…

As you can see in the result, the code and its variables are fully analyzed.

Fixing the Code

Now if we fix our code and change the expected in the first function to 0:


from brownie import SimpleStorage, accounts
def test_deploy():

	account = accounts[0]
	simple_storage = SimpleStorage.deploy({"from": account})
	starting_value = simple_storage.retrieve()
	expected = 0
	assert starting_value == expected

def test_updating_storage():

	account = accounts[0]
	simple_storage = SimpleStorage.deploy({"from": account})
	expected = 38
	simple_storage.store(expected,{"from":account})
	assert expected == simple_storage.retrieve()
	



And test our deployment again:

brownie test -s

We will see:

rownie v1.18.1 - Python development framework for Ethereum ===================================================== test session starts ===================================================== platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /home/mohamad/.local/pipx/venvs/eth-brownie/bin/python cachedir: .pytest_cache hypothesis profile 'brownie-verbose' -> verbosity=2, deadline=None, max_examples=50, stateful_step_count=10, report_multiple_bugs=False, database=DirectoryBasedExampleDatabase(PosixPath('/home/mohamad/.brownie/hypothesis')) rootdir: /home/mohamad/Desktop/solidity/Solidity and web3 codes/brownie_simple_storage plugins: eth-brownie-1.18.1, web3-5.27.0, xdist-1.34.0, forked-1.4.0, hypothesis-6.27.3 collected 2 items Launching 'ganache-cli --chain.vmErrorsOnRPCResponse true --server.port 8545 --miner.blockGasLimit 12000000 --wallet.totalAccounts 10 --hardfork istanbul --wallet.mnemonic brownie'... tests/test_simple_storage.py::test_deploy PASSED tests/test_simple_storage.py::test_updating_storage PASSED ====================================================== 2 passed in 2.08s ====================================================== Terminating local RPC client...

Brownie test uses the functions in the Pytest module and you can use more functions than mentioned here to be able to have all different kinds of analysis on your smart contract deployment.

What We Achieved through Testing Deploy.py Using Brownie

In this article, we’ve completed testing the deployments of the smart contracts (deploy.py script) using Brownie in more detail, so that we can see if there is any problem at all and if there is, we can analyze it in more detail. This kind of detailed test and code analysis becomes handy, especially when the code is too long and complex that we cannot so easily understand where the unexpected result originates from.

Download this Article in PDF format

metaverse

What Do We Do in Arashtad?

3D websites, 3D games, metaverses, and other types of WebGL and 3D applications are what we develop in our 3D web development team.

Arashtad Serivces
Drop us a message and tell us about your ideas.
Request a Quote
ThreeJS Development

Introduction to Brownie-mix: A Boilerplate for Important Smart Contract Projects

In this article, we are going to get familiar with Brownie-mix as a boilerplate for blockchain projects in python. Using this boilerplate with the Brownie bake command will help you have so many of the dependency contracts provided for that specific project. There is also a complete brownie_config.yaml file provided with a complete list of networks. Some ready python files such as helpful_scripts.py and deploy_mocks.py are provided for you.

Introduction to the Brownie-mix

When we were examining how to deploy a smart contract using python web3 tools among our previous articles, we showed how to use Brownie. It is highly recommended that before you start this tutorial, be familiar with web3 python tools and also solidity language.
So far, we have coded most of our smart contract deployments using Brownie by starting like this in the terminal:

brownie init

And then some folders would have been created and then the rest of the project. But the hard part was that we needed to copy a lot of dependencies, such as the VRFConsumer.sol and other smart contracts, brownie-config.yaml file, helpful_scripts.py, deploy_mocks.py, and a lot of other useful scripts that we need to rewrite every time we created the project.
A Brownie-mix helps us cover this hard task and provides easy boilerplates for every type of project like DAO, NFTs, Token, ChainLink, and so on.

Brownie-mix

To Use Brownie-mix: Starting the Brownie Template

In order to use Brownie-mix boilerplates, we should first write the following command in the terminal:

brownie bake

In our case, for example, we want chainlink-mix (using which we have managed to write and deploy our contracts, so far).

brownie bake chainlink-mix
cd chainlink

And you will see that all the folders and files alongside all the necessary routine codes are provided for you in your directory called chainlink.

Brownie-mix

Modifying brownie_config.yaml

Notice that in the brownie-config.yaml, you should modify some parts:


# exclude SafeMath when calculating test coverage
# https://eth-brownie.readthedocs.io/en/v1.10.3/config.html#exclude_paths
reports:
	exclude_contracts:
		- SafeMath
dependencies:
	- smartcontractkit/[email protected]
	- OpenZeppelin/[email protected]
compiler:
	solc:
		remappings:
			- "@chainlink=smartcontractkit/[email protected]"
			- "@openzeppelin=OpenZeppelin/[email protected]"
# automatically fetch contract sources from Etherscan
autofetch_sources: True
# Uncomment to use the .env file
# dotenv: .env
# set a custom mnemonic for the development network
networks:
   default: development
   development:
		keyhash:"0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4"
		fee: 100000000000000000
		jobId: "29fa9aa13bf1468788b7cc4a500a45b8"
		update_interval: 60
		verify: False
   kovan:
	vrf_coordinator: "0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9"
	link_token: "0xa36085F69e2889c224210F603D836748e7dC0088"
	keyhash:"0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4"
	fee: 100000000000000000
	oracle: "0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8"
	jobId: "d5270d1c311941d0b08bead21fea7747"
	eth_usd_price_feed: "0x9326BFA02ADD2366b30bacB125260Af641031331"
	# Change to True if you have an Etherscan API key and want to verify
	verify: True
	update_interval: 60
   ganache:
	keyhash:"0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4"
	fee: 100000000000000000
	jobId: "29fa9aa13bf1468788b7cc4a500a45b8"
	update_interval: 60
	verify: False
	rinkeby:
	vrf_coordinator: "0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B"
	link_token: "0x01be23585060835e02b77ef475b0cc51aa1e0709"
	keyhash:"0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311"
	fee: 100000000000000000
	oracle: "0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8"
	jobId: "6b88e0402e5d415eb946e528b8e0c7ba"
	eth_usd_price_feed: "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e"
	# Change to True if you have an Etherscan API key and want to verify
	verify: False
   fuji:
	link_token: "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846"
	fee: 100000000000000000
	oracle: "0xcc80934eaf22b2c8dbf7a69e8e0d356a7cac5754"
	jobId: "5ca4fa9b2d64462290abfbda84e38cf4"
   mumbai:
	eth_usd_price_feed: "0x0715A7794a1dc8e42615F059dD6e406A6594651A"
	link_token: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB"
	vrf_coordinator: "0x8C7382F9D8f56b33781fE506E897a4F1e2d17255"
	keyhash:"0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4"
	fee: 1000000000000000000
   binance:
	# link_token: ??
	eth_usd_price_feed: "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e"
   binance-fork:
	eth_usd_price_feed: "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e"
   mainnet-fork:
	eth_usd_price_feed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"
   matic-fork:
	eth_usd_price_feed: "0xF9680D99D6C9589e2a93a78A04A279e509205945"
wallets:
	from_key: ${PRIVATE_KEY}
	from_mnemonic: ${MNEMONIC}



Notice that if you use mnemonic, you should use accounts.from_mnemonic to be able to use from_mnemonic and if you use the private key, you should use accounts.add instead.
Also, make sure to uncomment the dotenv: .env if you want to keep your private data somewhere safe.
By using the above .yaml file, you can use any networks that you want and be sure that there is nothing else needed to add to this file. In the contracts folder, you will also be able to see some useful contracts that work as a dependency. The most important folder is the scripts, inside which we have helpful_scripts.py, deploy_mocks.py, and some useful scripts that will help using them in your main deploy.py file.

Brownie-mix

As you can see, some of the important and useful functions of useful_scripts.py are as follows:


get_account

get_contract

fund_with_link

deploy_mocks


Using the above functions, you can write your test files and deploy.py file much easier.

Final Word on Brownie-mix

In this article, we have introduced Brownie-mixes as a boilerplate (template) for blockchain projects and provided guides on how to quickly modify them so that you can run your desired project instantly. These projects could be creating an ERC-20 token, NFT, Aave protocol, Chainlink, and so on.

Download this Article in PDF format

metaverse

Care to Know About Metaverse?

In Arashtad, we are providing custom services on 3d developments such as 3d websites, 3d models, metaverses and all 3d applications.

Arashtad Serivces
Drop us a message and tell us about your ideas.
Tell Us What You Need
Blockchain Development