DEV Community

Cover image for How To Deploy A Smart Contract On Blockchain Using Python
Subroto Kumar
Subroto Kumar

Posted on

How To Deploy A Smart Contract On Blockchain Using Python

Dependencies

Python

web3.py :
Web3.py is a Python library for interacting with Ethereum.

It’s commonly found in decentralized apps (dapp) to help with sending transactions, interacting with smart contracts, reading block data, and a variety of other use cases.

Installation:

pip install web3

Py-solc-x | Py-solc :

Py-solc is a Python wrapper and version management tool for the solc Solidity compiler

Installation:

pip install py-solc-x

Ganache UI | Cli

Installation:

  • Ganache Desktop Download Link Ganache UI download website
    OR
  • Ganache-cli : pip install ganache-cli

Lets Get Started

1. Open the directory where you have put your smart contract in the code editor like VSCode.

2. Create solidity file SmartContractDemo.sol.

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

contract SmartContractDemo {
    struct Person {
        string name;
        string dateOfBirth;
    }

    Person[] public idCard;

    function numberOfEntries() public view returns (uint256) {
        return idCard.length;
    }

    function store(string memory _name, string memory _birthday) public {
        idCard.push(Person(_name, _birthday));
    }

    function changeData(
        uint256 index,
        string memory _name,
        string memory _birthday
    ) public {
        require(index <= numberOfEntries(), "Given index not present");
        idCard[index] = Person(_name, _birthday);
    }

    function retrieve(uint256 index)
        public
        view
        returns (string memory, string memory)
    {
        require(index <= numberOfEntries(), "Given index not present");
        return (idCard[index].name, idCard[index].dateOfBirth);
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Next create a python file deploy.py. Here, we write the code required to push our contract to the blockchain.

4. First add the below code to import the web3 and py-solc-x in python files:

from web3 import Web3
from solcx import compile_standard, install_solc

import json
Enter fullscreen mode Exit fullscreen mode

5. Read and store the content of SmartContractDemo.sol in a separate variable:

# extract the content of SmartContractDemo.sol
with open("./SmartContractDemo.sol", "r") as file:
    smart_contract_demo = file.read()
Enter fullscreen mode Exit fullscreen mode

6. Run the below code to install solc and compile the solidity code:

install_solc("0.6.0")

# Solidity source code
compiled_sol = compile_standard(
    {
        "language": "Solidity",
        "sources": {"SmartContractDemo.sol" : { "content" : smart_contract_demo_file }},
        "settings": {
            "outputSelection": {
                "*": {
                    "*": ["abi","metadata","evm.bytecode","evm.sourceMap"]
                }
            }
        }
    },
    solc_version="0.6.0",
)
Enter fullscreen mode Exit fullscreen mode

7. The below code will put in the compiled_code as a new JSON file.

with open("compiled_code.json","w") as file:
    json.dump(compiled_sol,file)
Enter fullscreen mode Exit fullscreen mode

8. Now before we deploy this contract, we need abi and bytecode first which we can get from compiled_code. This can be achieved by using this code:

# get abi
abi = compiled_sol["contracts"]["SmartContractDemo.sol"]["SmartContractDemo"]["abi"]

# bytecode
bytecode = compiled_sol["contracts"]["SmartContractDemo.sol"]["SmartContractDemo"]["evm"]["bytecode"]["object]
Enter fullscreen mode Exit fullscreen mode

9. Connecting to Ganache:

To connect with ganache, we need an HTTP Provider URL, chain-id, the public key & private key which will be going to be used for deploying our smart contract.

How to get HTTP provider, chain-id, the public and private key of Transaction account:

If you are using Ganache UI

Step 1: Open Ganache App.

Step 2: Click on the Quickstart button.

Ganche-ui starting page

ganche-cli overview.jpg

This is what Ganache-UI looks like were

  • White-outlined box give us the RPC server i.e., http://127.0.0.1:7545
  • Yellow-outlined box give us chain_id i.e, 5777
  • Red-outlined box marks the public key of the account e.g., 0xE1584b4d8f1b0CeEF97190B296DaF446674A3d63
  • Blue-outlined box point to the button will show the private key associated with the given account

or

If you are using Ganache-CLI

Step 1: Open a terminal and then run the given command: ganache-cli.

This will launch the ganache-cli terminal.

image.png

Step 2: Copy and note the public key and private key associated with any account, clain-id, and RPC server url which is http://127.0.0.1:8545 in my case.

Important Note:

  • Accounts provided in the Ganache are only meant for development and testing purposes. Please, don't try to do actual transactions.
  • Private keys are highly confidential. So, keep your private keys safe. It allows the user to access the wallet.

10. Managing private key

Adding private key:

Even if we are just using the private key associated with ganache, for best practice we should always avoid hard coding private key in our coding.

So, to store the private key, we will add it as an environment variable and extract it in our python program deploy.py using OS module.

To do so :

  • Inside same directory, add a file .env
  • Open .env file and write: export $PRIVATE_KEY=<put your private key here> e.g., ![[Pasted image 20220523145104.png]]
  • Head back to deploy.py and import these module at the top: ![[Pasted image 20220523145413.png]]

11. Go back to our deploy.py and connect it with ganache.

# Connecting to ganache
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
chain_id = 5777
my_address= "0xE1584b4d8f1b0CeEF97190B296DaF446674A3d63"
private_key = os.getenv("PRIVATE_KEY")
Enter fullscreen mode Exit fullscreen mode

12. Now let's create the contract in python and get the latest transaction.

# Creating contract in python
SmartContractDemo = w3.eth.contract(abi=abi, bytecode=bytecode)

# Get the latest transaction
transaction = SmartContractDemo.constructor().buildTransaction({
    "chainId": chain_id,
    "gasPrice": w3.eth.gas_price,
    "from": my_address,
    "nonce": nonce,
})
Enter fullscreen mode Exit fullscreen mode

13. Finally, let's sign our transaction and deploy it.

# Sign the transaction
signed_txn = w3.eth.account.sign_transaction(transaction, private_key=private_key)

print("Deploying Contract!")
# Sent it
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)

# Wait for the transaction to be mined, and get the transaction receipt
print("Waiting for Transaction to finish...")

tx_receipt=w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Done! Contract Deployed to {tx_receipt.contractAddress}")
Enter fullscreen mode Exit fullscreen mode

Well done! We have successfully learned to deploy Smart Contract to the local blockchain.

Interacting with our smart contract

There are two types of Interaction one can make with a Smart Contract:

  1. Call -> Simulate making the call and getting a return value
  2. Transact -> Actually make a state change

Let's perform both the interaction with our smart contract :

1. To call a public function numberOfEnteries()from SmartContractDemo, go back to deploy.py.

# Working with the contracts
smart_contract_demo = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi)

print(f"Number of Enteries in idCard array is {smart_contract_demo.functions.numberOfEnteries()}")
Enter fullscreen mode Exit fullscreen mode

2. Now a state change by adding a data to the idCard array using the function store():

store_transaction = smart_contract_demo.functions.store("Naruto", "10-10-1999").buildTransaction({
    "chainId": chain_id,
    "gasPrice": w3.eth.gas_price,
    "from":my_address,
    "nonce":nonce+1,
})

signed_store_txn = w3.eth.account.sign_transaction(
    store_transaction, private_key=private_key
)

signed_store_hash = w3.eth.send_raw_transaction(signed_store_txn.rawTransaction)

tx_receipt = w3.eth.wait_for_transaction_receipt(signed_store_hash)
Enter fullscreen mode Exit fullscreen mode

Whenever we make a state change, the transaction has to be signed first with our private key.

Note:
Calling a view or pure public function doesn't cost anything.
Whereas deploying a smart contract and making a function call that changes the state of the blockchain cost some amount of GAS Fees.

3. Finally, finish it by again calling numberOfEnteries() function and retrieve() function.

print(f"Number of Enteries in idCard array is {smart_contract_demo.functions.numberOfEnteries()}")

print(f"Person at 0th index in idCard array is {smart_contract_demo.functions.idCard(0)}")
Enter fullscreen mode Exit fullscreen mode

4. Now run the deploy.py file (run via terminal: python ./deploy.py).

OUTPUT:

image.png
Now, if we check the ganache-cli, we can find two transaction records there,

  1. The First transaction is about contract creation.
  2. The Second transaction is made we call the store function to add Personal detail to idCard array.

image.png

Resource Link

Project Link:

Documentation:

CONNECT WITH ME

I hope you have found this article helpful. Thank you for reading!

Top comments (0)