Circuit artifacts
Each proof bundle contains seal-plonk.js plus a WASM witness generator, compressed compact key and verification key for each circuit: multiAssetWithdraw, multiAssetTransfer, multiAssetSettle and accountStateAction.
Local artifacts
npm run prepare:multi-asset builds deterministic development artifacts from the pinned power-19 public SRS. Compiled circuits live in build/<circuit>/; keys and the source manifest live in build/multi-asset-dev/. npm run prepare:assets installs the browser files. Scratch circuit files and full stock keys are excluded from Git. The approved compact browser bundle is retained with the release evidence.
Candidate verifier exports also stay in build/multi-asset-dev/. Preparation checks that their verification logic matches the committed verifiers in contracts/src/contracts/verifiers/production/; it never overwrites those sources. Tests, rehearsals and sandbox deployments use the committed verifiers. The stock snarkJS reference implementations remain in contracts/test/helpers/verifiers/ for differential checks.
The key format is seal-plonk-rows-v1 with zkcr magic and format version 1. Node tools consume .zkcr files. Browsers download .zkcr.gz.bin, verify its compressed digest, decompress it, and verify the expanded digest before proving. Each operation has a separate key; each manifest pins its exact size.
Production bindings
The browser manifest uses version 1, proofScheme: "plonk-bn254" and provingKeyFormat: "seal-plonk-rows-v1". It pins every file's size and SHA-256, including both compressed and expanded key bytes. The statement version is 3 (71 monetary fields or 11 account-only fields), and the initial verifier version is 0.
A production release additionally binds the reviewed setup manifest, verified SRS record, release approval record, complete circuit/tool sources, generated verifier provenance and exact compiled runtime hashes. A separate deployment record identifies the pool, registry and each operation adapter. It binds the artifact manifest digest; the artifact manifest must not contain deployment runtimes because the registry embeds that manifest digest. Registry order is settlement, transfer, withdrawal. Each adapter locks its immutable raw verifier's code hash.
A circuit-specific contribution ceremony is unnecessary for PLONK. Verification and acceptance of the universal SRS, circuits, compact prover and verifier optimizations remain necessary. Development artifacts do not become approved merely because setup is deterministic.
Client release installation
Each deployment selects a proofBundlePath, proofManifestSha256 and proofDeploymentSha256. Set VITE_CONFIG_URL to the reviewed local catalog and SEAL_NATIVE_PROOF_INDEX to a local JSON array of {manifest, bundleDirectory, deploymentRecords} entries (with deploymentRecords an array of record paths), then run npm run build:web.
The installer verifies all files, current source bindings, RPC chain identity and deployed runtimes before installing a bundle. Production status requires accepted-production, setupManifestSha256 and releaseApprovalSha256; those hashes bind records and do not authenticate human approval by themselves. After acceptance, retain the approved bundle and evidence in releases/proofs/current/ and generate its nonzero pins. This checkout has no accepted production bundle and keeps every pin zero. CI checks that this gate is coherent; npm run check:production-release -- --require-accepted additionally requires an accepted release and rejects the current unaccepted state.
Synthetic benchmarks use a separately installed PLONK bundle from prepared local assets or SEAL_BENCHMARK_BUNDLE_DIR. They cannot authorize account actions or production acceptance.
The hosted default is the sandbox. A clean build:web derives its deterministic benchmark bundle from the pinned public SRS (a roughly 604 MB setup download plus compilation/setup); subsequent builds reuse verified local artifacts. Set SEAL_BENCHMARK_BUNDLE_DIR to an existing checked bundle to avoid setup during the hosted build.
Integrity checks detect corrupt or mixed artifacts relative to trusted application configuration. They do not protect against a malicious application build. Keep the accepted configuration, source revision, toolchain and qualification results together.
Browser circuit cache
The proof worker saves verified public circuit files in seal-proof-assets-v1 using the browser Cache API. The WASM, compressed proving key, verification key and prover library are keyed by SHA-256 and size, so subsequent proofs, page reloads and other tabs on the same origin reuse identical bytes. Pinned manifests are also cached; unpinned development manifests are fetched on each proof to detect local rebuilds. Changed releases download only missing content.
Every cache hit is checked against the selected manifest before use. Corrupt entries are removed and downloaded again, and expanded proving keys are still checked after decompression. Web Locks coordinate downloads across workers where supported. No witnesses, private keys or proof inputs are stored in this cache.
The cache keeps at most 64 entries and reserves at most 512 MiB, removing the oldest entries first (each manifest reserves up to 1 MiB). A lower browser quota also evicts older proof files. Browser storage restrictions or an exhausted quota fall back to verified downloads. Clearing site data or browser eviction requires another download. The UI shows circuit loading and integrity checking separately from network downloads and proof generation.
Run node --experimental-strip-types --test scripts/tests/unit/proof-integrity.test.ts for integrity, release changes, corruption and storage-failure coverage, and npx playwright test --config apps/web/playwright.interactions.config.ts proof-cache.spec.ts for real worker/cache reuse across tabs and reloads. Regenerate public workers with node --experimental-strip-types scripts/build/build-proof-workers.ts after changing their TypeScript sources.
Margin extension deployment
For the disposable relayer rehearsal, run npm run test:relayer:e2e. All writes
target a loopback fork and temporary TLS PostgreSQL. If the default Sepolia RPC
has pruned event history, select a supported public archive provider with
SEAL_TESTNET_RPC_URL=https://sepolia.gateway.tenderly.co; the rehearsal still
checks the chain ID and recorded deployment block hash before forking.
The margin extension is qualified separately from the core pool and its proof bundle. Its production tooling requires a validated native core deployment, matching chain and pool, accepted production artifacts, qualified Aave/Uniswap bindings and a verified margin deployment manifest. A sandbox address or local rehearsal record cannot satisfy production acceptance.
Use npm run margin:preflight to inspect the selected production inputs before deployment. Use npm run margin:rehearse -- --chain ethereum --require-private or --chain base to exercise the deployment path on a local pinned Anvil fork. Rehearsals use development proofs and explicit local records; they do not broadcast to a public chain.
The production deployment tool is npm run margin:deploy. Its environment, manifest validation, runtime checks and post-deployment monitoring are maintained in scripts/deploy/margin/. Production build configuration must match the verified margin-ethereum.json or margin-base.json manifest when margin is present.
See Deployments and Margin Architecture for deployment requirements, and Audits for audit scope.