What You Get
AFI generates a single JSON payload — the Proof Payload — that contains everything your protocol needs to cryptographically verify reserve backing.
The payload is self-contained. It ships with the hardware root certificate, the ZK verification keys, and all proof data. Once you receive it, you never need to contact AFI again. You verify it yourself — on-chain, off-chain, or in a browser.
No oracle feeds to subscribe to. No third-party APIs to depend on. No trust required.
The Integration Flow
.png)
Here's how it works:
- Your protocol sends reserve and liability data to AFI's relay server via a single API call
- The relay server validates the request and forwards it into a hardware-isolated AWS Nitro Enclave through a secure channel (VSOCK)
- Inside the enclave — where no one can observe or tamper with execution — the system computes cryptographic commitments for every data point, generates ZK proofs for the totals, and produces a hardware attestation that seals the results
- You receive a self-contained proof payload in the API response
- You verify both the hardware attestation and the ZK proofs independently — they're designed to be checked separately
- You update your on-chain state with cryptographically verified totals
The relay server is intentionally thin. It handles authentication, rate limiting, and request validation — but it never touches sensitive computation. All cryptographic work happens inside the enclave.
What's Inside the Proof Payload
The payload is structured into clear sections — each serving a different verification purpose:
The Proof Payload Is Self-Contained — Here's Why That Matters
Most attestation systems require you to fetch verification keys from an external server, download root certificates from a CA repository, or call an API to check validity. Each of those is a dependency — and a potential point of failure or manipulation.
AFI embeds everything directly in the payload:
- The AWS Nitro Root CA certificate — so you can verify the hardware attestation's certificate chain without contacting AWS
- The ZK verification keys — so you can verify Groth16 proofs without downloading circuit artifacts
- The raw attestation document — the full COSE_Sign1 structure, so you can parse and verify it independently
This means a verifier running on an air-gapped machine, a smart contract on Ethereum, or a browser on a user's phone can all verify the same proof with zero external dependencies.
What the Totals Look Like
The payload includes both human-readable totals and cryptographically attested values:
- Verified Totals — formatted in USD with standard decimal precision (e.g.,
"200000010.50") - Attested Data — the same values in minor units (USD multiplied by 10^6) that were sealed inside the hardware attestation
The minor unit representation eliminates floating-point ambiguity. When verification checks that the TEE-attested total matches the ZK-proven total, both sides use the same integer representation — no rounding errors, no precision loss.
Three ZK Proofs, Not One
Rather than a single monolithic proof, AFI generates three separate Groth16 proofs:
- Merkle Root Proof — proves the Merkle tree root was correctly computed from the individual data commitments
- Reserves Proof — proves that hidden individual reserve values sum to the public total
- Liabilities Proof — proves that hidden individual liability values sum to the public total
Why three? Because each proves a different property, and a verifier might care about different combinations. A smart contract might only verify the sum proofs to confirm collateralization. An auditor might focus on the Merkle root proof to verify data integrity. Separating them gives integrators flexibility without sacrificing anything.
How Verification Works
A verifier runs three independent checks. Each succeeds or fails on its own. All three must pass for full confidence.
1. Hardware Attestation (TEE)
The proof includes a hardware-signed attestation document from an AWS Nitro Enclave. This is a COSE_Sign1 structure — a standard format for signed CBOR data, signed with ECDSA P-384.
Verification means:
- Certificate chain — the attestation document contains a certificate chain. Walk it from the enclave's ephemeral leaf certificate through intermediate certificates up to the AWS Nitro Root CA (which is embedded in the payload). Each certificate must be signed by the next one in the chain. If the chain is valid, the signature traces back to AWS's root of trust.
- Code measurements — the attestation includes PCR values (Platform Configuration Registers): cryptographic hashes of the enclave image (PCR0), the kernel (PCR1), and the application code (PCR2). Compare these against your expected values. If they match, you know exactly what code was running — not a modified version, not a debug build.
- Data binding — this is the critical piece. The Merkle root and computed totals are hashed together into an attestation hash, which is sealed as the
user_datafield inside the hardware signature. This isn't a side channel — it's embedded in the signed structure itself. The hardware is attesting to these specific values, not just "some code ran."
If this passes, you know: genuine AWS hardware computed these exact values using the expected code.
2. Mathematical Proof (ZK)
The proof includes three Groth16 zero-knowledge proofs on the BN128 curve. Verification uses the standard snarkjs library — the same toolchain used by Zcash, Polygon zkEVM, and dozens of production ZK systems.
Verification means:
- Merkle root proof — given the verification key and the proof's public signals, confirm the Merkle root was correctly computed from the leaf commitments. This ensures every individual data point contributed to the final root — you can't add, remove, or modify a value without changing the root.
- Reserves proof — confirm that some set of hidden values (the individual reserve amounts) genuinely sums to the public total. The proof reveals the total but not the breakdown. An auditor sees "$200M in reserves" without seeing "$80M at Custodian A, $120M at Custodian B."
- Liabilities proof — same as reserves, but for the liability side. Hidden individual liabilities are proven to sum to the public total.
Each proof is approximately 192 bytes regardless of how many values are being proven. Verification requires three elliptic curve pairing operations — fast enough to run on-chain in a single transaction.
If this passes, you know: the claimed totals are mathematically correct, without seeing any individual value.
3. Cross-Check
The values attested by the hardware must exactly match the values proven by the ZK proofs. Specifically:
- The total reserves sealed in the TEE attestation hash must equal the public signal in the reserves ZK proof
- The total liabilities sealed in the TEE attestation hash must equal the public signal in the liabilities ZK proof
- The Merkle root in the TEE attestation must equal the root verified by the Merkle root ZK proof
If they don't match, either the hardware attestation or the ZK proof was generated from different data — and the entire proof is rejected. This binding prevents an attacker from presenting a valid TEE attestation for one dataset and a valid ZK proof for a different one.
If this passes, you know: both independent proof systems agree on the same numbers.
On-Chain Verification
The ZK proofs use Groth16 on BN128 — the same proof system used by Zcash and Ethereum L2s. This means they're natively verifiable on any EVM chain.
AFI provides tooling to export Solidity verifier contracts from the circuit verification keys. The standard flow:
- Export a verifier contract from the verification key using
snarkjs - Deploy it to your chain of choice
- Submit proofs — your contract calls the verifier, checks the public signals match the claimed totals, and updates on-chain state
- Emit events — other contracts and indexers can react to verified reserve updates
The entire verification — three Groth16 proofs checked, totals stored, event emitted — fits in a single transaction. Gas costs depend on the chain, but Groth16 verification is among the cheapest ZK operations on the EVM thanks to the BN128 precompiles (EIP-196/197).
What about TEE attestation on-chain? The TEE attestation uses ECDSA P-384, which isn't natively supported on the EVM. It's verified off-chain — by your backend, by auditors, or by users in their browsers. The two layers complement each other: ZK proofs for on-chain verification, TEE attestation for off-chain hardware guarantees. Together, they cover both contexts.
Browser Verification
The same proofs can be verified client-side using standard ZK libraries. A user visiting your transparency dashboard can verify the proof in their own browser — no server calls, no trust in your infrastructure.
The snarkjs library runs in the browser. The verification keys are embedded in the payload. The verification is pure math — no network requests, no API calls, no trust assumptions beyond "elliptic curve cryptography works."
This is what makes AFI's approach fundamentally different from oracle-based systems. An oracle requires you to trust the oracle. A self-contained proof requires you to trust math. Your users can verify the proof themselves, on their own hardware, without asking anyone's permission.
Timeseries Chaining
Each proof can optionally be chained to the previous one. When you request a new proof, you pass the previous proof's Merkle root. The system hashes the previous root together with the current root to produce a chained root — and this chained value is what gets attested and proven.
The result: every new attestation is mathematically dependent on every previous one. You can't skip, reorder, or replace any proof in the chain without breaking the sequence.
Why this matters for protocols:
- Rollback prevention — a protocol can't show you an old "healthy" proof when the current state is worse
- Gap detection — if a proof in the chain is missing, the chain breaks and verifiers know something was skipped
- Continuous solvency — you're not proving "we're solvent right now" but "we've been continuously solvent since proof #1"
For protocols that update proofs on a regular cadence — hourly, daily, or on every rebalance — this creates an immutable audit trail of every reserve state the protocol has ever had.
Verification at a Glance
%20(1).png)
What Makes This Different
Most "proof of reserves" integrations ask you to trust an oracle feed, a signed message, or an API response. AFI gives you something fundamentally different:
- Self-contained — verify without calling any external service, ever. The payload includes everything: root certificates, verification keys, raw attestation documents.
- Two independent proof systems — hardware attestation and mathematical proof, each covering the other's blind spots. An attacker would need to break both ECDSA P-384 and Groth16 soundness simultaneously.
- On-chain verifiable — ZK proofs verify natively on EVM chains via BN128 precompiles. One transaction, three proofs verified, state updated.
- Privacy-preserving — individual reserve breakdowns stay hidden behind cryptographic commitments. Only totals are public. Selective disclosure is possible when auditors need it.
- Historically continuous — timeseries chaining proves ongoing solvency, not just a snapshot. Every proof is linked to every proof before it.
Your protocol doesn't trust AFI. It verifies AFI. That's the point.

%202.png)