Inserts a Groth16 zk-SNARK Reasoning Anchor into every LLM agent-to-chain settlement path — making memory poisoning attacks in autonomous DeFi provably impossible.
Autonomous LLM agents executing DeFi transactions face an attack that ignores private keys entirely — an adversary corrupts the agent's vector memory, RAG corpus, or oracle stream, making it sign malicious transactions while believing it operates within safe parameters.
Before reasoning, the agent commits a Poseidon hash of its context window, state vector, and oracle inputs to an on-chain contract.
H₁ = Poseidon(X₁, S₁, I₁) → commitState(H₁) on-chain.
After producing a transaction payload Tₓ, the agent generates a Groth16 zk-SNARK proving Tₓ was derived from inputs hashing to H₁ and satisfying the safety policy C (amount bounds, slippage ≤ 200 bps, router whitelist).
π ← Prove(pk, (H₁, Tₓ), (X₁, S₁, I₁, r, σ))
The smart contract verifies π via Groth16 pairing check, enforces policy bounds, marks the nullifier ν (replay protection), then executes the ERC-20 safeTransfer atomically. Any transaction from poisoned inputs fails the pairing check and is rejected.
The Python daemon sits between the LLM agent and the blockchain. The Solidity contract is the cryptographic enforcement layer.
┌────────────────────────────────────────────────────────────────┐
│ LLM Agent Runtime │
│ │
│ Oracle feeds ──► Context Window (Xt) │
│ RAG memory ──► State Vector (St) ──► Poseidon ──► Ht │
│ User intent ──► Input stream (It) │
│ | | │
│ ▼ ▼ │
│ Policy engine C commitState(Ht) │
│ generates Tx ──► chain (block b) │
│ | │
│ ▼ │
│ SnarkJS / rapidsnark │
│ Groth16 Prove(pk, pub, wit) ──► π │
└──────────────────────────────────┤──────────────────────────────┘
| verifyAndExecute(π, Tx, nonce, ν)
▼
┌────────────────────────────────────────────────────────────────┐
│ ReasoningAnchorVerifier.sol │
│ │
│ 1. Load Ht from pendingCommitments[agent][nonce] │
│ 2. Groth16 pairing check │
│ 3. Enforce: amount ≤ cap, slippage ≤ 200 bps, router ∈ W │
│ 4. Mark nullifier ν (replay protection) │
│ 5. ERC-20 safeTransfer to recipient │
└────────────────────────────────────────────────────────────────┘
Groth16 circuit over BN254. Arithmetizes Poseidon state commitment and policy bounds in ~3,800 R1CS constraints. Circom 2.1.6.
On-chain Groth16 verifier with AGENT_ROLE / GUARDIAN_ROLE access control, commitment storage, nullifier replay protection, and ERC-20 safeTransfer.
Async Python daemon that intercepts LLM agent tool calls, computes Poseidon state hash, drives SnarkJS or rapidsnark prover, and submits proofs to the on-chain verifier.
The circuit arithmetizes a single, precise statement: this transaction was derived from unmodified reasoning inputs that satisfy the safety policy.
| Parameter | Value |
|---|---|
| Proving system | Groth16 |
| Curve | BN254 (alt_bn128) |
| Hash function | Poseidon (t=3, α=5, Rṣ=8, Rẞ=57) |
| Context chunks Nₓ | 8 field elements |
| State chunks Nₛ | 8 field elements |
| Input chunks Nᵢ | 4 field elements |
| Total R1CS constraints | ~3,800 |
| Public inputs | H₁, recipient, amount, slippage_bps, routerHash |
Witness: 38 ms Prove: 1,164 ms Total: 1,202 ms
Witness: 12 ms Prove: 170 ms Total: 182 ms
BN254 pairing (4): 180,000 Scalar mul (5×): 30,000 Storage reads: 4,200 ERC-20 transfer: 35,000 Calldata + events: 25,000 Total: 276,200
Under q-SDH on BN254 and Poseidon collision resistance — the standard hardness assumptions for Groth16 deployments.
An honest agent with valid witnesses always produces an accepted proof. Legitimate transactions are never blocked by the protocol.
Under q-SDH on BN254 and Poseidon collision resistance, no adversary — regardless of how they poisoned the agent's memory — can produce a valid proof for a transaction derived from corrupted inputs.
The proof reveals nothing about the context window X₁, state vector S₁, oracle inputs I₁, the router address, or the proving salt σ. Strategy and position data stay private.
Each proof is bound to a nullifier ν. Once verifyAndExecute succeeds, ν is marked on-chain — the same proof cannot be submitted twice.
Amount bounds, slippage limits (≤ 200 bps), and router whitelist membership are verified inside the circuit — not just in application code — making them unforgeable.
AGENT_ROLE and GUARDIAN_ROLE separation in the Solidity contract. Guardian can pause settlement without revoking the agent's ability to commit state.
| Defense | Memory poisoning proof | On-chain enforceable | <200ms latency | Zero-knowledge | Policy in circuit |
|---|---|---|---|---|---|
| Memory encryption | ✗ | ✗ | ✓ | ✗ | ✗ |
| Runtime monitor | ✗ | ✗ | ✓ | ✗ | ✗ |
| zkML (full inference) | ✓ | ✓ | ✗ >2s | ✓ | partial |
| ZKP-RA (this work) | ✓ | ✓ | ✓ 182ms | ✓ | ✓ |
Four steps from clone to a running agent guardian with on-chain proof verification.
git clone https://github.com/\ sunilgentyala/ZKP-RA cd ZKP-RA npm install pip install -r requirements.txt
bash scripts/compile_and_setup.sh
npx hardhat compile npx hardhat run \ scripts/deploy.js \ --network <network>
snarkjs vkey before deploying.export AGENT_PRIVATE_KEY=0x... python src/agent_guardian.py \ config.json
Track ZKP-RA's growth on GitHub.
A star helps cryptographers, DeFi security researchers, and AI safety engineers find this work. Companion paper in preparation — IEEE.