Interacting With On-Chain Contracts

Building => Using Smart Contracts

In the first of two asides, we will discuss how to utilize smart contracts. At this point of the textbook, we have become proficient Solidity developer and have become accustomed to building smart contracts. While it is important to learn the art of building smart contracts, an equally important skill is learning how to interact with them outside the Solidity programming language.

Given that the computer science curriculum at Cornell gives students a substantial amount of experience in Python, we will approach this section from a data science perspective.

Prerequisites

For this section, we required that students have both Python and Jupyter Notebooks installed on their computers.

What Library to Use?

The first question that comes to mind is what library to use to interact with contracts? Each library has its pros and cons, but we can separate libraries by programming languages:

  • JavaScript: web3.js, ethers.js

  • Rust: ethers.rs

  • Python: web3.py

For the purposes of this section, we will be using web3.py

Getting Started with web3.py

Assuming that you have Python and Jupyter Notebook installed on your computer, the first step in getting started with web3.py is to download the library itself.

pip install web3

Afterwards, create a new Jupyter Notebook and create a new cell with the following code:

from web3 import Web3
w3 = Web3(Web3.HTTPProvider(api_url))

print(w3.isConnected())

where api_url is the API URL of the node that you wish to connect you. Services such as https://www.quicknode.com/ and https://www.alchemy.com/ allow you to sign up for a free plan and gain access to a node from which you can use to interact with blockchains like Ethereum.

If all goes well, the following should be printed when you run the cell above:

True

Awesome, you are now able to connect to the blockchain (via a node provider)! But what does the code you just ran actually mean? Inspecting the code on a line-by-line basis:

  • Line 1: we are importing the web3 libary into our Python script

  • Line 2: we are creating a web3 object (w3). By using a web3 object, we are able to call it to perform a wide array of blockchain-related actions

    • As part of its constructor, we can pass in an HTTPProvider (i.e. the API URL). This allows our web3 object to have access to the blockchain.

  • Line 4: we are checking if our web3 object has access to the blockchain

Although the web3 class is useful when interacting with the blockchain, it also provides us with many "offline" functions that make our lives easier. An example of this is the keccak function; while one can compute the hash of a string manually, this would be egregiously tedious. However, the web3 class provides a built-in keccak function that does this for us:

message = "Solidity is Awesome!"
print(w3.keccak(text=message).hex())

If you run the code block above, you will produce the following hash:

0x7afee51dff6870d56cf757e9eb2d8fd31a91153fc307867f43f06990c1b349c6

Querying the Blockchain

For the rest of this section, we will focus on the "online" functionality that the web3 class provides us. To start, we will need to narrow our scope from the web3 object to the web3.eth object; this object provides us with the functionality to read from and write to the Ethereum blockchain. To start. Although there are a countless number of things we can do to interact with the blockchain, perhaps a good starting point is to get the current block number:

print(w3.eth.get_block_number())

At the time of writing this, the following was printed when running the cell above:

17559222

Taking things one step further, what if we want to get information about a block and its contents? Below is the code snippet for how we might want to do that:

block_info = w3.eth.get_block('latest')

# block_info contains a lot of data, so we're just going to print the most relevant data, full details can be found at https://web3py.readthedocs.io/en/v5/web3.eth.html

print(f"block number is {block_info['number']}")
print(f"block difficulty is {block_info['difficulty']}")
print(f"block miner is {block_info['miner']}")
print(f"total number of transactions is {len(block_info['transactions'])}")

At the time of writing this, the following was printed when running the cell above:

block number is 17559240
block difficulty is 0
block miner is 0xDAFEA492D9c6733ae3d56b7Ed1ADB60692c98Bc5
total number of transactions is 110

As another example of how we can leverage the web3.eth object to query the blockchain, the following code demonstrates how we can get the balances of accounts:

# Getting my account balance
my_bal = w3.eth.get_balance("0x7f610402ccc4CC1BEbcE9699819200f5f28ED6e3")
print(f"my balance is {w3.fromWei(my_bal, 'ether')} ether")

# Getting balance of WETH smart contract
contract_bal = w3.eth.get_balance("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
print(f"the WETH contract balance is {w3.fromWei(contract_bal, 'ether')} ether")
my balance is 0.004094900992929802 ether
the WETH contract balance is 3984615.278144831435284183 ether

Resources

Last updated