Skip to content

NAV Oracle

The NAV Oracle is the core proprietary technology Agama builds. Everything else (vault shell, fees, KYC, reporting) is provided by Lagoon. The oracle is what makes Agama structurally non-replaceable, and what makes it one of the first verifiable bridges between a private institutional chain and public DeFi.

The problem: bridging private to public

For an invoice sitting on Nimofast's Privacy Node to generate yield in a public Lagoon vault, something has to bridge the gap between the two layers. Without this bridge, the invoices stay locked, invisible, non-valorizable, non-existent for the public vault.

PRIVACY NODE (Nimofast)
┌─────────────────────────────────────┐
│  Invoice #1: [ENCRYPTED]           │
│  Invoice #2: [ENCRYPTED]           │
│  Invoice #3: [ENCRYPTED]           │
│  Total NAV:  ???                   │
└──────────────────┬──────────────────┘

                   │  Public chain cannot read this.
                   │  A DeFi vault cannot price
                   │  what it cannot see.


PUBLIC CHAIN
┌─────────────────────────────────────┐
│  agaNMF vault                       │
│  Share price: ???                   │
│  Cannot update without NAV          │
└─────────────────────────────────────┘

This is not a Nimofast problem. It is a structural problem for every institution on Rayls. Agama solves it.

Why a real ZK proof, not a signed attestation

Most oracle designs in DeFi rely on a multisig attestation: a trusted party signs a value and publishes it on-chain. If the signer lies, it is only detectable after the fact.

Agama does not use attestations. The NAV Oracle generates a real ZK proof using gnark, the same library used by Enygma internally. The proof is verified on-chain by anyone, instantly. If the NAV is wrong, the proof is invalid and the smart contract rejects it. Agama cannot lie.

This is possible because Enygma uses Pedersen commitments to store balances. A Pedersen commitment is C = v*G + r*H where v is the value and r is a blinding factor. The critical property: Pedersen commitments are homomorphic. You can add commitments without knowing the individual values. C1 + C2 is itself a valid commitment for (v1 + v2) without revealing v1 or v2 separately. This means the circuit can verify portfolio-level properties without exposing individual invoice data.

The Oracle Sidecar

Agama builds and maintains a software process, the Oracle Sidecar, that runs alongside each institution's Privacy Node. The institution runs it. Agama owns the code.

PRIVACY NODE (Nimofast)
┌──────────────────────────────────────────────────────┐
│                                                      │
│   Invoice tokens (Enygma encrypted, Pedersen         │
│   commitments on balances)                           │
│                                                      │
│   ┌──────────────────────────────────────────────┐   │
│   │  AGAMA ORACLE SIDECAR              (Go)      │   │
│   │                                              │   │
│   │  1. connector/enygma_client.go               │   │
│   │     Reads invoice tokens via view key        │   │
│   │     Obtains: face values, blinding factors,  │   │
│   │     purchase dates, maturity dates           │   │
│   │                                              │   │
│   │  2. circuit/nav_circuit.go                   │   │
│   │     gnark ZK circuit that proves:            │   │
│   │     - each face value is positive            │   │
│   │     - accrual is computed correctly           │   │
│   │     - NAV = sum of all accrued values        │   │
│   │     - tranching is computed correctly         │   │
│   │     Generates proof π                        │   │
│   │                                              │   │
│   │  3. publisher/onchain_relay.go               │   │
│   │     Submits (NAV, tranching, π) on-chain     │   │
│   │     Pays gas in USDr                         │   │
│   └──────────────────────────────────────────────┘   │
│                                                      │
└────────────────────────┬─────────────────────────────┘

                         │  ZK proof π + NAV + tranching
                         │  (no invoice data crosses)


PUBLIC CHAIN
┌──────────────────────────────────────────────────────┐
│                                                      │
│   AgamaOracle.sol                                    │
│     AgamaVerifier.sol (auto-generated by gnark)      │
│     Verifies π on-chain using BN254 precompiles      │
│     If valid: updates NAV + share price              │
│     If invalid: transaction reverts                  │
│                                                      │
│   Anyone can call verifyProof() and check            │
│   that the published NAV is correct                  │
│                                                      │
└──────────────────────────────────────────────────────┘

What crosses the bridge: the aggregated NAV, the tranche breakdown, and the ZK proof. No invoice details, no debtor names, no individual amounts.

What stays private: everything. The sidecar reads data locally using the view key, computes the proof locally, and only publishes the verified result.

The oracle does not publish a single NAV number. It publishes the NAV broken down into three risk tranches, computed from the invoice portfolio.

NAV(t) = Σ [purchase_price_i + (face_value_i - purchase_price_i) × accrual_factor_i]

accrual_factor_i = (t - t_purchase_i) / (t_maturity_i - t_purchase_i)

Tranche assignment by invoice duration:

  SENIOR      duration ≤ 30 days     debtors: Petrobras, Shell
  MEZZANINE   duration 30-60 days    debtors: regulated distributors
  JUNIOR      duration > 60 days     longer duration positions

What the investor sees on-chain:

agaNMF Portfolio

NAV Total        :  1,240,000 USDXP
ZK Proof         :  Verified on-chain

Breakdown :
  Senior         :    744,000 USDXP  (60%)
  Mezzanine      :    372,000 USDXP  (30%)
  Junior         :    124,000 USDXP  (10%)

Last update      :  2026-04-30 14:23 UTC

Why tranching from day one: it is the foundation for agaUSD at V4 (the capital stack already exists on-chain with historical data), and it prepares Cork integration (the lender can look at the senior ratio to decide the acceptable LTV on agaNMF).

The ZK circuit

The circuit is written in Go using gnark (ConsenSys ZK library, production-ready, used by Enygma). It compiles once, generates a Solidity verifier contract, and then produces proofs for each NAV update.

gnark workflow:

  STEP 1. Write the circuit (nav_circuit.go)
           Defines mathematical constraints

  STEP 2. Compile the circuit (one-time)
           gnark.Compile() → generates AgamaVerifier.sol
           + proving key (sidecar keeps this)
           + verifying key (deployed on-chain)

  STEP 3. Deploy the verifier
           AgamaVerifier.sol deployed on Rayls Public Chain
           One-time deployment

  STEP 4. Generate proofs (every NAV update)
           Sidecar reads invoices via view key
           Computes NAV + tranching
           gnark.Prove() → proof π
           Submits (NAV, tranching, π) to AgamaOracle
           Verifier checks π on-chain
           If valid → NAV updated
           If invalid → transaction reverts

What the circuit proves without revealing private inputs:

PRIVATE INPUTS (never published)
  vi           face value of each invoice
  ri           Enygma blinding factor

CIRCUIT CONSTRAINTS
  1. Each face value and purchase price are positive
     (range proof: vi > 0, pi > 0, pi ≤ vi)
  2. Each accrual factor is computed correctly
     from the public timestamps
  3. No invoice has accrued beyond its face value
     (accrual_factor ≤ 1)
  4. value_i = purchase_price_i + (face_value_i - purchase_price_i) × accrual_factor_i
  5. The sum of all accrued values = the claimed NAV
  6. The tranche breakdown sums to the total NAV
  7. Each invoice is assigned to the correct tranche
     based on its duration

PUBLIC OUTPUTS (published on-chain)
  NAV total                  verified
  Senior / Mezzanine / Junior breakdown  verified
  Timestamps per invoice     verified
  ZK proof π                 verifiable by anyone

Sidecar repository structure

agama-oracle-node/                         (Go)

  ├── circuit/
  │   └── nav_circuit.go                   THE CORE
  │       gnark circuit encoding:
  │       range proofs, accrual computation,
  │       NAV summation, tranche classification

  ├── setup/
  │   └── compile.go                       RUN ONCE
  │       gnark.Compile(circuit)
  │       → AgamaVerifier.sol
  │       → proving key
  │       → verifying key

  ├── connector/
  │   └── enygma_client.go                 RAYLS API
  │       Connects to Privacy Node
  │       Reads invoice tokens via view key
  │       Returns: []Invoice{FaceValue, PurchaseTime, MaturityTime}

  ├── prover/
  │   └── nav_prover.go                    PROOF GENERATION
  │       Receives decrypted invoices
  │       Builds the witness (private + public inputs)
  │       gnark.Prove(circuit, witness) → π

  ├── publisher/
  │   └── onchain_relay.go                 ON-CHAIN SUBMISSION
  │       Calls AgamaOracle.updateNAV(NAV, tranching, π)
  │       Pays gas in USDr

  └── config/
      └── nimofast.config.json
          privacy_node_rpc : "https://..."
          view_key          : "0x..."
          oracle_contract   : "0x..."
          update_interval   : "24h"

Each institutional client gets the same sidecar configured for their asset type. Nimofast for invoices. Santander for trade finance. Nuclea for receivables. The software is the same. The configuration changes.

On-chain contracts

gnark auto-generates AgamaVerifier.sol at compile time. The oracle contract wraps it:

solidity
contract AgamaOracle {

    struct TrancheNAV {
        uint256 total;
        uint256 senior;
        uint256 mezzanine;
        uint256 junior;
        uint256 timestamp;
    }

    IVerifier public immutable verifier;  // gnark auto-generated
    TrancheNAV public latestNAV;

    function updateNAV(
        TrancheNAV calldata nav,
        uint256[2] calldata a,       // gnark proof components
        uint256[2][2] calldata b,
        uint256[2] calldata c
    ) external {
        uint256[] memory pub = new uint256[](5);
        pub[0] = block.timestamp;
        pub[1] = nav.total;
        pub[2] = nav.senior;
        pub[3] = nav.mezzanine;
        pub[4] = nav.junior;

        // On-chain ZK verification
        // Invalid proof → automatic revert
        require(
            verifier.verifyProof(a, b, c, pub),
            "Invalid ZK proof"
        );

        latestNAV = nav;
    }

    function getLatestNAV() external view returns (
        TrancheNAV memory nav,
        bool isValid
    ) {
        nav = latestNAV;
        isValid = (block.timestamp - nav.timestamp) < 48 hours;
    }
}

Anyone can call verifyProof() and cryptographically confirm that the published NAV is correct, without seeing any private data. This is the real oracle.

What makes this a first

Agama is one of the first verifiable oracle bridges between a private institutional chain and public DeFi. Existing private-to-public bridges rely on trusted attestations (multisig signers, trusted committees). Agama replaces trust with math: if the NAV is wrong, the ZK proof is invalid and the smart contract rejects it automatically.

No other vault curator in the RWA space offers on-chain verifiable proofs of NAV. This is the technical moat that scales from one client (Nimofast) to an oracle network (V3).

Questions to confirm with Rayls before build

Everything depends on the Privacy Node API. These must be answered before coding enygma_client.go:

  1. When using the view key, does the API return decrypted face values directly, or the raw Pedersen commitments with blinding factors? Both work for gnark, but the circuit complexity differs.

  2. Do invoice tokens on the Privacy Node have structured metadata accessible via API (purchase_date, maturity_date, face_value)? Or is this data stored off-chain at Nimofast?

  3. Does the Rayls Public Chain support Groth16 proof verification (gnark default)? If BN254 precompiles are available, verification is cheap. Otherwise gnark can target Plonk.

  4. Is there a testnet Privacy Node accessible to Agama before April 30 for end-to-end testing?

Security parameters

ParameterValue
Update frequencyDaily (V1), real-time (V2)
Proof systemGroth16 via gnark (or Plonk if no BN254 precompile)
Circuit sizeFixed at 100 invoices max (V1)
Staleness threshold48 hours
Circuit breakerNAV deviation > 5% in 24h → update blocked
VerifierAuto-generated by gnark, deployed once on Public Chain