Solidity events are used to inform the outside world about the current state of a smart contract. The smart contract address is the link to the logs and the blockchain includes the logs. Logs are part of the transaction receipts.
Events in solidity are more powerful than you think and it has very important use cases that we will discuss in this post.
How to declare an event in Solidity?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CodiesAlert {
string public name = "Anni";
uint public age = 29;
string public city = "New York";
event logName (string indexed name, uint indexed age, string indexed city);
function stateChanged(string memory _name, uint _age, string memory _city) public {
name = _name;
age = _age;
city = _city;
emit logName(name, age, city);
}
}
You can declare an event in solidity smart contract with the event keyword followed by the event name and the parameters. You can think of events like a function and they are declared the same way. You might have noticed the keyword indexed in the event parameter, If you index events they are easier and faster to find in the transaction log. You can also query data, let’s say you want to retrieve all the events log where the name is “Codies Alert“, it is doable because of the index keyword.
You can have as many parameters in an event but you can declare up to 3 Indexed type parameters and the rest of the parameters will be of non-index type. To access non-index parameters you will require the contract ABI to decode them.
For e.g., Whenever the function stateChanged is called it will write the event data in the transaction log and you can set up the event listener in Javascript or python and set up some actions based on the emitted event. emit keyword will write the event information in the transaction log.
Note: Events cannot be accessed by a smart contract so use events to store data that you don’t need in the smart contracts.
Avoid Storing Reference Type in Events
Indexed event parameters that are not value types, i.e. arrays and structs are not stored directly but instead, a keccak256-hash of encoding is stored. This encoding is defined as follows:
- the encoding of a
bytes
andstring
value is just the string contents without any padding or length prefix.- the encoding of a struct is the concatenation of the encoding of its members, always padded to a multiple of 32 bytes (even
bytes
andstring
).- the encoding of an array (both dynamically- and statically-sized) is the concatenation of the encoding of its elements, always padded to a multiple of 32 bytes (even
bytes
andstring
) and without any length prefixAs an alternative if you want to retrieve its value you should not use the indexed type, or have two parameters one indexed and the other without it.
What Can you do with events?
- Return function values from a smart contract. For e.g. You have a Loan Smart contract that creates a unique loan Id whenever a new loan is applied. You can listen to these events and show them on Frontend instead of reading the data from storage.
- Events are much cheaper to use. Events take 625 gas to store 32 bytes whereas storage takes 23000 gas to store 32 bytes.
Conclusion
You should consider storing data when you don’t want to use it in the smart contract. Events are cheap to store and easy to filter when indexed. Avoid using reference types(Array, String, bytes) because these are not stored directly instead , a keccak256-hash of encoding is stored which is not useful if you want to show the data on the frontend. keccak256 is a one-way hashing function which means you cannot get the original value back from its hash.
The best way to understand events is, for e.g. you have a crypto exchange and every time user withdraws and deposits funds it will emit an event. You don’t need to store that history in storage variable so events are helpful to keep track of all the deposits and withdrawals and show it on the front-end.