Skip to main content
Create your own

Logging On-Chain Activities with Events

Hello! In our last session, we dug into Solidity's primary data structures, establishing that mappings are the EVM's equivalent of an indexed key-value store, perfect for efficient lookups. We concluded by noting that while mappings are great for managing state within the contract, we need a way to communicate important state changes to the world outside the contract.

This lesson directly addresses that need. We'll explore Solidity events, the blockchain's mechanism for logging. For someone with your background in ETL and business intelligence, this concept should be quite intuitive. Think of events as the "Extract" step for on-chain data; they create structured, cost-effective logs that off-chain applications—from front-end UIs to complex data indexing platforms like The Graph—can consume. This is the fundamental bridge between on-chain logic and off-chain analytics and interaction.

By the end of this lesson, you will be able to define custom events in your smart contracts and emit them to create an auditable, on-chain log of your contract's activities.

1. What Are Events and Why Are They Essential?

A smart contract's state is stored on the blockchain, but reading that state directly can be cumbersome or impossible for certain historical queries. For example, how would you get a list of every time a favoriteNumber was changed in a contract over the past year? You would have to re-execute every single transaction that ever interacted with the contract, which is incredibly inefficient.

Events solve this problem. They are a specialized logging facility built into the EVM. When a contract emits an event, it writes a log to a special, separate data structure on the blockchain. These logs are not accessible by other smart contracts but are easily queryable by external clients (like a JavaScript application or an indexing service). This makes them much cheaper than writing to storage.

The Chainlink video below provides an excellent overview of what events are and why they are so critical for the blockchain ecosystem, including for off-chain services you're interested in, like Chainlink oracles and The Graph.

Events and Logging in Solidity

This video introduces the core concepts of events and logging in Solidity, explaining their purpose and gas efficiency.

Please watch the introductory segment from the beginning. Pay close attention to the explanation of why events are cheaper than storage variables and how they enable off-chain infrastructure to listen for on-chain activity.

As the video explains, events are the backbone of a responsive decentralized application. They allow a front-end to update when a transaction is complete, and they enable services like Chainlink to respond to data requests. For your goal of building tokenized money applications, events are non-negotiable. Every token transfer, every mint or burn, and every change in administrative rights must emit an event to create a transparent and auditable trail.

2. Defining and Emitting an Event

The syntax for using events involves two keywords: event to declare an event's structure, and emit to fire it.

  1. Declaration (event): You first define an event, giving it a name and specifying the parameters it will log. This looks similar to a function declaration.
    // Declares an event that logs a new value and the address that set it.
    event ValueChanged(uint256 newValue, address indexed updatedBy);
    
  2. Emission (emit): Inside a function that makes a state change, you use the emit keyword followed by the event's name and the arguments you want to log.
    function updateValue(uint256 _newValue) public {
        // ... some logic ...
        myValue = _newValue;
        emit ValueChanged(myValue, msg.sender);
    }
    

The RareSkills article on Solidity Events provides a concise look at this basic syntax.

Solidity Events | By RareSkills

This article offers a clear, no-frills introduction to the fundamental syntax for defining and emitting an event.

Read the short introductory section, the example, to see the event and emit keywords in action within a simple contract.

3. Indexed vs. Non-Indexed Parameters: The Key to Searchability

You'll notice the indexed keyword in the ValueChanged event example above. This is perhaps the most important concept for you to grasp, given your data background.

Think of a database table. If you want to efficiently query rows based on a specific column's value, you create an index on that column. Without an index, the database must perform a full table scan.

Solidity events work exactly the same way.

  • Indexed Parameters (Topics): These are like indexed columns. You can have up to three indexed parameters in an event. The EVM stores these separately, allowing off-chain clients to quickly filter for events where these parameters match a specific value (e.g., "find all Transfer events where the to address is 0x123...").
  • Non-Indexed Parameters (Data): These parameters are ABI-encoded together into a single data blob. They are cheaper in terms of gas but are not searchable. A client must retrieve all events and then decode this data blob to see their values.

This distinction is crucial for designing efficient and practical contracts. You should index parameters that you expect clients will use as filters. Addresses (from, to, owner) are almost always indexed. Large values like token amounts are typically not.

The Chainlink blog provides a fantastic visualization of how this appears on a block explorer like Etherscan.

An event log as seen on Etherscan. The 'Topics' section contains the event signature and the indexed parameters (`oldNumber`, `newNumber`), which are searchable. The 'Data' section contains the non-indexed parameters (`addedNumber`, `sender`), which are not directly searchable but are decoded for readability.

As you can see, the indexed parameters are broken out into separate, queryable Topics. The non-indexed parameters are bundled into the Data field. This structure is a direct result of using the indexed keyword in your Solidity code.

For a deeper dive into this mechanism, the following article provides a clear explanation.

Solidity Events | By RareSkills

This section of the RareSkills article clearly explains the purpose and implication of using the indexed keyword.

Read the section titled indexed vs non-indexed events. It explains precisely why you can filter by some event parameters and not others, and introduces the term topic for indexed arguments.

4. A Practical Walkthrough with Hardhat

Now, let's put this all together in a practical, hands-on exercise. The following video from the Chainlink channel walks you through the entire process within a Hardhat project, just like the one you have set up. You will build a simple SimpleStorage contract, add an event, emit it, and then inspect the results.

Events and Logging in Solidity

This video provides a complete, step-by-step guide to defining, emitting, and inspecting events using Solidity and Hardhat.

Follow along with the presenter as he builds and interacts with the contract. Define and Emit: Watch how the storedNumber event is first defined with a mix of indexed and non-indexed parameters, and then emitted within the store function. Create the Contract: Follow the creation of the SimpleStorage.sol contract in Hardhat, where the event is implemented. Accessing Events in a Script: This is a key part. Observe how the script waits for the transaction receipt and then accesses the emitted event's arguments via transactionReceipt.events. This is a pattern you will use extensively in testing. Viewing on Etherscan: The presenter deploys to a testnet and verifies the contract. Watch how the logs appear on Etherscan, reinforcing the difference between Topics (indexed) and Data (non-indexed).

This walkthrough gives you a complete picture, from code to deployment to inspection. Being able to access event arguments from the transaction receipt is a fundamental skill for writing robust tests, which is the entire subject of our next module.

5. Gas Costs & Best Practices

Finally, a brief word on costs and conventions. Events are cheap, but not free. The gas cost is primarily driven by the number of indexed parameters.

  • Base Cost: A fixed cost for the log operation itself.
  • Topic Cost: A cost for each indexed parameter.
  • Data Cost: A smaller cost per byte for the non-indexed data.

The RareSkills article provides the exact formula and a key takeaway.

Solidity Events | By RareSkills

This resource concludes with best practices and an analysis of the gas costs associated with emitting events.

Read the sections Solidity events best practices and Gas cost to emit Solidity event. The main takeaway is to be deliberate about what you index to balance searchability with gas cost.

In summary, the best practice is to:

  • Emit events for all significant state changes (e.g., transfers, ownership changes, parameter updates).
  • Index the parameters that off-chain clients will need for filtering (usually addresses or IDs).
  • Avoid indexing large or continuously variable data like amounts unless absolutely necessary.

Conclusion

In this lesson, we demystified Solidity events and established their role as the primary communication channel from the blockchain to the outside world. This mechanism is fundamental to creating transparent, auditable, and interactive decentralized applications.

Here are your key takeaways:

  • Events are for Off-Chain Consumption: They create logs that are cheap to write but cannot be read by other smart contracts. Their purpose is to signal state changes to UIs, scripts, and indexing services.
  • indexed is for Searchability: Indexed parameters become "topics" that act like database indexes, enabling efficient filtering of event logs.
  • Events Provide an Audit Trail: For tokenized money applications, emitting events for every transfer, mint, and burn operation is critical for transparency and compliance.
  • Testing Involves Events: Verifying that the correct events are emitted with the correct data is a cornerstone of smart contract testing.

You are now equipped to make your contracts "talk" to the outside world. In our next module, Smart Contract Testing with Hardhat, we will immediately put this skill to use. You'll learn how to write automated tests that execute a transaction and then assert that the expected event was emitted with the correct values, ensuring your contract behaves exactly as designed.

Can't find a good explanation? Sign up and we'll make it for you

Sign up