Proof and on-chain verification.
This is the evidence room. The real 256 bytes proof, the exact split between what Stellar sees and what stays hidden, the contracts that gate the money, and the trust model named in full. Every value below is read from a live testnet, not a screenshot.
The proof, byte by byte.
This is the real Groth16 over BN254 proof Stellar verifies on its own. It is the three curve points A · B · C, generated in your browser. Stellar reads all 256 bytes and decides for itself.
The 256-byte Groth16 proof — points A ‖ B ‖ C, byte by byte. Stellar reads it and decides on its own. A real proof locks lime. A forged one is rejected and nothing moves.
A real proof locks lime. A forged one is rejected and nothing moves. The lit bytes at the front mark where proof point A begins; the rest are points B and C, all checked by one BN254 pairing.
What Stellar sees, and what it never sees.
The proof commits to a small set of public inputs and nothing more. Everything on the left is on-chain. Everything on the right stays inside the prover and is never sent anywhere.
Proof that your collateral cleared the required minimum — the figure itself is never published.
The Poseidon2 commitment to your note, inserted into the pool tree.
Published when the note is spent, so the same note can never be spent twice.
The authenticated (commitment, amount) delivery that backed your note with real Sepolia WETH.
How much you actually locked. Sealed in the witness, never transmitted.
Which wallet holds it. Never written to Stellar, never on the ledger.
That gap is the privacy guarantee. Stellar can confirm you cleared the threshold and that this proof has never been used, without ever learning how much you hold or which wallet is yours. The lender, the ledger, and every observer see only the public journal.
The contract that checks every proof.
A single Soroban contract on Stellar testnet does the verification. It is pinned to one circuit's verifying key, so it only accepts proofs produced by the exact circuit Veil published.
Forge the proof, and no USDC moves.
This is not hypothetical. In Veil's live cross-chain run a borrow proof with a tampered public input was rejected on-chain with Error(Contract, #0) InvalidProof, and zero USDC moved. Replay it below and the proof shatters red. Re-spending an already-spent note is rejected too — its nullifier is already recorded. Either way the money stays put.
This flips one byte inside the real 256-byte Groth16 proof. On-chain, the vault rejects a tampered proof: a real one locks lime, a forged one shatters and nothing moves.
The 256-byte Groth16 proof — points A ‖ B ‖ C, byte by byte. Stellar reads it and decides on its own. A real proof locks lime. A forged one is rejected and nothing moves.
Deployed contracts and on-chain proof.
A real WETH lock on Ethereum Sepolia, the Soroban pool, vault, and Groth16 verifier on Stellar, and the live cross-chain transactions that locked collateral and disbursed the loan.