Events are the mechanism that applications off-chain can use to monitor changes and events in contracts on-chain.
How are events emitted?
ContractEvents are emitted in Stellar Core's
TransactionMeta. You can see in
the TransactionMetaV3 XDR below that there is a list of
OperationEvent corresponds to an operation in a
transaction, and itself contains a list of
ContractEvents. Note that
will only be populated if the transaction succeeds. Take a look at this
example to learn more about how to emit an event
in your contract.
// We can use this to add more fields, or because it
// is first, to change ContractEvent into a union.
union switch (int v)
LedgerEntryChanges txChangesBefore; // tx level changes before operations
// are applied if any
OperationMeta operations<>; // meta for each operation
LedgerEntryChanges txChangesAfter; // tx level changes after operations are
// applied if any
OperationEvents events<>; // custom events populated by the
// contracts themselves. One list per operation.
Hash hashes; // stores sha256(txChangesBefore, operations, txChangesAfter),
// sha256(events), and sha256(txResult)
// Diagnostics events that are not hashed. One list per operation.
// This will contain all contract and diagnostic events. Even ones
// that were emitted in a failed contract call.
Link to the XDR above.
There are three
CONTRACTevents are events emitted by contracts that use the
contract_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 the
update_current_contract_wasmhost function is called, where
topics = ["executable_update", old_executable: ContractExecutable, old_executable: ContractExecutable]and
data = .
DIAGNOSTICevents are meant for debugging and will not be emitted unless the host instance explictly enables it. You can read more about this below.
What are diagnosticEvents?
While looking at the
TransactionMetaV3 XDR struct above, you may have noticed
diagnosticEvents 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 not only include all
events, but will also include events from failed contract
calls, errors from the host, events to trace the contract call stack, and logs
log_from_linear_memory host function. These events can be identified
type == DIAGNOSTIC. The diagnostic events emitted by the host to track the
call stack are defined below.
fn_call diagnostic event is emitted when a contract is called
and contains -
- The symbol "fn_call".
- The contract id of the contract about to be called.
- A symbol containing the name of the function being called.
- A vector of the arguments passed to the function being called.
fn_return diagnostic event is emitted when a contract call completes and contains -
- The symbol "fn_return".
- A symbol containing the name of the function that is about to return.
- The value returned by the contract function.
When should diagnostic events be enabled?
ContractEvents that should convey information about state
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).