Reading Contract Data
Query smart contracts with Ethers.js
Learn how to read data from smart contracts on RISE using Ethers.js.
Setup
Create a provider and contract instance:
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider('https://testnet.riselabs.xyz');
const contractAddress = '0x...';
const abi = [ /* contract ABI */ ];
const contract = new ethers.Contract(contractAddress, abi, provider);Read Contract Data
Call view/pure functions:
// Simple read
const value = await contract.getValue();
console.log('Value:', value.toString());
// Read with arguments
const balance = await contract.balanceOf('0x...');
console.log('Balance:', ethers.formatEther(balance));ERC-20 Token Example
Read ERC-20 token information:
const tokenAddress = '0x...';
const abi = [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
'function totalSupply() view returns (uint256)',
'function balanceOf(address) view returns (uint256)'
];
const token = new ethers.Contract(tokenAddress, abi, provider);
// Get token info
const name = await token.name();
const symbol = await token.symbol();
const decimals = await token.decimals();
const totalSupply = await token.totalSupply();
console.log('Token:', name);
console.log('Symbol:', symbol);
console.log('Decimals:', decimals);
console.log('Total Supply:', ethers.formatUnits(totalSupply, decimals));
// Check balance
const userAddress = '0x...';
const balance = await token.balanceOf(userAddress);
console.log('Balance:', ethers.formatUnits(balance, decimals), symbol);Get Contract Events
Query past events:
// Get Transfer events
const filter = contract.filters.Transfer();
const events = await contract.queryFilter(filter, 0, 'latest');
console.log('Transfer events:', events.length);
events.forEach(event => {
console.log({
from: event.args.from,
to: event.args.to,
value: ethers.formatEther(event.args.value),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash
});
});Filter Events by Parameters
// Get transfers TO a specific address
const toFilter = contract.filters.Transfer(null, '0x...');
const toEvents = await contract.queryFilter(toFilter);
// Get transfers FROM a specific address
const fromFilter = contract.filters.Transfer('0x...', null);
const fromEvents = await contract.queryFilter(fromFilter);
// Get specific block range
const recentEvents = await contract.queryFilter(
contract.filters.Transfer(),
-1000, // 1000 blocks ago
'latest'
);Listen to Events
Subscribe to realtime events:
// Listen to Transfer events
contract.on('Transfer', (from, to, value, event) => {
console.log('Transfer detected:');
console.log('From:', from);
console.log('To:', to);
console.log('Value:', ethers.formatEther(value));
console.log('Block:', event.log.blockNumber);
});
// Listen once
contract.once('Transfer', (from, to, value) => {
console.log('First transfer:', ethers.formatEther(value));
});
// Stop listening
contract.removeAllListeners('Transfer');Get Block Data
// Get latest block
const blockNumber = await provider.getBlockNumber();
console.log('Latest block:', blockNumber);
// Get block details
const block = await provider.getBlock(blockNumber);
console.log('Block:', {
number: block.number,
hash: block.hash,
timestamp: block.timestamp,
transactions: block.transactions.length,
gasUsed: block.gasUsed.toString()
});
// Get block with full transactions
const blockWithTxs = await provider.getBlock(blockNumber, true);
console.log('Transactions:', blockWithTxs.prefetchedTransactions);Get Transaction Data
const txHash = '0x...';
// Get transaction
const tx = await provider.getTransaction(txHash);
console.log('Transaction:', {
from: tx.from,
to: tx.to,
value: ethers.formatEther(tx.value),
gasLimit: tx.gasLimit.toString(),
gasPrice: ethers.formatUnits(tx.gasPrice, 'gwei') + ' Gwei',
nonce: tx.nonce
});
// Get transaction receipt
const receipt = await provider.getTransactionReceipt(txHash);
console.log('Receipt:', {
status: receipt.status, // 1 = success, 0 = failed
blockNumber: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString(),
contractAddress: receipt.contractAddress, // if contract deployment
logs: receipt.logs.length
});Parse Transaction Logs
Decode logs from a transaction:
const receipt = await provider.getTransactionReceipt(txHash);
// Parse logs with contract interface
const iface = new ethers.Interface(abi);
receipt.logs.forEach(log => {
try {
const parsedLog = iface.parseLog(log);
console.log('Event:', parsedLog.name);
console.log('Args:', parsedLog.args);
} catch (e) {
// Log doesn't match ABI
}
});Estimate Gas
Estimate gas for a function call:
const gasEstimate = await contract.transfer.estimateGas('0x...', ethers.parseEther('1'));
console.log('Estimated gas:', gasEstimate.toString());
// With specific transaction parameters
const gasWithParams = await contract.transfer.estimateGas(
'0x...',
ethers.parseEther('1'),
{
from: wallet.address
}
);Static Call (Simulate)
Simulate a transaction without sending it:
// Will revert if the transaction would fail
const result = await contract.transfer.staticCall('0x...', ethers.parseEther('1'));
console.log('Simulation result:', result);
// Useful for functions that return values
const mintResult = await contract.mint.staticCall(1000);
console.log('Would mint:', mintResult.toString(), 'tokens');Call with Overrides
Override transaction parameters for a call:
const balance = await contract.balanceOf('0x...', {
blockTag: 1000000 // Query at specific block
});
const historicalBalance = await contract.balanceOf('0x...', {
blockTag: 'earliest' // Or 'latest', 'pending'
});Example: Complete Token Info
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider('https://testnet.riselabs.xyz');
const tokenAddress = '0x8a93d247134d91e0de6f96547cb0204e5be8e5d8'; // USDC
const abi = [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
'function totalSupply() view returns (uint256)',
'function balanceOf(address) view returns (uint256)',
'event Transfer(address indexed from, address indexed to, uint256 value)'
];
const token = new ethers.Contract(tokenAddress, abi, provider);
async function getTokenInfo() {
// Get basic info
const [name, symbol, decimals, totalSupply] = await Promise.all([
token.name(),
token.symbol(),
token.decimals(),
token.totalSupply()
]);
console.log('Token Information:');
console.log('Name:', name);
console.log('Symbol:', symbol);
console.log('Decimals:', decimals);
console.log('Total Supply:', ethers.formatUnits(totalSupply, decimals));
// Get recent transfers
const transferFilter = token.filters.Transfer();
const recentTransfers = await token.queryFilter(transferFilter, -1000, 'latest');
console.log('\nRecent Transfers:', recentTransfers.length);
// Show last 5 transfers
recentTransfers.slice(-5).forEach(event => {
console.log({
from: event.args.from,
to: event.args.to,
value: ethers.formatUnits(event.args.value, decimals),
block: event.blockNumber
});
});
}
getTokenInfo().catch(console.error);Next Steps
- Writing to Contracts - Send transactions and modify state
- Contract Addresses - Find deployed contract addresses
- Testnet Tokens - Get testnet tokens for testing