Blockchain stores transactions in blocks. Every transaction has logs, representing Solidity events that have occurred. This tutorial discusses the concept of an event in Solidity and aims to explain the way events are handled in the blockchain.
The tutorial also reviews event filtering by going over the logs in the blockchain. The event data (in the form of transaction logs) remains in the database as long as the block is accessible. However, there are certain limitations for accessing event data.
Contents
Solidity Events: Main Tips
- There are two types of Solidity event parameters:
indexed
and not indexed. - Blockchain keeps event parameters in transaction logs.
- Parameters can be placed in two parts of logs: data and topics.
- You can filter events by name and by contract address.
Events and Contracts
Solidity defines events with the event
keyword. After events are called, their arguments are placed in blockchain.
Note: logs are related to the contract address. They stay in the blockchain as long as blocks are accessible.
pragma solidity >=0.4.21 <0.7.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
Solidity events are interfaces with EVM logging functionality. You can add an attribute indexed
to up to three parameters. Then, they appear in the structure of topics, not the data portion of the log.
Note: when parameters do not have the indexed attribute, they are ABI-encoded into the data portion of the log.
You can ask for a simple payment verification (SPV) for logs. If an outside source provides a contract with this type of verification, you can confirm whether the log is in the blockchain.
Event Filtering
The topics portion of the log lets you search for Solidity events. You can detect specific events from a sequence of blocks.
Note: it is possible to filter events by the address of a contract that removed the event.
The example below applies the subscribe('logs')
(web3.js) for filtering logs that fit a topic with a specific address:
var options = {
fromBlock: 0,
address: web3.eth.defaultAccount,
topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null]
};
web3.eth.subscribe('logs', options, function (error, result) {
if (!error)
console.log(result);
})
.on("data", function (log) {
console.log(log);
})
.on("changed", function (log) {
});
Anonymous Solidity events are less expensive to use. However, you can’t filter them by name, only by their contract address:
pragma solidity >=0.4.21 <0.7.0;
contract ClientReceipt {
event Deposit(
address indexed _from,
bytes32 indexed _id,
uint _value
);
function deposit(bytes32 _id) public payable {
// Events are emitted using `emit`, followed by
// the name of the event and the arguments
// (if any) in parentheses. Any such invocation
// (even deeply nested) can be detected from
// the JavaScript API by filtering for `Deposit`.
emit Deposit(msg.sender, _id, msg.value);
}
}
Low-Level Interface to Logs
The functions log0
, log1
, log2
, log3
and log4
give access to the low-level interface of the logging mechanism. logi
accepts i + 1
parameter of bytes32
type.
- The first parameter applies to the data portion of the log.
- The second parameter applies to the topics portion.
The following code snippet shows how to make an event call:
pragma solidity >=0.4.10 <0.7.0;
contract C {
function f() public payable {
uint256 _id = 0x420042;
log3(
bytes32(msg.value),
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
bytes32(uint256(msg.sender)),
bytes32(_id)
);
}
}
Solidity Events: Summary
- Event parameters can be
indexed
and not indexed. - Transaction logs that contain event parameters are in the blockchain.
- Logs have two portions for keeping parameters: data and topics.
- Event filtering can be done according to names and contract addresses.