Question: What are events in smart contracts? How can they be used to enable application-level listening and feedback?

Summary: Events in smart contracts are lightweight log entries used to record important state changes. They enable off-chain apps to subscribe, listen, and react in real time without polling the chain. This post explains events, shows Solidity and JavaScript examples, and lists practical use cases.


What are Events?

Events in smart contracts are a special type of log entry that record important state changes or information during contract execution. They are designed to be lightweight and cost-efficient, because event data is stored in the transaction receipt (logs) rather than contract storage.

  • Lightweight: cheaper than writing to contract storage.
  • Queryable: up to three parameters can be indexed, enabling fast filtering.
  • Write-only for contracts: contracts can emit events, but they cannot read historical events—events are intended for off-chain consumers.

How to Use Events

1. Define an Event

Define events in Solidity with the event keyword. Use indexed to make parameters searchable.

event Transfer(address indexed from, address indexed to, uint256 value);

2. Emit the Event

Use the emit keyword inside contract functions when conditions are met.

function transfer(address _to, uint256 _value) public returns (bool) {
    require(balanceOf[msg.sender] >= _value, "Insufficient balance");
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
    return true;
}

3. Listen to Events (Off-chain)

Frontends and backends can subscribe to events using libraries such as web3.js or ethers.js.

Web3.js example:

const myContract = new web3.eth.Contract(abi, contractAddress);

myContract.events.Transfer({ fromBlock: "latest" })
.on("data", (event) => {
    console.log("Transfer detected:", event.returnValues);
})
.on("changed", (event) => {
    // event removed from local DB (reorg)
})
.on("error", console.error);

Ethers.js v6 example:

contract.on("Transfer", (from, to, value, event) => {
    console.log(`Transfer: ${value} tokens from ${from} to ${to}`);
});

Real-world Use Cases

  • Wallet Notifications: Notify users on token receipt or outgoing transfers.
  • DApp UI Updates: Refresh balances, staking statuses, or swap results in real time.
  • Backend Processing: Store emitted events in a database for analytics, auditing, or compliance workflows.
  • Off-chain Automation: Trigger off-chain jobs (indexers, relayers, monitoring tools) on event emission.

Notes & Best Practices

  • Use indexed for fields you need to filter by (up to 3 indexed params).
  • Keep event payloads concise—logs are cheaper than storage, but still cost gas.
  • Design your event schema to balance queryability (indexed) and detail (non-indexed).
  • Remember: contracts cannot read past events; always rely on state variables for logic.
  • Handle chain reorganizations (reorgs) in listeners: wait for confirmations or re-check state.

Conclusion

Events are the bridge between on-chain logic and off-chain applications. They provide a cost-effective and transparent mechanism to expose contract execution results. By subscribing to events rather than polling the chain, applications achieve real-time responsiveness and better UX.

Subscribe for New Articles!

Leave a Comment

Your email address will not be published. Required fields are marked *