75249 sc medium rc 28 zk interval mismatch prevents dual proof fast finality
#75249 [SC-Medium] rc.28 ZK interval mismatch prevents dual-proof fast finality
Submitted on Apr 28th 2026 at 01:57:48 UTC by @cgdusek for Audit Comp | Base Azul
Report ID: #75249
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/base/contracts/tree/v8.1.0/src/multiproof
Impacts:
Temporary freezing of funds for at least 24 hours (e.g., stuck withdrawal proofs, locked dispute game bonds)
Description
Vulnerability Report
Selected fields
program:
Base Azulcategory:
Smart Contractsupporting assets:
base/base v0.8.0-rc.28for the ZK proof-service root causebase/contract-deploymentsfor Base Sepolia deployment constants
impact:
High: Temporary freezing of funds for at least 24 hours (e.g., stuck withdrawal proofs, locked dispute game bonds)title:
rc.28 ZK interval mismatch prevents dual-proof fast finality
Executive summary
base/base v0.8.0-rc.28 hardcodes OP-Succinct's DEFAULT_INTERMEDIATE_ROOT_INTERVAL=10 when generating ZK witnesses, while the active Base Sepolia Azul type-621 AggregateVerifier is configured with INTERMEDIATE_BLOCK_INTERVAL=30.
For a 30-block challenge or full proposal proof, the ZK program commits a journal containing 10-block intermediate roots, but the contract verifies a journal containing 30-block roots. The valid ZK proof therefore cannot match the onchain journal needed to add the second proof, leaving games on the single-proof 604800 second path instead of the dual-proof 86400 second path and adding 518400 seconds of finality delay.
Classification and scope justification
Exact program criteria match
asset name(s) exactly as listed on scope page:
Smart Contract - base/contracts v8.1.0 src/multiproofselected;Blockchain/DLT - base/base v0.8.0-rc.28andSmart Contract - base/contract-deploymentsas supporting evidence assetsspecific scoped asset(s) supporting this severity claim:
selected Smart Contract asset
base/contracts v8.1.0 src/multiproofcarries the finality/withdrawal-delay impactsupporting
base/base v0.8.0-rc.28carries the ZK proof-service root causesupporting
base/contract-deploymentscarries Base Sepolia deployment constants
exact current Immunefi scope picker URL(s) supporting this severity claim:
Audit Comp | Base Azul scope, checked
2026-04-28
selected online form category:
Smart Contractselected online form asset:
base/contracts v8.1.0 src/multiproofexact current Immunefi scope picker URL for selected form asset: base/contracts v8.1.0 src/multiproof
selected severity from scope page:
Highselected impact title from scope page:
Temporary freezing of funds for at least 24 hours (e.g., stuck withdrawal proofs, locked dispute game bonds)exact scope wording:
Runnable PoC Required; the scope page listsOffchain Components,Base Azul, andImplementation Contracts; the online form requires theSmart Contractcategory to select the temporary-freezing-of-funds impact, so this submission selects the multiproof contract asset that realizes the finality/withdrawal delay while retainingbase/base v0.8.0-rc.28as the supporting root-cause assetscope page last checked:
2026-04-28why this matches the demonstrated consequence: the PoC proves an additional
518400seconds of finality delay for games that cannot receive the ZK second proof, which exceeds 24 hours and directly affects withdrawal proof readiness and dispute game bond finality.
Why higher or adjacent criteria do not fit
closest higher severity criterion considered:
Forging or bypassing TEE or ZK proof verification in AggregateVerifier to finalize an invalid state root on L1why the report does not satisfy it: this report proves valid ZK proof unusability caused by a journal mismatch. It does not prove verifier bypass, forged proof acceptance, finalized invalid state, direct bridge theft, or permanent freezing.
closest adjacent same/lower criteria considered:
Circumventing the dispute/challenge mechanism to prevent correction of an invalid proposal before finalizationPermanent freezing of funds in the bridge or in dispute game bonds with no available recovery pathTemporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments
why the selected criterion fits better: the proven effect is a time-bounded finality delay for proofs, withdrawals, and dispute-game bonds. It is not a chain-transaction halt, an invalid-state finalization path, or a no-recovery permanent freeze.
Out-of-scope exclusion check
relevant out-of-scope exclusions reviewed: compromised Base-operated infrastructure, relying on invalid TEE/ZK proofs, assuming Base will not dispute/blacklist/retire invalid proposals, assuming services will not be restarted with different configuration, out-of-scope
base/basefolders, and core Op-Succinct/circuit root causes.excluded assumptions not used by this exploit: the PoC does not require leaked keys, privileged addresses, signer compromise, public testnet writes, mainnet writes, invalid proof acceptance, governance action, sequencer behavior, or a claim that Base cannot manually restart services. The report is limited to the release-pinned rc.28 integration mismatch and its deployed AggregateVerifier finality consequence.
Finding details
Public documentation invariant
Public evidence checked on 2026-04-27:
The live Audit Comp | Base Azul scope page lists
Offchain Components,Base Azul, andImplementation Contractsas in-scope assets; marks the competition as requiring a runnable PoC; identifies proof-system integration, TEE/ZK dispute game submission logic, verifier contract bugs, and ZK recursion soundness as primary concerns; and explains that Base Azul replaces optimistic fault proofs with a TEE + ZK dual-proof system for faster finality.The same live scope page states that the competition environment is Base Sepolia post-April 20 Azul activation, that public Base mainnet is not in scope, and that the core Op-Succinct program is out of scope while Base changes around it are in scope.
The Base V1 proof documentation defines a long
7 dayssettlement path for TEE-only or ZK-only proposals and a short1 daypath when TEE and ZK both back the same proposal.The same V1 documentation describes ZK provers as the permissionless proving backend, including dispute/backstop use.
AggregateVerifierhashes the contract-supplied intermediate roots into the ZK verifier journal in_verifyZkProof(), and its delay logic uses1 daysfor the fast path and7 daysfor the slow path.
The resulting invariant is inference-backed from the linked public docs and source: a valid rc.28 ZK proof generated for the active contract interval must commit the same intermediate-root vector that AggregateVerifier hashes into the verifier journal. This vulnerability breaks that invariant because the rc.28 proof service records 10-block roots while the active contract verifies 30-block roots. The trust boundary is narrow: the report does not assume the common proposer path must start with ZK, and it does not rely on core Op-Succinct or circuit bugs; it relies on Base's in-scope rc.28 integration passing the contract interval consistently into the proof-service journal.
Root cause
OpSuccinctProvider::generate_witness() calls get_sp1_stdin() with DEFAULT_INTERMEDIATE_ROOT_INTERVAL, and that constant is 10. The challenge driver sets number_of_blocks_to_prove from the candidate's contract interval, but the ProveBlockRequest has no field for the intermediate-root recording interval, and build_zk_request() cannot pass it.
The range client records an intermediate root whenever blocks_processed.is_multiple_of(interval) in advance_to_target(). The aggregation program then concatenates all range intermediate roots and commits the packed digest in aggregation/src/main.rs.
Strongest demonstrated exploit path
A type-621 AggregateVerifier game is created with
INTERMEDIATE_BLOCK_INTERVAL=30.A permissionless ZK proof is requested as the second proof needed for the fast-finality path.
For a full 600-block proposal proof, the contract-side journal contains
600 / 30 = 20intermediate roots, while rc.28 records600 / 10 = 60roots because the proof service usesDEFAULT_INTERMEDIATE_ROOT_INTERVAL=10.The same source-level mismatch also applies to a 30-block challenge subrange (
3rc.28 roots versus1contract root), but the runnable artifact anchors the full-proposal second-proof path._verifyZkProof()hashes the contract-side root vector into the ZK journal and callsZK_VERIFIER.verify. A proof generated for the rc.28 10-block journal is rejected under the onchain 30-block journal.Without the second proof,
_getDelay()keeps the game on theSLOW_FINALIZATION_DELAYpath and_getDelay()returns 7 days for one proof and 1 day for two proofs.
PoC-backed proof chain
The PoC package at the secret gist generates two real SP1 Groth16 proofs for an equivalent aggregate-journal program, then verifies them through release-pinned Base ZkVerifier code. It prints:
POC_RESULT: REAL_ZK_PROOF_SYSTEM=SP1 Groth16POC_RESULT: SP1_PROGRAM_VKEY_BYTES32_FORMAT=truePOC_RESULT: PUBLIC_SEPOLIA_ZK_AGGREGATE_HASH_BYTES32_FORMAT=truePOC_RESULT: PROGRAM_VKEY_DIFFERS_FROM_PUBLIC_SEPOLIA=truePOC_RESULT: ONCHAIN_SP1_PROOF_BYTES_PRESENT=truePOC_RESULT: RC28_SP1_PROOF_BYTES_PRESENT=truePOC_RESULT: SP1_CONTRACTS_COMMIT_MATCH=truePOC_RESULT: BASE_CONTRACTS_COMMIT_MATCH=truePOC_RESULT: ZK_VERIFIER_ONCHAIN_PROOF_ACCEPTED=truePOC_RESULT: ZK_VERIFIER_RC28_PROOF_ACCEPTED_WITH_RC28_JOURNAL=truePOC_RESULT: ZK_VERIFIER_RC28_PROOF_ACCEPTED_WITH_ONCHAIN_JOURNAL=falsePOC_RESULT: ZK_VERIFIER_PUBLIC_SEPOLIA_VKEY_ACCEPTED=falsePOC_RESULT: FULL_PROPOSAL_ONCHAIN_ROOT_COUNT=20POC_RESULT: FULL_PROPOSAL_RC28_ROOT_COUNT=60POC_RESULT: FULL_PROPOSAL_DIGESTS_EQUAL=falsePOC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_SECONDS=518400POC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_GE_24H=truePOC_RESULT: INTERVAL_MISMATCH_PROVEN=truePOC_RESULT: HIGH_TEMPORARY_FREEZE_CANDIDATE=true
PoC setup conditions
The PoC runs in an isolated reviewer environment. It does not call RPC, deploy to a public network, submit transactions, use privileged addresses, or depend on a public network fork. It clones release-pinned base/contracts v8.1.0, generates two SP1 Groth16 proofs during execution for the aggregate-journal shape, deploys the release-pinned SP1 Groth16 verifier and Base ZkVerifier inside Foundry execution, and checks the rc.28 proof rejection under the onchain 30-block journal.
Meaning of valid ZK proof in this report
Within the public-boundary PoC, valid ZK proof means verifier-valid under the same vkey type and verifier interface used by the scoped Base contracts:
The proof bytes are generated by SP1 Groth16 for a concrete aggregate-journal program and concrete public inputs.
The public journal is the
AggregateVerifierZK journal shape:proposer,l1OriginHash, starting and ending roots, starting and ending L2 sequence numbers, intermediate roots,CONFIG_HASH, andZK_RANGE_HASH.The vkey is a
bytes32SP1 program verification key passed to the release-pinned upstreamZkVerifier.verify(proofBytes, imageId, journal)path, the same Solidity type and verifier interface used for Base Sepolia'sZK_AGGREGATE_HASH.The release-pinned upstream
ZkVerifieraccepts each proof when the proof is paired with the journal it proves.The rc.28 proof is rejected when paired with the onchain 30-block journal, which is the contract journal needed for the second proof.
The vkey has the same encoding, Solidity type, and verification-call semantics as the public Sepolia aggregate vkey. The difference is the vkey value, which identifies an equivalent aggregate-journal SP1 program rather than Base Sepolia's deployed aggregate program. This report does not use valid to mean accepted by Base Sepolia's deployed aggregate vkey. Proving that deployment-specific condition would require Base's production aggregate SP1 program and proving inputs that produce proof bytes verifying against public Sepolia's ZK_AGGREGATE_HASH.
Exploit preconditions
The active AggregateVerifier remains configured with
INTERMEDIATE_BLOCK_INTERVAL=30.A participant attempts to use rc.28's ZK proof service as the permissionless ZK dispute/backstop path or as the second proof path for fast finality.
The proof must be generated honestly; the failure is a journal mismatch, not an invalid-proof bypass.
The issue is operator-remediable by redeploy/code config, not user-remediable by existing runtime configuration: the active contract interval is immutable deployment configuration, while rc.28's proof request path does not expose an intermediate-root interval that a participant can set.
Deployment and in-scope surface
The active rc.28 source is base/base v0.8.0-rc.28 at commit e3467a2048881213b56739a54a876efb9c6ea103, matching the Immunefi mid-contest update to the rc.28 tree. Deployment material shows BLOCK_INTERVAL=600, INTERMEDIATE_BLOCK_INTERVAL=30, and PROOF_THRESHOLD=1 in the multiproof activation environment, and the later AggregateVerifier redeploy script preserves the existing verifier, hashes, intervals, and threshold with post-checks for the same values at lines 99-109.
Read-only Base Sepolia checks on 2026-04-27 found the active type-621 implementation at 0xF3f0fA3124b7b0feB048A00404Fe4D5D49E60796, INTERMEDIATE_BLOCK_INTERVAL=30, BLOCK_INTERVAL=600, PROOF_THRESHOLD=1, ZK_VERIFIER=0xF9780104117C0FaD3A9b1386FbF40a9F5857988A, and no pause on the respected game type. OptimismPortal2.checkWithdrawal() depends on anchorStateRegistry.isGameClaimValid() before finalization, and AnchorStateRegistry.isGameClaimValid() requires the game to be finalized and defender-won at lines 311-335.
Fresh public-source and Base Sepolia checks on 2026-04-28 did not identify a public fix in the current public base/base main branch and confirmed the mismatch is still present in the testnet competition environment. The latest public main commit checked was 4b389f03b4963ec7bbb4d024445af6281a90d9a8; at that commit, OpSuccinctProvider::generate_witness() still passes DEFAULT_INTERMEDIATE_ROOT_INTERVAL into get_sp1_stdin(), the public ProveBlockRequest still has no intermediate-root interval field, and the default interval remains 10. Read-only Base Sepolia calls at block 10746130 (2026-04-28T01:32:24Z) still returned gameImpls(621)=0xF3f0fA3124b7b0feB048A00404Fe4D5D49E60796, INTERMEDIATE_BLOCK_INTERVAL=30, BLOCK_INTERVAL=600, PROOF_THRESHOLD=1, ZK_AGGREGATE_HASH=0x0020f5df94945d8d40bc2b11128cbf2535565f5cde58960029017ee2ccef46d7, respectedGameType=621, and paused=false. This confirms the bug-relevant mismatch is still deployed on Base Sepolia, while not ruling out private unpublished fixes.
Public-known / duplicate boundary
I did not identify a public disclosure for this exact rc.28 proof-service interval mismatch. The live Immunefi page checked on 2026-04-28 lists public known issues and audit references, and states that publicly disclosed bugs or unfixed issues mentioned in prior audits are not eligible. This report is distinct from generic ZK prover/circuit issues because the root cause is the Base rc.28 integration path: the request surface cannot pass the contract's active intermediate-root interval to the proof service.
Repository, file, and line of code where finding is found
Steps to replicate
All testing was performed in an isolated reviewer-style environment. I did not use mainnet or public testnet.
secret gist: PoC gist
PoC name:
RC28IntervalMismatchRealSP1PoC
Expected high-signal output markers:
POC_RESULT: REAL_ZK_PROOF_SYSTEM=SP1 Groth16POC_RESULT: ZK_VERIFIER_RC28_PROOF_ACCEPTED_WITH_ONCHAIN_JOURNAL=falsePOC_RESULT: FULL_PROPOSAL_DIGESTS_EQUAL=falsePOC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_SECONDS=518400POC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_GE_24H=truePOC_RESULT: INTERVAL_MISMATCH_PROVEN=truePOC_RESULT: HIGH_TEMPORARY_FREEZE_CANDIDATE=true
Impact of finding
Short term
Permissionless ZK backing for active 30-block dispute/proposal intervals cannot supply the second proof that shortens finality from 604800 seconds to 86400 seconds. Affected games remain in the one-proof path for an additional 518400 seconds, delaying withdrawal finalization and dispute-game bond finality by more than 24 hours.
Long term
If rc.28 is used as the ZK proof-service path without an interval fix, the ZK backstop/fast-finality lane remains unusable for the active interval. This report does not claim permanent freezing, invalid state finalization, direct theft, or total network shutdown.
Mitigation suggestions
Add an explicit intermediate-root interval field to
ProveBlockRequestand populate it from the candidate/onchainINTERMEDIATE_BLOCK_INTERVAL.Refuse to submit a ZK proof when the generated intermediate-root count does not match the target AggregateVerifier's expected interval.
Add regression tests for 30-block challenge proofs and 600-block full proposal proofs where the ZK service and AggregateVerifier journal digests must match.
As an operational mitigation boundary, treat this as operator-remediable by redeploy/code config, not user-remediable by existing runtime configuration.
Optional suggested patch
Treat DEFAULT_INTERMEDIATE_ROOT_INTERVAL only as a fallback for standalone tests. Production proof requests should carry the onchain interval through the challenger, prover API, witness-generation call, and aggregation input.
Comparable public incidents
Not used. This report is source and PoC driven.
References
Runnable PoC package
secret gist: PoC gist
PoC name:
RC28IntervalMismatchRealSP1PoC
Live deployment / release confirmation
Audit Comp | Base Azul scope, checked
2026-04-28Audit Comp | Base Azul information, checked
2026-04-28
Relevant code paths
Scope / rules
Public protocol documentation
Additional context / provenance
Base Azul information page, checked
2026-04-28
Submission notes
selected scope criterion:
High - Temporary freezing of funds for at least 24 hours (e.g., stuck withdrawal proofs, locked dispute game bonds)online form category:
Smart Contractonline form asset picker selection:
base/contracts v8.1.0 src/multiproofspecific scoped assets carrying the claim:
selected
base/contracts v8.1.0 src/multiproofSmart Contract asset forAggregateVerifier,AnchorStateRegistry, andOptimismPortal2finality/withdrawal impactsupporting
base/base v0.8.0-rc.28ZK proof servicesupporting
base/contract-deploymentsBase Sepolia Azul type-621 deployment constants
severity anchor:
518400additional seconds of finality delay, exceeding 24 hoursbreadth-only variant: the 30-block challenge path has the same interval mismatch by source/code path; the runnable severity anchor is the full 600-block proposal second-proof path
explicitly not claiming: Critical proof forgery/bypass, finalized invalid state, direct theft, permanent freezing, chain shutdown, public-network exploitation, or invalid proof reliance
Link to Proof of Concept
https://gist.github.com/cgdusek/43cde38ec160412f84fa5eaf687f8181
Proof of Concept
PoC Specification
Command
Run from the secret gist root after downloading the gist files into one directory. The command performs an isolated reviewer-environment execution. It requires forge, Rust/Cargo, protoc, Go, outbound internet for first-run source/tool/circuit downloads, and enough disk and memory for SP1 Groth16 proving. It does not require SEPOLIA_RPC_URL, a wallet, a private key, a funded account, public-network writes, or an external proof fixture.
Version Gate
The runner prints and enforces:
POC_RESULT: BASE_BASE_SCOPE_TAG=v0.8.0-rc.28POC_RESULT: BASE_BASE_SCOPE_COMMIT=e3467a2048881213b56739a54a876efb9c6ea103POC_RESULT: BASE_CONTRACTS_TAG=v8.1.0POC_RESULT: BASE_CONTRACTS_COMMIT_EXPECTED=01dad230390cd69bcf130b5fc7a7a580b31650a7POC_RESULT: BASE_CONTRACTS_COMMIT_MATCH=truePOC_RESULT: SP1_VERSION=v6.1.0POC_RESULT: SP1_CONTRACTS_COMMIT_MATCH=true
What the runner does
Embedded PoC code for automated triage
The authoritative executable files are included in poc/ and in the secret gist. These hashes identify the exact source snapshot used by this specification:
poc/run_poc.shSHA-256:
8f88582fc9887b061a8076bb6495dfe6fe255a9eeb72ee5e5a9ed8e1af04211d
poc/RC28IntervalMismatchRealSP1PoC.t.solSHA-256:
15d48d80e2e11547f73522285cde661586017be6f71653fa38fef493106fde74
poc/README.mdSHA-256:
f8c80c492d933df89cd9e41714c53e4abba8998f110fc7cb6a165706b061f9ac
poc/OUTPUT.txtSHA-256:
e2cddf122430495ca508ebd08bb9c880dc0ad55e1837139cf059da57dae2b30a
Expected markers
POC_RESULT: REAL_ZK_PROOF_SYSTEM=SP1 Groth16POC_RESULT: SP1_PROGRAM_VKEY_BYTES32_FORMAT=truePOC_RESULT: PUBLIC_SEPOLIA_ZK_AGGREGATE_HASH_BYTES32_FORMAT=truePOC_RESULT: PROGRAM_VKEY_DIFFERS_FROM_PUBLIC_SEPOLIA=truePOC_RESULT: FULL_PROPOSAL_ONCHAIN_ROOT_COUNT=20POC_RESULT: FULL_PROPOSAL_RC28_ROOT_COUNT=60POC_RESULT: FULL_PROPOSAL_ONCHAIN_PACKED_LEN=836POC_RESULT: FULL_PROPOSAL_RC28_PACKED_LEN=2116POC_RESULT: FULL_PROPOSAL_DIGESTS_EQUAL=falsePOC_RESULT: ONCHAIN_SP1_PROOF_BYTES_PRESENT=truePOC_RESULT: RC28_SP1_PROOF_BYTES_PRESENT=truePOC_RESULT: SP1_CONTRACTS_COMMIT_MATCH=truePOC_RESULT: BASE_CONTRACTS_COMMIT_MATCH=truePOC_RESULT: ZK_VERIFIER_ONCHAIN_PROOF_ACCEPTED=truePOC_RESULT: ZK_VERIFIER_RC28_PROOF_ACCEPTED_WITH_RC28_JOURNAL=truePOC_RESULT: ZK_VERIFIER_RC28_PROOF_ACCEPTED_WITH_ONCHAIN_JOURNAL=falsePOC_RESULT: ZK_VERIFIER_PUBLIC_SEPOLIA_VKEY_ACCEPTED=falsePOC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_SECONDS=518400POC_RESULT: ADDITIONAL_WITHDRAWAL_FREEZE_GE_24H=truePOC_RESULT: INTERVAL_MISMATCH_PROVEN=truePOC_RESULT: HIGH_TEMPORARY_FREEZE_CANDIDATE=trueSuite result: ok. 1 passed; 0 failed; 0 skipped
AWS fresh run
The current poc/OUTPUT.txt was produced by executing bash run_poc.sh on 2026-04-27 on an AWS r7i.16xlarge on-demand VM in us-east-1, using the included aws_spot_test.sh helper with a 350 GB root volume. The helper copied the flat PoC package to a temporary remote working directory, executed the reviewer command, preserved OUTPUT.txt, and terminated the instance.
Key observed markers from that run:
Meaning of valid ZK proof
For this PoC, a ZK proof is valid when all of the following are true:
SP1 Groth16 generated the proof bytes for the aggregate-journal program used by the runner.
The public journal has the same field order and hash preimage shape consumed by upstream
AggregateVerifier._verifyZkProof(...).The vkey is a
bytes32SP1 program verification key passed to the release-pinned upstreamZkVerifier.verify(proofBytes, imageId, journal)path, the same Solidity type and verifier interface used for Base Sepolia'sZK_AGGREGATE_HASH.The release-pinned upstream Base
ZkVerifier.verify(...)call accepts(programVKey, journal, proofBytes)through the Succinct SP1 Groth16 verifier contract.No mock verifier, signer registration, privileged registry mutation, or verification bypass is used.
The onchain-interval proof and rc.28 proof each verify when paired with the journal they prove.
This definition is bounded by the public artifacts available to the PoC. The vkey has the same encoding, Solidity type, and verification-call semantics as Base Sepolia's public aggregate vkey. The difference is the vkey value, which identifies an equivalent aggregate-journal SP1 program rather than Base Sepolia's deployed aggregate program. This definition does not assert that these proof bytes verify against Base Sepolia's deployed aggregate vkey. Removing that boundary requires production aggregate proof material for public Sepolia's ZK_AGGREGATE_HASH.
Production boundary
The runner intentionally does not use a production fork gate because public artifacts do not provide proof material for Base Sepolia's configured aggregate vkey. The PoC uses real SP1 Groth16 proofs for an equivalent aggregate-journal program and wires them through the release-pinned upstream Base ZkVerifier path.
This boundary is explicit in the output:
The primary path is ZK-only and verifies real SP1 proof bytes through the release-pinned upstream Base ZkVerifier path.
Network safety
The runner does not broadcast transactions and does not interact with public network state. All verifier calls occur inside Foundry execution. It does not require SEPOLIA_RPC_URL, wallet material, a funded account, or a fork block.
What is not proven
This is not a public testnet or mainnet broadcast.
This is not a production fork proof.
This is not proof material for Base Sepolia's configured aggregate vkey.
This is not a forged-proof, bridge-loss, invalid-state-root-finalization, permanent-freeze, or chain-shutdown claim.
Was this helpful?