2. Connecting to Smart Contract

Smart contracts are the main feature that distinguishes Ethereum from Bitcoin. A smart contract is a program running on the Ethereum network, and it can access the blockchain data.

You write smart contracts in the Solidity programming language. Like Java, Solidity gets compiled to a bytecode that runs in a virtual machine. In this case, it's called the Ethereum Virtual Machine, or EVM for short.

Interacting with Smart Contracts

To interact with a smart contract from JavaScript, you need three things:

  1. The address that points to the smart contract
  2. The full or partial Application Binary Interface of the contract
  3. A provider that is connected to the Ethereum network

In the last lesson, you learned, every EOA and smart contract has an address; this is how you find the contract on the blockchain.

const address = "0x25ed58c027921E14D86380eA2646E3a1B5C55A8b"

To figure out what functions a contract has to offer, you need an Application Binary Interface, or short ABI, a list of function signatures of functions you want to call later. Ethers.js uses the ABI to determine what arguments a function expects and what values it returned when it finished its work.

When using Ethers.js, you can define the ABI as an array of strings, where the strings are Solidity function signatures, just like you would write them in the Solidity programming language.

Here is an example of an ABI for one function:

const abi = [
  "function ownerOf(uint256 tokenId) external view returns (address owner)",
]

Functions get defined with the function keyword followed by a name and then the arguments in paratheses. Solidity is statically typed and doesn't support floating points but integer types of different sizes.

In the example above the function takes one argument of type uint256 and it's named tokenId.

The external keyword is an access modifier that marks the function as callable from outside of the contract.

The view keyword is crucial too because it tells the EVM that the function won't modify any on-chain state; it will just read it. view enables you to call the function without having a wallet because the Ethereum RPC you use can read all data from its local copy of the blockchain.

The returns keyword tells you what you get back when you call the function. In this case, it's the owner's address of a token.

The next step is to create a new contract instance and call the ownerOf function defined by the ABI!

Try it yourself in the editor!

const contractAddress = "0x25ed58c027921E14D86380eA2646E3a1B5C55A8b" const contractAbi = [ "function ownerOf(uint256 tokenId) external view returns (address owner)" ] const provider = ethers.getDefaultProvider() // Write your code here!

const smartContract = new ethers.Contract( contractAddress, contractAbi, provider, ) const owner = await smartContract.ownerOf(2) print(owner)

The owner of the contract, like everything on the blockchain, is located at an address, and this is just what the function returned. The address could point to another contract that created our contract, as so called factory contract. The address could also point to an EOA, which is the case in this example.

Conclusion

This lesson taught you about smart contract interaction. How to find them on the blockchain with the help of a provider and an address and how to call its functions with an ABI.

An ABI is just an array of strings, these strings are function signatures like you would write them in Solidity, the programming language powering Ethereum.

If you found these addresses a bit cumbersome to work with, I have good news for you. The next lesson is about the blockchain equivalent of DNS: The Etherum Name Service.