Implementing Events in Custom Precompiles
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.