Research Solidity 0.8.24 Circom 2.1.6 MIT License

Memory-proof DeFi agents,
cryptographically

Inserts a Groth16 zk-SNARK Reasoning Anchor into every LLM agent-to-chain settlement path — making memory poisoning attacks in autonomous DeFi provably impossible.

Built with
Groth16
BN254
Poseidon
Solidity
Circom
rapidsnark
182ms
Proof Generation (rapidsnark)
276K
Gas On-Chain Verification
3,800
R1CS Constraints
9.7x
Gas Reduction vs zkML
The problem

Memory poisoning bypasses key security

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.

Bypasses cryptographic keys

The attack targets the agent's reasoning inputs, not its signing key — so hardware wallets and key management provide zero protection.

Invisible at signing time

The transaction itself looks valid. The poison is in the context the agent used to decide what to sign — undetectable without verifiable inference.

Scales with agent autonomy

As agents manage larger positions and act more independently, the attack surface grows. Runtime monitoring cannot keep pace.

ZKP-RA makes it provably impossible

A Groth16 proof, verified on-chain before every settlement, cryptographically binds the transaction to unmodified reasoning inputs.

The three-step solution
1

State Commitment

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.

2

Verifiable Inference

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, σ))

3

On-Chain Settlement

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.


Architecture

Agent Guardian + On-Chain Verifier

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                             │
└────────────────────────────────────────────────────────────────┘
🐧

reasoning_anchor.circom

Groth16 circuit over BN254. Arithmetizes Poseidon state commitment and policy bounds in ~3,800 R1CS constraints. Circom 2.1.6.

circom-2.1.6 groth16 bn254 poseidon ~3,800 R1CS
🔒

Verifier.sol

On-chain Groth16 verifier with AGENT_ROLE / GUARDIAN_ROLE access control, commitment storage, nullifier replay protection, and ERC-20 safeTransfer.

solidity-0.8.24 eip-197 erc-20 access-control
🐠

agent_guardian.py

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.

python-3.10+ asyncio snarkjs rapidsnark

Circuit design

What the proof proves

The circuit arithmetizes a single, precise statement: this transaction was derived from unmodified reasoning inputs that satisfy the safety policy.

Statement proved

"I know private witnesses (X₁, S₁, I₁, r, σ) such that Poseidon(X₁∥S₁∥I₁) = H₁, the transaction satisfies amount ≤ MAX, slippage ≤ 200 bps, and Poseidon(r, σ) = routerHash."

Public inputs only

H₁, recipient, amount, slippage_bps, and routerHash are public. Context window, state vector, oracle inputs, router address, and proving salt remain private — zero information leakage.

ParameterValue
Proving systemGroth16
CurveBN254 (alt_bn128)
Hash functionPoseidon (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 inputsH₁, recipient, amount, slippage_bps, routerHash
Proof generation benchmarks
SnarkJS (WASM)
Witness:  38 ms
Prove:  1,164 ms
Total:  1,202 ms
Pure JavaScript — no native dependencies. Suitable for development and testing.
rapidsnark (C++)  RECOMMENDED
Witness:   12 ms
Prove:    170 ms
Total:    182 ms
Native C++ prover. 6.6× faster than SnarkJS. Benchmarked on AMD EPYC 9354, 128 GB DDR5.
On-Chain Gas (EVM)
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
Istanbul opcodes. 9.7× gas reduction versus full zkML inference verification.

Security properties

Cryptographic guarantees

Under q-SDH on BN254 and Poseidon collision resistance — the standard hardness assumptions for Groth16 deployments.

Completeness

An honest agent with valid witnesses always produces an accepted proof. Legitimate transactions are never blocked by the protocol.

🛡️

Soundness

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.

👁️

Zero-Knowledge

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.

🔄

Replay Protection

Each proof is bound to a nullifier ν. Once verifyAndExecute succeeds, ν is marked on-chain — the same proof cannot be submitted twice.

📋

Policy Enforcement

Amount bounds, slippage limits (≤ 200 bps), and router whitelist membership are verified inside the circuit — not just in application code — making them unforgeable.

Access Control

AGENT_ROLE and GUARDIAN_ROLE separation in the Solidity contract. Guardian can pause settlement without revoking the agent's ability to commit state.

Comparison
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

Installation

Get started

Four steps from clone to a running agent guardian with on-chain proof verification.

1. Install dependencies
git clone https://github.com/\
  sunilgentyala/ZKP-RA
cd ZKP-RA
npm install
pip install -r requirements.txt
Requires Node 20+, Python 3.10+, Circom 2.1.6, SnarkJS 0.7.4, Hardhat 2.22+.
2. Compile circuit & setup
bash scripts/compile_and_setup.sh
Downloads Hermez BN128 Phase 1 powers-of-tau, compiles to R1CS + WASM, runs Groth16 Phase 2 setup, exports verification key.
3. Deploy contract
npx hardhat compile
npx hardhat run \
  scripts/deploy.js \
  --network <network>
Update IC values in Verifier.sol with output of snarkjs vkey before deploying.
4. Run agent guardian
export AGENT_PRIVATE_KEY=0x...
python src/agent_guardian.py \
  config.json
Provide RPC URL, deployed contract address, WASM path, and zkey path in config.json.
Community

Star history

Track ZKP-RA's growth on GitHub.

Star History Chart

Support the research ⭐

A star helps cryptographers, DeFi security researchers, and AI safety engineers find this work. Companion paper in preparation — IEEE.

★  Star on GitHub Open an issue Read the docs
Author

Built by

SG
Sunil Gentyala
IEEE Senior Member  ·  Lead Cybersecurity & AI Security Consultant
HCL America Inc., Dallas TX  ·  sunil.gentyala@ieee.org