AURA

Confidential Guardrails

How EUint64 FHE ciphertexts keep spending limits private while still being enforced on-chain via Ika Encrypt.

The Problem

A naive treasury stores daily_limit_usd = 10_000 in a public Solana account. Any observer can read it, infer the agent's strategy, and front-run or manipulate it. AURA solves this with Fully Homomorphic Encryption (FHE) via the Ika Encrypt network — the limit value is stored as an EUint64 ciphertext and never decrypted during evaluation.

What Gets Encrypted

Three scalar EUint64 ciphertext accounts are attached to a treasury via configure_confidential_guardrails:

Ciphertext accountWhat it holds
daily_limit_ciphertextEncrypted daily spending limit in USD cents
per_tx_limit_ciphertextEncrypted per-transaction limit in USD cents
spent_today_ciphertextEncrypted running total spent today in USD cents

These are Solana accounts owned by the Ika Encrypt program. Their addresses are stored in the TreasuryAccount and passed as accounts to every confidential instruction.

Instruction Flow

CPI Accounts for propose_confidential_transaction

The instruction requires these accounts beyond the standard treasury/AI authority pair:

AccountSeed / SourcePurpose
daily_limit_ciphertextstored in TreasuryAccountEncrypted daily limit
per_tx_limit_ciphertextstored in TreasuryAccountEncrypted per-tx limit
spent_today_ciphertextstored in TreasuryAccountEncrypted running counter
amount_ciphertextfreshly createdEncrypted proposal amount
policy_output_ciphertextfreshly createdOutput — encrypted verdict
encrypt_program4ebfzWdKnrnGseuQpezXdG8yCdHqwQ1SSBHD3bWArND8Ika Encrypt program
configEncrypt program global configEncrypt network config
depositpayer-fundedPays for FHE compute
caller_programaura-core program IDCPI caller identity
cpi_authority["__encrypt_cpi_authority"] on aura-coreSigns the CPI
network_encryption_keyEncrypt program accountNetwork's public key
event_authority["__event_authority"] on Encrypt programEmit Encrypt events
system_program11111111111111111111111111111111Account creation

What the FHE Circuit Does

The Ika Encrypt network evaluates a circuit over the four ciphertexts:

verdict = if (amount > per_tx_limit) → PerTransactionLimit
          else if (spent_today + amount > daily_limit) → DailyLimit
          else → None (approved)

The output is an encrypted u8 — the ViolationCode. Only this small integer is decrypted on-chain. The limit values and running counter remain encrypted throughout.

What Stays Private

DataOn-chain visibility
Daily limit valuePrivate — EUint64 ciphertext only
Per-tx limit valuePrivate — EUint64 ciphertext only
Running spent-today totalPrivate — EUint64 ciphertext only
Proposal amountPublic — in PendingTransaction.amount_usd
Violation code (0 or N)Public — decrypted on-chain
Recipient / chainPublic — in PendingTransaction

Public Precheck Before FHE

evaluate_public_precheck runs before the FHE CPI. It evaluates all rules except per_tx_limit and daily_limit (those are deferred to Encrypt). If any public rule fails, the proposal is rejected immediately — no FHE call is made, saving compute and cost.

Decryption Accounts for request_policy_decryption

AccountPurpose
request_accountFreshly created — tracks the decryption request
ciphertextThe policy_output_ciphertext from the pending proposal
encrypt_programIka Encrypt program
configEncrypt global config
depositPays for decryption
caller_programaura-core program ID
cpi_authority["__encrypt_cpi_authority"] on aura-core
network_encryption_keyEncrypt network's public key
event_authority["__event_authority"] on Encrypt program
system_programAccount creation

SDK Usage

import { AuraClient } from "@aura-protocol/sdk-ts";

// Configure confidential guardrails (owner signs)
await client.configureConfidentialGuardrails(owner, {
  owner: owner.publicKey,
  treasury,
  dailyLimitCiphertext,    // PublicKey of EUint64 ciphertext account
  perTxLimitCiphertext,
  spentTodayCiphertext,
});

// Propose a confidential transaction (AI authority signs)
await client.proposeConfidentialTransaction(aiAuthority, {
  aiAuthority: aiAuthority.publicKey,
  treasury,
  dailyLimitCiphertext,
  perTxLimitCiphertext,
  spentTodayCiphertext,
  amountCiphertext,        // freshly created
  policyOutputCiphertext,  // freshly created — will hold verdict
  encryptProgram: ENCRYPT_DEVNET_PROGRAM_ID,
  config: encryptConfig,
  deposit: depositAccount,
  callerProgram: AURA_PROGRAM_ID,
  cpiAuthority: deriveEncryptCpiAuthorityAddress()[0],
  networkEncryptionKey,
  eventAuthority: deriveEncryptEventAuthorityAddress(ENCRYPT_DEVNET_PROGRAM_ID)[0],
  systemProgram: SystemProgram.programId,
}, args);

On this page