Prove a vulnerability exists without revealing how to exploit it.
⚠️ By using this software you agree to the DISCLAIMER. For authorized security research only.
Today, a white-hat researcher who discovers a vulnerability must transmit the actual exploit code to the protocol team to prove it works. If that code leaks — through a compromised inbox, a careless forward, or an insider — the protocol can be drained before a fix ships.
zkPoEX eliminates the transmission of exploit code. By allowing proof without payload, the researcher proves exploitability cryptographically while the exploit mechanics stay private. The protocol learns that a vulnerability exists and what its impact is, without ever receiving code that could be replayed.
zkPoEX executes the simulation locally and does not broadcast transactions to any live blockchain network. It only performs read-only RPC queries to fetch public chain data needed to build the proving input.
- Rust (stable)
- Foundry (for
anvilandsolc)
No prebuilt binaries are distributed. You must build from source.
curl -fsSL https://raw.githubusercontent.com/zkoranges/zkPoEX/main/install.sh | bashThis clones the repository and builds from source. On Apple Silicon it automatically enables Metal GPU acceleration. Requires git and cargo.
git clone https://github.com/zkoranges/zkPoEX
cd zkPoEX
cargo build -p zkpoex-cli --release --features <gpu>Replace <gpu> with the flag for your platform:
| Flag | Platform |
|---|---|
metal |
Apple Silicon (macOS) |
cuda |
NVIDIA GPUs |
Omit --features entirely to build without GPU acceleration.
1) Explain (interactive, generates assertions)
./target/release/zkpoex explain \
--poc pocs/sushi_router/PoC.sol \
--rpc-url https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY \
--block-number 17007838 \
--interactive \
--emit-assertions assertions.txt \
--emit-cli2) Prove (uses the saved assertions)
./target/release/zkpoex prove \
--poc pocs/sushi_router/PoC.sol \
--rpc-url https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY \
--block-number 17007838 \
--assertions assertions.txt \
-o exploit.proof3) Verify (offline, same assertions)
./target/release/zkpoex verify exploit.proof \
--assertions assertions.txtFor detailed usage, see USAGE.md. For real-world exploit walkthroughs, see pocs/README.md.
zkPoEX proofs are not claims that a historical on-chain transaction happened. They are counterfactual: a proof attests that, starting from the authenticated pre-state of a real Ethereum block, there exists a transaction that executes successfully and satisfies the public assertions you chose.
Concretely:
- The proof is bound to a real block via
block_number,chain_id, and the blockstate_root(and other env fields). - The PoC contract is injected into an overlay at
--contract-addressonly if that address is empty at the fork point (zkPoEX refuses to overwrite real chain code). - A single call to
Exploit.exploit()is executed from--callerwith the chosengas_limit. - No transaction is broadcast to mainnet: the execution happens locally inside the prover/verifier model.
- Optional "deals" can override balances inside the guest; use
--assert no-dealsto prove no balance overrides were used.
All public claims are expressed via --assert:
no-dealsbalance:ADDRESS:FROM:TOslot:ADDRESS:SLOT:FROM:TOerc20:TOKEN:OWNER:FROM:TO[:SLOT_INDEX]transfer:TOKEN:FROM:TO:AMOUNT[:SLOT_INDEX]not-owner:ADDRESS:SLOTchanged:ADDRESS(verify-only)slot-changed:ADDRESS:SLOT(verify-only)
Assertions are hash-committed inside the proof. Verification succeeds only if the verifier supplies the same assertion set (or a matching assertions.txt file).
- Host: fetches authenticated chain state, compiles PoC, orchestrates proof generation.
- Guest (ZKVM): verifies Merkle proofs, checks bytecode hash, executes EVM, commits public journal.
- Verifier: validates the receipt and checks assertion commitments against their own expectations.
pocs/— real-world exploit PoCs with minimal assertions and exact prove/verify commands.tests/fixtures/— small fixtures used by unit/integration tests.bin/zkpoex-cli/— CLI implementation.guests/— zkVM guest code.
This is a research prototype. It is designed to be useful and verifier-friendly, but it does not prove every property a verifier might wish it proved.
A verifying receipt means the zkVM guest program ran, and the guest committed the ExploitJournal included in the
receipt. Concretely, the proof attests to the following statements, as implemented by the guest:
- The guest verified EIP-1186 Merkle Patricia Trie proofs against the claimed block
state_rootfor the accounts and storage slots the proof depends on. - The guest bound execution to the block environment included in the journal (at minimum
chain_id,block_number,timestamp,basefee,block_gas_limit, andstate_root). - The PoC contract was injected at the chosen
--contract-address, and proving fails if that address is non-empty on chain at the target block (we never overwrite real chain state). - The exploit call executed inside
revmunder the derived hardfork spec for that block, from the chosen--caller. - The public
--assertset is enforced inside the guest, and the committedassertions_hashbinds the proof to the exact assertion list the verifier expects. - Deals (balance overrides) are applied inside the guest, and the committed
deals_hashbinds the proof to the exact deal list the verifier expects. - If provided,
--nonceis committed in the journal to support verifier-challenge binding and replay resistance. - If
--slowwas used, the proof can additionally commit a call-trace hash and a state-diff summary (as recorded in the journal).
These are important non-goals and sharp edges for verifiers:
- Canonical chain inclusion: the proof contains a
state_root, but it does not by itself prove that thisstate_rootis the canonical head/state for a given chain. Verifiers should independently verify the block header (and thus thestate_root) from a trusted source (for example by passing--rpc-urltozkpoex verify). - Economic meaning or intent: "execution succeeded" does not imply the behavior is malicious, unauthorized, or exploitable in the bounty sense. You must choose assertions that capture the intended impact.
- Multi-transaction / multi-block exploits: zkPoEX proves a single transaction execution of
Exploit.exploit(). It does not natively model time-delayed, multi-tx, or off-chain coordination requirements. - Completeness of impact: unless you commit a full state diff (slow mode), the verifier only learns what your chosen assertions reveal. A proof can be valid while omitting other important side effects.
- Exact client equivalence: execution uses
revm. The proof inherits any semantic mismatches or bugs inrevm(or in the fork-selection logic) relative to a real client and the target chain. - Perfect confidentiality: zk proofs hide the PoC bytecode and calldata, but the public journal fields (gas used, chosen assertions, optional state diff) can leak information. A determined verifier can sometimes infer mechanics by search or side-channel reasoning.
- zkPoEX is not a formal verification system. Its security depends on the correctness of the guest program, the host tooling, and the underlying proof system (RISC Zero) and its cryptographic assumptions.
RISC0_DEV_MODEreceipts (fake proofs) must never be treated as evidence.zkpoex verifyrejects dev-mode receipts.- No one can honestly guarantee that false proofs are impossible. The intent is that forging a proof that verifies but lies should be computationally infeasible under standard assumptions, but software vulnerabilities, integration mistakes, or future cryptographic breaks could make forgery possible.
To preserve soundness without adding heavy commitments, zkPoEX currently disallows the BLOCKHASH opcode. If a PoC
executes BLOCKHASH, proving will fail. This avoids relying on block hashes that are not authenticated by the state
root and are awkward to validate inside the circuit.
License: MIT + Strict Usage Disclaimer. See DISCLAIMER for prohibited use cases (e.g., Extortion/Ransomware).
This tool is a research artifact and experimental prototype. It is intended for academic study, authorized security testing, and the exploration of ZKVM capabilities. Users are responsible for ensuring they have permission to test any systems they target. The authors assume no liability for misuse.