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 account | What it holds |
|---|---|
daily_limit_ciphertext | Encrypted daily spending limit in USD cents |
per_tx_limit_ciphertext | Encrypted per-transaction limit in USD cents |
spent_today_ciphertext | Encrypted 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:
| Account | Seed / Source | Purpose |
|---|---|---|
daily_limit_ciphertext | stored in TreasuryAccount | Encrypted daily limit |
per_tx_limit_ciphertext | stored in TreasuryAccount | Encrypted per-tx limit |
spent_today_ciphertext | stored in TreasuryAccount | Encrypted running counter |
amount_ciphertext | freshly created | Encrypted proposal amount |
policy_output_ciphertext | freshly created | Output — encrypted verdict |
encrypt_program | 4ebfzWdKnrnGseuQpezXdG8yCdHqwQ1SSBHD3bWArND8 | Ika Encrypt program |
config | Encrypt program global config | Encrypt network config |
deposit | payer-funded | Pays for FHE compute |
caller_program | aura-core program ID | CPI caller identity |
cpi_authority | ["__encrypt_cpi_authority"] on aura-core | Signs the CPI |
network_encryption_key | Encrypt program account | Network's public key |
event_authority | ["__event_authority"] on Encrypt program | Emit Encrypt events |
system_program | 11111111111111111111111111111111 | Account 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
| Data | On-chain visibility |
|---|---|
| Daily limit value | Private — EUint64 ciphertext only |
| Per-tx limit value | Private — EUint64 ciphertext only |
| Running spent-today total | Private — EUint64 ciphertext only |
| Proposal amount | Public — in PendingTransaction.amount_usd |
| Violation code (0 or N) | Public — decrypted on-chain |
| Recipient / chain | Public — 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
| Account | Purpose |
|---|---|
request_account | Freshly created — tracks the decryption request |
ciphertext | The policy_output_ciphertext from the pending proposal |
encrypt_program | Ika Encrypt program |
config | Encrypt global config |
deposit | Pays for decryption |
caller_program | aura-core program ID |
cpi_authority | ["__encrypt_cpi_authority"] on aura-core |
network_encryption_key | Encrypt network's public key |
event_authority | ["__event_authority"] on Encrypt program |
system_program | Account 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);