Skip to content

emit_event

View as Markdown

The emit_event syscall records an event in the transaction’s event log. Events are stored in anonymous memory and become part of the transaction’s output for external consumption.

Code: 0x0D (TN_SYSCALL_CODE_EMIT_EVENT)

ulong tsys_emit_event(void const* data, ulong data_sz);

data · void const · required*

Pointer to the event data to be recorded.

data_sz · ulong · required

Size of the event data in bytes. Must not exceed the maximum event size.

Returns a syscall result code:

Success · ulong

  • TN_VM_SYSCALL_SUCCESS (0) - Event recorded successfully

Error Codes · ulong

  • TN_VM_ERR_SYSCALL_EVENT_IS_ZERO_SIZE (-46) - Event size must be greater than zero
  • TN_VM_ERR_SYSCALL_EVENT_TOO_LARGE (-31) - Event size exceeds maximum allowed
  • TN_VM_ERR_SYSCALL_INVALID_ADDRESS (-22) - Invalid virtual address for event data
  • TN_VM_ERR_SYSCALL_INSUFFICIENT_PAGES (-26) - Not enough pages to expand event storage
  • Base cost: TN_VM_SYSCALL_BASE_COST (512 units)
  • Event cost: Additional units equal to event data size in bytes
  • Total formula: base_cost + data_sz
  • Event storage: Pages allocated for event storage in anonymous memory segment
  • Automatic expansion: Event storage segment grows as needed (page-aligned)
  • Metadata overhead: Additional space for event metadata per event
  • Event storage: Copies event data to transaction’s event log
  • Memory allocation: May expand event storage segment if needed
  • Event counter: Increments the transaction’s event count

The runtime automatically adds internal metadata to each emitted event before exposing it in transaction output. That metadata is not part of the public C SDK surface, so programs should treat the event payload they pass to tsys_emit_event() as the only SDK-facing input.

The metadata attached by the runtime includes:

  • Event size: Size of the event data
  • Call index: Unique identifier for the program invocation
  • Program account index: Index of the program that emitted the event
  • Events are stored in a grow-up anonymous memory segment
  • Storage automatically expands as needed (page-aligned)
  • Events are stored sequentially in the order emitted
  • Multiple events can be emitted by the same program
  • Maximum event size: UINT_MAX bytes (4GB)
  • Practical limits imposed by available memory pages
  • Event storage competes with other memory allocations
  • Events are included in transaction output for external consumption
  • Event order is preserved within the transaction
  • Events from different programs are distinguished by metadata
  • Event data format is application-defined
#include <thru-sdk/c/tn_sdk_syscall.h>
#include <string.h>
#include <stdint.h>
// Emit a simple text event
char event_msg[] = "Account created successfully";
ulong result = tsys_emit_event(event_msg, strlen(event_msg));
// Emit structured event data
struct account_created_event {
uint64_t account_id;
uint64_t initial_balance;
char account_type[16];
} event = {
.account_id = 12345,
.initial_balance = 1000000,
.account_type = "savings"
};
result = tsys_emit_event(&event, sizeof(event));
// Emit multiple related events
for (int i = 0; i < transfer_count; i++) {
struct transfer_event {
uint64_t from_account;
uint64_t to_account;
uint64_t amount;
} transfer = {
.from_account = transfers[i].from,
.to_account = transfers[i].to,
.amount = transfers[i].amount
};
result = tsys_emit_event(&transfer, sizeof(transfer));
if (result != TN_VM_SYSCALL_SUCCESS) break;
}