How are events emitted?
ContractEvents are emitted in Stellar Core’s TransactionMeta. The location of events will depend on the version of TransactionMeta emitted. You can see in the TransactionMetaV3 XDR below that for Soroban transactions, there is a sorobanMeta field containing SorobanTransactionMeta which includes both events (custom events from contracts) and diagnosticEvents. Note that events will only be populated if the transaction succeeds.
TransactionMetaV4 is more complex because it supports events for not only Soroban, but also classic operations, fees, and refunds. The top-level events vector is used for transaction level events, and currently contains fee events for both the initial fee charged and the refund (if applicable). Events tied to operations can be found under OperationMetaV2.
ContractEvent
An event’s topics don’t have to be made of the same type: you can mix different types. An event also contains a data object of any value or type, including custom types defined by contracts using#[contracttype]:
ContractEvent can be emitted in the following versions of TransactionMeta -
TransactionMetaV3
TransactionMetaV4
Event types
There are threeContractEventType’s -
CONTRACTevents are events emitted by contracts that use thecontract_eventhost function to convey state changes.SYSTEMevents are events emitted by the host. At the moment, there’s only one system event emitted by the host. It is emitted when theupdate_current_contract_wasmhost function is called, wheretopics = ["executable_update", old_executable: ContractExecutable, new_executable: ContractExecutable]anddata = [].DIAGNOSTICevents are meant for debugging and will not be emitted unless the host instance explicitly enables it. You can read more about this below.
What are diagnosticEvents?
While looking at the xdr above, you may have noticed thediagnosticEvents field. This list will be empty by default unless your stellar-core instance has ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true in its config file. If diagnostic events are enabled, this list will include events from failed contract calls, errors from the host, events to trace the contract call stack, and logs from the log_from_linear_memory host function. These events can be identified by type == DIAGNOSTIC. If the transaction is for a soroban invocation, the list will also contain the non-diagnostic events emitted by the contract. The diagnostic events emitted by the host to track the call stack are defined below.
fn_call
Thefn_call diagnostic event is emitted when a contract is called and contains -
- Topics
- The symbol “fn_call”.
- The contract id of the contract about to be called.
- A symbol containing the name of the function being called.
- Data
- A vector of the arguments passed to the function being called.
fn_return
Thefn_return diagnostic event is emitted when a contract call completes and contains -
- Topics
- The symbol “fn_return”.
- A symbol containing the name of the function that is about to return.
- Data
- The value returned by the contract function.
When should diagnostic events be enabled?
RegularContractEvents should convey information about state changes. diagnosticEvents on the other hand contain events that are not useful for most users, but may be helpful in debugging issues or building the contract call stack. Because they won’t be used by most users, they can be optionally enabled because they are not hashed into the ledger, and therefore are not part of the protocol. This is done so a stellar-core node can stay in sync with the network while emitting these events that normally would not be useful for most users.
Due to the fact that a node with diagnostic events enabled will be executing code paths that diverge from a regular node, we highly encourage only using this feature on watcher node (nodes where NODE_IS_VALIDATOR=false is set).
Tracking the movement of value
Starting in protocol 23, classic operations can emittransfer, mint, burn, clawback, fee, and set_authorized events so that the movement of assets and trusline updates can be tracked using a single stream of data. These events will be emitted if a node has EMIT_CLASSIC_EVENTS=true set. If BACKFILL_STELLAR_ASSET_EVENTS=true is also set, then events will be emitted for any ledger, regardless of protocol version.
Reading events
You can use thegetEvents endpoint of any RPC service to fetch and filter events by type, contract, and topic.
To learn more about working with events, take a look at the events guides and this example contract.
For a quick high-level demonstration, though, we’ll use the TypeScript SDK to infinitely fetch all transfer events (defined by the Soroban Token Interface) involving the XLM contract and display them in a human-friendly format.
xdrFormat: "json" as an additional parameter to the getEvents example.