Skip to main content
Every successful transact call emits exactly one AuditEncodedDigest Soroban event. This event is the handoff point between the on-chain privacy pool and the off-chain Arcane compliance pipeline — it carries the encrypted audit payload your application prepared, making it available to the Arcane scanner for ingestion, storage, and eventual interpretation by the Auditing Portal.

Event structure

The AuditEncodedDigest event is defined in the contract as follows:
#[contractevent(topics = ["audit", "encoded_digest"], data_format = "single-value")]
pub struct AuditEncodedDigest {
    #[topic]
    message_name: String,
    digest: Bytes,
}
FieldMeaning
message_nameAlways "transact" for the current contract. The Arcane scanner uses this topic to categorize the raw event.
digestThe encrypted audit payload that was passed to transact as the encoded argument. This is stored verbatim — the contract does not inspect or modify its contents.
The event is indexed under the topics ["audit", "encoded_digest"], which the Arcane scanner uses to identify and route it to the compliance pipeline.

What gets indexed

When the Arcane scanner observes an AuditEncodedDigest event, it stores the encrypted payload alongside the transaction metadata as a raw audit row. The scanner records the contract ID, the Stellar transaction hash, the Soroban event ID, the event type (transact), and the ciphertext from digest. The encrypted payload is later picked up by the interpretation worker, which decrypts it using the contract’s registered decoding_key and produces a structured audit_interpretation record that the Auditing Portal can present to auditors. For a full description of the off-chain processing path, see Auditing Portal.

What you need to provide

Your application is responsible for preparing the encoded argument before calling transact. You construct this payload using the Arcane SDK — it encrypts the transaction details in a format the Auditing Portal can later decrypt and interpret.
// The SDK encodes and encrypts the audit payload for you
const encoded = await sdk.encodeAuditPayload({
  coin,
  recipient,
  amount,
  // ...other transaction fields
});

// Pass the encoded payload to transact alongside the proof
await privacyPool.transact({
  from,
  proofBytes,
  pubSignalsBytes,
  encoded,
});
The encoded payload is encrypted end-to-end. Your application never decrypts it. The Arcane Auditing Portal uses the decoding_key registered against the contract to decrypt and interpret the payload — your application only needs to produce it via the SDK and pass it through to transact.

Handoff flow

After transact succeeds, the audit event travels through the following pipeline before it becomes visible in the Arcane Auditing Portal: The scanner polls Stellar RPC for new events, filters on the audit topic, and persists the ciphertext. The interpretation worker then decrypts the payload, resolves the transaction fields, and writes the final audit_interpretation record that auditors see in the UI.
The AuditEncodedDigest event is only emitted on successful transact calls. Failed transactions — for example, those rejected due to an invalid proof, a consumed nullifier, or an out-of-history state root — do not produce audit events and will not appear in the Arcane Auditing Portal.