testnet
GitHub

Implementing Events in Custom Precompiles

intermediate advanced 45 min

Learn how to make your Maroo precompile observable by emitting EVM-standard events using the utils package.

What You Will Learn

  • How to define events in Solidity interfaces for precompiles
  • How to load ABI definitions in Go
  • How to use `EmitEvent` to generate logs

Prerequisites

  • Basic understanding of Go and EVM
  • Existing precompile skeleton

Tools Needed

Go 1.20+Maroo Source Code
Events are the bridge between on-chain logic and off-chain indexing. In this tutorial, we will add a ConfigChanged event to a hypothetical configuration precompile.
1

1. Define the Solidity Interface

First, define the event in your Solidity interface. This serves as the source of truth for the ABI.
IConfig.sol solidity
interface IConfig {
    event ConfigChanged(address indexed admin, string key, uint256 value);
    function setConfig(string memory key, uint256 value) external;
}
2

2. Load the ABI in Go

In your precompile package, you need to parse this ABI. Usually, this is done in an init() function or a global variable.
precompile.go go
var ConfigABI abi.ABI

func init() {
    var err error
    ConfigABI, err = abi.JSON(strings.NewReader(IConfigABIJSON))
    if err != nil {
        panic(err)
    }
}
3

3. Emit the Event

Inside your Run method, after successfully changing the state, call EmitEvent.
precompile.go go
// ... inside Run function ...

// 1. Perform logic
// 2. Emit Event
err := utils.EmitEvent(
    contract.Address(),
    evm.StateDB,
    ConfigABI,
    "ConfigChanged",
    callerAddress, // indexed arg 1
    key,           // non-indexed arg 2
    value,         // non-indexed arg 3
)

if err != nil {
    return nil, err
}
Tip: Ensure the order of arguments in `EmitEvent` matches the Solidity definition exactly.

Conclusion

Your precompile now emits standard EVM logs that can be picked up by block explorers and indexers.
Source: maroo
ESC
Type to search