Solidity Events: Everything You Need to Know

Introduction

Hello, Web3 folks! If you’ve worked with Solidity before, you know that it’s a powerful language for building decentralised applications on the Ethereum blockchain. But have you ever thought about how smart contracts can talk to things outside of the blockchain? This is where Solidity events come in!

Solidity events are an important part of making smart contracts because they let contracts send out messages when certain conditions are met. Events can be thought of as a way for smart contracts to “talk” to other applications, telling them about the state of the contract or making them do something when certain events happen.

We’ll learn a lot about Solidity events in this article. We’ll talk about everything you need to know about defining and sending events in Solidity. We’ll also show you how to use Web3.js to listen for events. By the end of this guide, you’ll have a good idea of how events work in Solidity and why they’re such an important part of building powerful decentralised applications. So let’s get started!

Defining Events in Solidity

In Solidity, we use the keyword “event” followed by the name of the event and a list of parameters to define an event. Here’s what a definition of an event might look like:

event NewTransaction(

  address indexed from,

  address indexed to,

  uint256 amount

);

In this example, we’ve set up an event called NewTransaction that takes three parameters: from, to, and amount. The from and to parameters have also been marked as indexed.

Indexed parameters are unique because they let us filter event logs in the future. When an event has a “indexed parameter,” the value of that parameter is stored in the blockchain in a separate data structure called a “index.” This lets us find and get events quickly based on the values of their indexed parameters.

It’s important to keep in mind that not all kinds of data can be marked as indexed. At the moment, only certain types of data, like address, bytes32, bool, and uint256, are supported. If you try to mark as indexed a parameter that is not of the same type, the compiler will give you an error.

When implementing events in Solidity, it’s also important to think about how much gas they will cost. It can be costly to send out events, especially if they contain a lot of data or have a lot of indexed parameters. As a best practise, it’s best to keep the number of parameters to a minimum and only include data that is needed for other applications to interact with your contract.

In the next section, we’ll explore how to emit events in Solidity.

Emitting Events in Solidity

To emit an event in Solidity, we use the emit keyword followed by the name of the event and the values we want to pass for each parameter. Here’s an example of how we might emit the NewTransaction event we defined in the previous section:

function transfer(address to, uint256 amount) public {

  // Transfer logic goes here...

  emit NewTransaction(msg.sender, to, amount);

}

In this example, we’ve made a transfer function that takes two parameters: an address and an uint256. When this function is called, a NewTransaction event is emitted with the parameters msg.sender, to, and amount.

One thing to remember when emitting events in Solidity is that the amount of gas needed to send an event depends on how many indexed parameters it has and how much data it contains. As a best practise, it’s smart to keep the amount of data in events to a minimum and to avoid putting in sensitive information that could make your contract less safe.

You can also send events from other Solidity structures, like fallback functions and constructors, in addition to sending them directly from functions. But in these situations, it’s important to be aware of the gas costs that come with emitting events and to make sure that your contract is optimised to keep these costs as low as possible.

In the next section, we’ll look at how to use Web3.js to listen for Solidity events.

Listening to Solidity Events with Web3.js

Now that we know how to define and send events with Solidity, let’s look at how to use Web3.js to listen for these events.

We use the contract.events method followed by the name of the event we want to listen for in Web3.js. Here’s one way we could listen for the NewTransaction event we talked about earlier:

import Web3 from 'web3';
const web3 = new Web3('YOUR_RPC_ENDPOINT_HERE');
const ABI = 'YOUR ABI OF SMART CONTRACT WHICH EMITS REQUIRED EVENT';
const CONTRACT_ADDRESS = 'YOUR CONTRACT ADDRESS HERE';

const myContract = new Web3.Contract(ABI, CONTRACT_ADDRESS);

let options = {
    filter: {
        from: accounts[0] ,
    },
    fromBlock: 0
};

myContract.events.NewTransaction(options)
    .on('data', event => console.log(event))
    .on('changed', changed => console.log(changed))
    .on('error', err => throw err)
    .on('connected', str => console.log(str))

In this example, we are listening for the NewTransaction event by using the contract.events method. We’ve also set a filter to only listen for events where the from address matches accounts[0], and we’ve set the fromBlock parameter to 0 to start listening for events from the genesis block.

When an event is emitted that matches our filter criteria, the on(‘data’) callback function will be called with an event object that has information about the event. In this example, we use the event.returnValues object to get the values of the from, to, and amount parameters and log a message to the console.

It’s important to know that listening for events in Web3.js can use a lot of resources, especially if you do it for a long time and listen for a lot of events. As a best practise, it’s a good idea to limit the number of events you’re listening for and use filters to reduce the amount of data you need to process.

Solidity Event Logs

When an event happens in Solidity, the data is stored in the blockchain as an event log. Event logs are kept in a different data structure than transactions, and they are made so that they can be searched and filtered quickly.

Using the Web3.js library, you can access the event logs by calling the getPastEvents method on a contract instance. Here’s an example of how we could use getPastEvents to get all of our contract’s NewTransaction events:

let options = {
    filter: {
        value: ['1000', '1337']    //Only get events where transfer value was 1000 or 1337
        from: accounts[0] 
    },
    fromBlock: 0,                  // Number || "earliest" || "pending" || "latest"
    toBlock: 'latest'
};

myContract.getPastEvents('NewTransaction', options)
    .then(results => console.log(results))
    .catch(err => throw err);

In this example, we use the getPastEvents method to get all of the NewTransaction events sent by our contract where the from address matches accounts[0]. We’ve set the fromBlock parameter to 0 to start searching from the genesis block and the toBlock parameter to latest to search up to the most recent block.

When the getPastEvents method finishes, it will give back an array of event objects that have information about each event that matches. Here’s an example of what an event object could look like:

{
  event: 'NewTransaction',
  address: '0x1234567890123456789012345678901234567890',
  returnValues: {
    from: '0x456789012345678901234567890123456789012',
    to: '0x7890123456789012345678901234567890123456',
    amount: '100'
  },
  blockNumber: 12345,
  transactionHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
  transactionIndex: 0,
  logIndex: 0,
  blockHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
}

In addition to the event and returnValues properties, the event object also has information about the block and transaction in which the event was sent, as well as the index of the event log within the block.

By looking at Solidity event logs, you can learn a lot about the state of your contracts and how other blockchain users behave. You can also use event logs to make powerful analytics tools that can help you understand how your contracts are being used and find places to improve.

Best Practices for Working with Solidity Events

When working with Solidity events, there are a few best practises to keep in mind to make sure your contracts are safe and optimised for performance. Here are some things to consider:

1. Use events sparingly

Even though events can be a powerful way to interact with other systems, they can also use a lot of resources and have a big effect on how well a contract works. As a best practice, it’s best to use events only when they’re needed.

2. Minimize the amount of data included in events

As I’ve already said, the amount of data in an event can change how much gas it costs to emit it. To get the most out of your contract’s gas usage, it’s a good idea to keep the amount of data in events to a minimum and not include sensitive information that could put your contract’s security at risk.

3. Use indexed parameters for efficient filtering

When defining events, you can mark certain parameters as “indexed” to make it easier to filter and search for events. Indexed parameters are stored separately from regular parameters, and when Web3.js is listening for events, you can use the filter option to find what you’re looking for.

4. Ensure that events are properly emitted

When emitting events in Solidity, it’s important to ensure that all required parameters are included and that the data is formatted correctly. Failing to properly emit events can result in unexpected behavior and can make it difficult to debug your contract.

5. Test your events thoroughly

As with any other part of your contract, you should test your events carefully to make sure they work the way you want them to. This means testing both how your events send and receive data and making sure that the data being sent is correct and consistent.

Conclusion

Solidity events are a key part of building decentralised applications on the Ethereum blockchain. They make it possible for contracts to talk to other systems and give powerful tools for keeping track of and analysing contract activity.

In this article, we’ve talked about the basics of Solidity events, like how to declare and emit them, and how to use event logs to find out what’s going on with a contract. We’ve also talked about the best ways to work with Solidity events, such as using names that make sense, avoiding sensitive information in event data, and making the best use of event gas.

This guide was more or less practical and will get you started quickly. I recommend going through Solidity official docs for Events for in-depth understanding. I will try to write one more article.

I appreciate you reading this article and hope it was helpful. If you have any questions or comments, don’t be afraid to reach out to me on my social handles.

%d bloggers like this: