From the analysis performed by Precedence Research, the blockchain technology market size is expected to reach USD 69.7 Billion by 2025 and USD 1593.8 Billion by 2030. Demand of the blockchain developers are increasing day by day.
Growth Analysis of Blockchain Market:
Image Source: Precedence Research
People coming from any Industry be it Electronics, Software, Medical, Mechanical… “You need to keep learning to stay up to date in the current market”. Being a software engineer, new programming languages or tools change very frequently, but today we are not going to learn any new programming language considering that you are aware of Python programming.
This post will explain the steps of deploying smart contracts using Python and make you understand on how to do it independently and concisely. Before we dig into the article, we need to understand few things explained below:
- Python pre-requisites to deploy ledger Smartcontract
- About the libraries installation
- Details of the Platform for performing blockchain operations
Python pre-requisites to deploy ledger Smartcontract:
- For executing the code, we need the Python version 3.7 (or) above - Install
- For creating a project and writing / modifying the program, we need an IDE – Visual Studio / Pycharm
- We need a sample contract to work on - Solidity contract file
- Need below Python Libraries to interact with and manipulate the smart contract using python:
About the libraries Installation:
Run the following commands to install:
- Web3.py: $ pip install web3
- Solcx: $ pip install py-solc-x
- Eth_Utils: $ pip install eth-utils==1.1.2
- Dotenv: $ pip install python-dotenv
Note: When installing you might find issues related to library version. If you observe, try with below to resolve:
$ pip install web3==4.1.9
$ pip install eth-utils==1.10.0
Details of the Platform for performing blockchain operations:
No need to worry if you do not have prior experience or knowledge on Solidity, I have an article on this and it a “16 Step Guide to Setup and program a Ledger Smartcontract using Solidity” will help you understand step by step, till then you can use the sample file “SimpleStorage.sol” – Download
We will be using “Gananche” tool to perform blockchain operations locally before deploying. This tool is used to test blockchain transactions, inspect changes etc.. (Tool has both CLI and GUI)
7 Steps to Setup and program Smartcontract:
STEP – 1: Importing Libraries
from eth_utils import address
from web3 import Web3
import os
from solc import compile_standard, install_solc
from dotenv import load_dotenv
import json
STEP – 2: Reading the .SOL file using python
with open("./SimpleStorage.sol", "r") as file:
simple_storage_file = file.read()
STEP – 3: Compiling the Smartcontract
For this Step we use “py_solc_x” library to use standard compile function. This is used to break the code into Assembly Language, which is much closer to Machine Language for execution.
Before going into code, we need to understand 4 parameters used to compile Smartcontracts:
lauguage: Solidaty language to understand the details of the Smartcontract
sources: Smartcontract file, content and variables used to store information of Smartcontract
outputSelection: To get information related to ABI, Metadata, Bytecode and its sourcemap.
solc_version: This is the version used in the Smartcontract code
Once we understand the above information, Open the file and save it into JSON formatted file:
compiled_sol = compile_standard(
{
"language": "Solidity",
"sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
"settings": {
"outputSelection": {
"*": {
"*": ["abi", "metadata", "evm.bytecode", "evm.bytecode.sourceMap"]
}
}
},
},
solc_version="0.6.0",
)
with open("compiled_code.json", "w") as file:
json.dump(compiled_sol, file)
STEP – 4: Extraction (ABI & Bytecode from Solidity Smartcontract)
Bytecode contains the information for code execution. It includes the key commands in assembly language that are executed at low-level or machine-level instead of the whole smart contract. In other words, this is the code that is executed by Ethereum Virtual Machine (EVM) and which governs the working of the smart contract file.
Below code is in JSON format, this is from the compiled contract file
# get bytecode
bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"][
"bytecode"
]["object"]
Besides, ABI is “Application Binary Interface” this is also an important piece of information for a Smartcontract.
ABI in Smartcontract is responsible for interaction between methods and structures, it is similar to Application Programming Interface (API). In the above compiled JSON object if you print the data, you will find ABI with Smartcontract file inputs, names, rdata types and outputs etc..
# get abi
abi = json.loads(
compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["metadata"]
)["output"]["abi"]
STEP – 5: Local Ethereum Blockchain connection using Ganache
Install Ganache tool, use Quick Start and get the information from the tool.
w3 = Web3(
Web3.HTTPProvider("HTTP://127.0.0.1:7545")
)
chain_id = 1337
my_address = "0x23959D4e00640f2D152dA3F96474504e63Aa6d2D"
# private_key = os.getenv("PRIVATE_KEY")
private_key = "0x4d08735ff981fa51e9c56c79c99d121c9f66754c27926ca5014fdaa2d71e904f"
Few things to consider here:
- Add a 0x before pasting the private key from Ganache.
- It is good practice not to leave your private key in the code. Instead, create a new file–.env. In this file, write “PRIVATE_KEY=0x,” and after 0x, paste in the private key.
- To find out the Chain IDs of different blockchains, head here.
STEP – 6: Performing Smartcontract Transaction using Python
This is the part where you need to keeps your eyes wide open and do not get disturbed.
initialize the smart contract in Python by setting parameters for ABI and Bytecode
# initialize contract
SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)
Next it is important to know about Nonce - it’s an arbitrary number that can be used once in blockchain communication. Nonce tracks the number of transactions with help of function – “getTransactionCount” on the addressed used.
nonce = w3.eth.getTransactionCount(my_address)
Few things to consider here:
After creating Smartcontract in Python, there are 3 more things to do –
Ø Build the transaction
Ø Sign the transaction
Ø Send the transaction
Build the Ledger Transaction:
Web3.py has information we passed related to chainid, address of sender, and a nonce. Pass this information as variables so we can use it when required
tx = SimpleStorage.constructor().buildTransaction(
{
"chainId": chain_id,
"gasPrice": w3.eth.gas_price,
"from": my_address,
"nonce": nonce,
}
)
Sign the Ledger Transaction:
To sign the transaction we need to use the private key of the address of the sender, hence it is advised to store the private key separately instead of using directly in the code. Here we use the transaction build and private key as show below:
signed_tx = w3.eth.account.signTransaction(tx, private_key=private_key)
Send the Ledger Transaction:
This step uses the send_raw_transaction function with signed transaction parameter as shown below:
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
print(f"Contract deployed to Infura at address {tx_receipt.contractAddress}")
STEP – 7: Deploying Smartcontract using Python
We have arrived to last step which we are waiting from the starting of this article, but all the above steps are mandatory to get to this point.
To work with or interact with smart contracts in Python, you need ABI and address.
There are 2 ways to interact with blockchains – call and transact
Call: The functions in smart contracts that don’t make state changes or the view functions.
Transact: The function in smart contracts that do make state changes.
To make a state change, you must:
- First build a transaction,
- Then sign the transaction
- Then send the transaction
- Once the store function has been “transacted,”
call the retrieve function to fetch the value, function is used in below code to work with deployed contracts
simple_storage = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi)
print(f"Initial stored value at Retrieve {simple_storage.functions.retrieve().call()}")
new_transaction = simple_storage.functions.store(25).buildTransaction(
{
"chainId": chain_id,
"gasPrice": w3.eth.gasPrice,
"from": my_address,
"nonce": nonce + 1,
}
)
signed_new_txn = w3.eth.account.signTransaction(
new_transaction, private_key=private_key
)
tx_new_hash = w3.eth.sendRawTransaction(signed_new_txn.rawTransaction)
print("Sending new transaction...")
tx_new_receipt = w3.eth.waitForTransactionReceipt(tx_new_hash)
print(f"New stored value at Retrieve {simple_storage.functions.retrieve().call()}")