Events
The Limitation
Shielded types cannot be emitted directly in events. The following will not compile:
event ConfidentialEvent(suint256 confidentialData); // Compilation errorThis restriction exists because events are stored in transaction logs, which are publicly accessible on-chain. Emitting a shielded value in an event would defeat the purpose of shielding it in the first place -- the value would be visible to anyone inspecting the logs.
This applies to all shielded types: suint, sint, sbool, saddress, and sbytes.
The Workaround: Encrypted Events via Precompiles
Although native encrypted events are not yet supported, you can achieve private event data today using the AES-GCM and ECDH precompiles. The approach is to encrypt the sensitive data before emitting it in a regular (unshielded) event, so that only the intended recipient can decrypt it.
Here is the general flow:
Generate a shared secret between the sender and the intended recipient using the ECDH precompile at address
0x65.Derive an encryption key from the shared secret using the HKDF precompile at address
0x68.Encrypt the event data using the AES-GCM Encrypt precompile at address
0x66.Emit a regular event containing the encrypted bytes. Since the event parameter is
bytes(not a shielded type), this compiles and works normally.Recipient decrypts the data using the AES-GCM Decrypt precompile at address
0x67, either off-chain or on-chain if needed.
Precompile Reference
Code Example
Below is a minimal private token showing how to emit encrypted transfer events. The contract holds a keypair; users register their public keys so the contract can encrypt event data that only the recipient can read.
For a full implementation, see the SRC20: Private Token tutorial.
The built-in helpers ecdh(), hkdf(), and aes_gcm_encrypt() are compiler-provided globals — no imports needed. See the Precompiles reference for details on each.
Decryption (Off-Chain)
The recipient reconstructs the shared secret off-chain using their own private key and the contract's public key (ECDH is symmetric). They then derive the same encryption key via HKDF and decrypt the event data using AES-GCM Decrypt.
The client libraries provide built-in helpers for this:
Python —
watch_src20_events_with_keyandSRC20EventWatcherTypeScript (viem) —
watchSRC20EventsWithKey()action
What Not to Do
Do not attempt to work around the restriction by casting a shielded value to its unshielded counterpart and then emitting it:
Casting from a shielded type to an unshielded type makes the value visible in the execution trace. Emitting it in an event then permanently records it in publicly accessible logs.
Future Improvements
Native encrypted events are planned for a future version of Seismic. This will allow shielded types to be emitted directly in events without requiring manual encryption via precompiles. The compiler and runtime will handle encryption transparently, making private events as simple to use as regular events.
Key Takeaway
Privacy in events is achievable today -- it just requires explicit encryption via the aforementioned precompiles. Encrypt sensitive data before emitting it, and ensure only the intended recipient has the keys to decrypt. When native encrypted events ship, migrating will be straightforward: replace the manual encryption logic with direct shielded type emission.
Last updated

