15
Getting started with some Ethereum concepts and interfacing mainnet with a React App
Let me guess: you read a few articles on blockchains, bitcoin, ethereum or cryptocoins and felt strangely attracted to the wild landscape you’ve pictured in your head. As a curious developer, you then decided to get a bit more technical, skimming through whitepapers, tweets and blog posts to understand how all that crazy stuff works. A few hours later a mild dizziness starts to develop. How the hell all those tokens, off-chain oracles, mainnet, DAOs, smart contracts, high gas prices, The Graph, dApps and cryptoanarchy come together?
Well, welcome to the 🚀 web3.
Take it easy now. Let’s clear some basic concepts to begin with: what fascinates us, developers, about Ethereum is that, unlike bitcoin, this blockchain has a built-in programming language. Not only it has a programming language, it can also work as a database. And it executes your code. Your humble script, made out of variables and functions, once is deployed to “the chain” becomes forever available to the public through thousands of ethereum nodes. Or at least as long as there still exists a single ethereum node running in the world.
This is why people like to call ethereum the ultimate “world computer”. But don’t worry if that’s not clear yet: we will get a better idea if that statement is valid or not when we start making the first calls with the react app we’re about to create.
Any deployed ethereum script is what we will call, from now on, a smart contract.
I think that’s enough for us to move on. We can now start interacting with ethereum. And when I say “interact” what I mean is doing any of the following:
*Calling a smart contract public function;
*reading a smart contract public state variable;
*reading a smart contract’s events logs;
Let’s start coding our app. Start an empty project and name it read-from-ethereum.
yarn create react-app read-from-ethereum
The only additional package we will use for now is ethers.js, a “complete and compact library for interacting with the Ethereum Blockchain and its ecosystem”. Go ahead and install it:
yarn add ethers
And just import it at the top of your ./src/App.js file:
import { ethers } from “ethers”;
The next step is to declare the interface that will help our script connect and make calls to ethereum. For that we will use a provider. We know that ethereum is made up of a network of computers that are running an Ethereum daemon. These computers are called nodes and you have to connect to a node to read and write to ethereum.
A time-consuming but self-sufficient and trustless way of doing that is running a node yourself. You can even do it on that Raspberry Pi 4 you have sitting idle in your drawer. But we shall not make things more complicated. There are many providers out there running ethereum nodes which we can use for free. Let’s use Cloudflare’s ethereum gateway for this exercise: https://cloudflare-eth.com/
Ok. We can declare our provider now passing our chosen gateway to the ethers.providers.JsonRpcProvider method:
const provider = new ethers.providers.JsonRpcProvider('https://cloudflare-eth.com');
That’s all we need to make simple calls to an ethereum node. Now you can check what is the current block number on the chain:
provider.getBlockNumber().then( r => { console.log( r ) } );
Here you go: you are officially connected to ETHEREUM! That’s exciting but at the same time rather useless. We should get more adventurous and start interacting with smart contracts! And that’s quite straightforward. For that we will need two things:
A smart contract address, which is generated once a contract is deployed to ethereum and becomes its permanent reference to be called when we need to interact with it;
the contract’s ABI, which is the mapping of what are the functions and their return types that will help our script understand how to communicate with it.
Now check out this link: Beeple’s NFT Everydays: the first 5000 Days — those are the details of the famous digital artwork NFT that was sold for US$ 69,346,250.00 back in march 2021.
You see that there’s a reference to a smart contract’s address that was used to create that NFT? Let’s get that info and put it on a variable:
const contractAddress = “0x2A46f2fFD99e19a89476E2f62270e0a35bBf0756”;
Okay, we have a contract’s address. Nice. But what does it do? How can we find its list of functions and parametes, its ABI? Well, one way to do this is by searching for that contract’s address at https://etherscan.io/. Once a contract is deployed to ethereum mainnet it will show up here as etherscan tracks every block and transaction on ethereum.
You can explore all the information and analytics tools that etherscan provides later. For now let’s go to the Contract ✅ tab. You will notice that the source code of the contract is open for us to check all its functions and variables, including the ABI. Great.
But not every contract will have its source code exposed here. When you deploy a smart contract to ethereum you are actually sending a compiled binary code to the chain which can be executed by the Ethereum Virtual Machine (EVM) running on the blockchain nodes. And in order to increase transparency and generate more trust, many smart contracts creators decide to verify their contracts by either open sourcing their source code on github or by providing its code to etherscan. Etherscan then compiles the provided source code and checks if it perfectly matches the compiled code deployed on ethereum.
(if the contract is not verified and you can’t find its source code or ABI anywhere, there are decompilers out there that can help revealing a contracts source code with some limitations)
Now go ahead and grab that NFT’s contract ABI from etherscan. It looks like this:
Create a variable called ABI and just paste all that code:
const ABI = [{“constant”:true,”inputs”:[],”name”:”currentStartingDigitalMediaId”,”outputs”:[{“name”:””,”type”:”uint256"}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:true,”inputs”:[{“name”:”_interfaceID”,”type”:”bytes4"}],”name”:”supportsInterface”,”outputs”:[{“name”:””,”type”:”bool”}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_metadataPath”,”type”:”string”}]…
We have everything we need to start interacting with the contract by creating an instance with the contractAddress, the ABI and the provider:
const contract = new ethers.Contract(contractAddress, ABI, provider);
Before we make our first call to this contract I think it would be beneficial if we quickly understand what this contract does. If you try to figure that out by reading the source code it can get a bit tricky. You’ll have better resources to understand it in a few more articles when we get into smart contracts programming and solidity (the programming language we’ll be using).
First of all, what is a NFT? It can be loosely defined as an item inside a kind of hash table in a contract’s storage. That’s a developer definition (If you want a more conceptual one check this).
Go to line 847 of the contract’s source code. The function called _mint is the function responsible for creating (minting) this contract’s NFTs (tokens). The minting function calls addTokenTo function which executes this piece of code:
tokenOwner[_tokenId] = _to;
It gets a _tokenId and maps it to a value _to on the tokenOwner “object” (the definition of tokenOwner is close to a hash table but not exactly one. We’ll get there later but in case you want to check it now: Solidity Mapping types).
Hence, by design, every NFT generated by this contract will have an assigned _tokenId which will be mapped to a _to value which, in this case, the address of the owner of the NFT.
It seems that if we can find the _tokenId of that 69 million dollars NFT we will be able to check who owns it.
It looks like we already have that:
token ID: 40913. That’s the _tokenId we are looking for.
At line 695 of the smart contract source code there’s a function called ownerOf. It’s a public function, which means we can call it from our app. The function asks for the _tokenId parameter, which we already have.
Go ahead and find who is the millionaire who owns this expensive hash table reference:
const NFT = 40913;
contract.ownerOf(NFT).then( r => { console.log( r ) } );
A-ha! Mr. 0x8bB37fb0F0462bB3FC8995cf17721f8e4a399629. Who the hell is that? It’s an ethereum address. The same way a smart contract has an address, someone can also have an account on ethereum which is identified by an address.
That’s a important concept: there are two types of accounts in ethereum. Smart contracts and user-controlled accounts, both identified by its address.
The owner can remain somehow anonymous and don’t have to reveal his identity if he doesn’t want. Let’s check now if he is really rich by finding out how much ether he owns. This is simple:
const address_of_the_owner_of_expensive_nft = "0x8bB37fb0F0462bB3FC8995cf17721f8e4a399629";
provider.getBalance(address_of_the_owner_of_expensive_nft).then( r => { console.log( r ) } );
The result is not easily readable because it’s a BigNumber. That does not mean that he is obscenely rich. The result we get is in wei, not ethers. The same way USD is divisible into 100 parts, having its smallest possible unit called a penny (0.01 USD), ether is divisible into 10**18 parts, and its smallest unit is called a wei.
1,000,000,000,000,000,000 wei = 1 ether
Ether.js has a nice little function to make the conversion for us: ethers.utils.formatEther(). Rewriting the above call to have the ether balance:
provider.getBalance(address_of_the_owner_of_expensive_nft).then( r => { console.log( ethers.utils.formatEther(r) ) } );
He owns 1.4737827687783069 ether. Not much. But hey, the owner of 0x8bB37fb0F0462bB3FC8995cf17721f8e4a399629 can own as many addresses as he wants. He probably have more ether and other cryptocurrencies in different addresses.
Another key aspect of ethereum is that not only user-controlled account can carry ether, but smart contracts themselves can also carry ether. We will see that one can create a smart contract function that requires some ether to run. And that ether can become part of the smart contracts ether balance. That opens up to a lot of interesting applications.
That’s probably enough to get us started. So far ethereum played a similar role to a web2 third-party API that can be called by our front-end app to retrieve some information. That’s just the surface, prepare for a deeper dive.
Two of the best resources out there to help us understand some of the basic concepts of ethereum are these two videos by Ethereum’s co-founders Gabin Wood and Vitalik Buterin.
And if you want to speed up things and get your hands dirty go check Austin Griffith’s Scaffold-eth github repository and all its branches to fast forward you app building with a bunch of application templates / starter kits!
15