Interacting with smart contracts
You don't always need to write and deploy your own smart contract. Most of the time as a developer, you'll want to interact with smart contracts that others have already deployed to the Ethereum network.
This page covers the two fundamental ways to interact with a smart contract—reading data and writing data—and the tools you need to do both.
Prerequisites
You should understand:
Two ways to interact with a smart contract
Interacting with a smart contract falls into two categories:
Reading from a contract
Reading is a free operation that does not create a transaction and does not change any state on the blockchain.
When you read from a contract, you're simply querying data that already exists. For example:
- Checking an ERC-20 token balance
- Reading the current price from a decentralized exchange
- Getting the owner of an NFT
Because reads don't modify state, they don't cost gas and can be performed by anyone without needing ETH.
Writing to a contract
Writing is a state-changing operation that requires a transaction and costs gas.
When you write to a contract, you're triggering a function that modifies the blockchain state. For example:
- Transferring tokens
- Swapping tokens on a decentralized exchange
- Minting an NFT
Writing always requires:
- An Externally Owned Account (EOA) with enough ETH for gas
- A transaction signed by the account's private key
- The transaction to be mined and included in a block
With account abstraction, a smart contract account can also initiate writes, and a paymaster can cover gas on the user's behalf—so an EOA holding ETH is not strictly required.
Understanding contract ABIs
To interact with a smart contract, your application needs to know what the contract can do. This is where the Application Binary Interface (ABI) comes in.
An ABI is a JSON document that describes:
- Every function the contract exposes (name, inputs, outputs)
- Every event the contract can emit
- How to encode and decode data when talking to the contract
Think of the ABI as the contract's instruction manual—without it, your application doesn't know which functions exist or what parameters they expect.
Where to find a contract's ABI
- Verified contracts on Etherscan - Etherscan (opens in a new tab) automatically exposes the ABI for verified source code
- From the developer - many projects publish their ABIs in their documentation or npm packages
- Generate from source - if you have the Solidity source code, you can compile it to produce the ABI
Tools and libraries for interacting with contracts
Developers typically use a JavaScript/TypeScript library to interact with contracts from a web app, backend, or script.
Client libraries (JavaScript/TypeScript)
- Viem (opens in a new tab) - Modern, lightweight TypeScript interface for Ethereum with first-class type safety
- ethers.js (opens in a new tab) - Battle-tested library for interacting with the Ethereum blockchain
- web3.js (opens in a new tab) - The original Ethereum JavaScript API
Backend libraries
- ethers.js (opens in a new tab) - Also works in Node.js for server-side scripts and bots
- web3.py (opens in a new tab) - Python library for Ethereum interaction
- go-ethereum (opens in a new tab) - Official Go library from the Geth team
Example: reading a token balance with Viem
import { createPublicClient, http, formatUnits } from 'viem'
import { mainnet } from 'viem/chains'
// USDC contract address and ABI (partial, for balanceOf)
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
const abi = [{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }],
}] as const
const client = createPublicClient({ chain: mainnet, transport: http() })
const balance = await client.readContract({
address: USDC,
abi,
functionName: 'balanceOf',
args: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'], // vitalik.eth
})
console.log(formatUnits(balance, 6)) // USDC has 6 decimals
Example: sending a transaction with ethers.js
const { ethers } = require('ethers')
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
// ERC-20 transfer ABI
const abi = ['function transfer(address to, uint256 amount) returns (bool)']
const contract = new ethers.Contract(tokenAddress, abi, wallet)
const tx = await contract.transfer(recipient, ethers.parseUnits('10', 18))
await tx.wait() // wait for the transaction to be mined
console.log(`Transferred! TX: ${tx.hash}`)
Events and logs
Smart contracts can emit events to signal that something happened. Your application can listen for these events to react in real time.
import { createPublicClient, http, parseAbiItem } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({ chain: mainnet, transport: http() })
// Watch for USDC Transfer events
const unwatch = client.watchEvent({
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: (logs) => console.log(logs),
})
Simulating transactions
Before sending a transaction, you can simulate it to check if it would succeed—and to see its return value—without spending gas. This is useful for catching errors early and for previewing outcomes.
Most client libraries support this through eth_call:
// With Viem
const result = await client.simulateContract({
address: contractAddress,
abi,
functionName: 'swap',
args: [amountIn],
account: userAddress,
})
Wallets and signing
In a dapp, the user's wallet (like MetaMask, Rainbow, or WalletConnect) handles signing. You don't manage private keys directly.
Wallet libraries and connection tools abstract this so you can focus on building your application logic.
Related tutorials
- Calling a smart contract from JavaScript
- Sending transactions using web3.js and Alchemy
- How to view your NFT in your wallet
Further reading
- Viem documentation: Reading and writing to contracts (opens in a new tab)
- ethers.js documentation: Contracts (opens in a new tab)
- Solidity ABI specification (opens in a new tab)
- What is an ABI? - Alchemy (opens in a new tab)