Constraint Mistakes
Errors in circuit constraints.
Underconstrained signals
criticalSignals that do not appear in any constraint let provers choose arbitrary values. This breaks the entire proof.
Impact: Prover can generate valid proofs for any output regardless of actual inputs.
Fix: Audit every signal. Each must appear in at least one constraint or be derived from constrained values.
Missing boolean constraints
criticalTreating a signal as boolean without constraining it to 0 or 1. Field elements have many other values.
Impact: Prover can use non-boolean values, breaking conditional logic.
Fix: Always add `signal * (signal - 1) === 0` for any boolean signal.
Forgetting to constrain array indices
highArray lookups where the index is not constrained to valid range.
Impact: Out-of-bounds access can leak information or cause unexpected behavior.
Fix: Add range checks for all array indices.
Incomplete Merkle proof verification
criticalNot constraining every step of Merkle path or getting left/right ordering wrong.
Impact: Invalid proofs accepted. Non-existent leaves proven to exist.
Fix: Verify each hash step. Test with known roots.
Arithmetic Mistakes
Finite field arithmetic errors.
Field overflow assumptions
criticalAssuming arithmetic works like integers. Field arithmetic wraps at the modulus.
Impact: Large numbers wrap to small numbers. Comparisons break. Security assumptions fail.
Fix: Add range checks. Be explicit about field size assumptions.
Division by zero
highNot checking that denominators are non-zero before division.
Impact: Undefined behavior. Prover might be able to exploit edge cases.
Fix: Constrain denominators to be non-zero.
Square root non-uniqueness
highField elements have two square roots. Not specifying which one is expected.
Impact: Prover can use either root, potentially breaking logic.
Fix: Constrain which square root by adding sign or range constraints.
Bit decomposition reconstruction mismatch
highDecomposing to bits but not constraining that bits reconstruct to original value.
Impact: Bits do not represent the actual value. Proofs become meaningless.
Fix: Always add reconstruction constraint: sum of bits * powers of 2 == original.
Cryptographic Primitive Mistakes
Errors using hashes and signatures.
Unconstrained hash inputs
criticalHash inputs that are not fully constrained allow hash manipulation.
Impact: Prover can adjust unconstrained inputs to produce desired hash.
Fix: Every hash input must be fully constrained by circuit logic.
Partial signature verification
criticalVerifying only part of a signature or not including the message.
Impact: Signature forgery. Proofs for unauthorized actions.
Fix: Complete signature verification including message binding.
Non-deterministic nullifier derivation
criticalNullifiers that can be computed multiple ways for the same underlying item.
Impact: Double-spending. Same asset used multiple times with different nullifiers.
Fix: Nullifier derivation must be deterministic and unique.
Invalid curve point acceptance
highNot validating that public keys are valid points on the curve.
Impact: Invalid keys can cause signature verification to misbehave.
Fix: Validate all external curve points are on the correct curve and subgroup.
Setup and Verification Mistakes
Errors in proof system setup and verification.
Single-party trusted setup
criticalUsing setup parameters generated by one party. That party can create fake proofs.
Impact: Setup generator can forge proofs for any statement.
Fix: Use multi-party ceremonies (Powers of Tau) for trusted setup.
Reusing proving keys across circuits
criticalUsing the same proving key for different circuits.
Impact: Proofs from one circuit might be valid for another, breaking security.
Fix: Each circuit requires its own setup. Never reuse keys.
Public input ordering mismatch
criticalPublic inputs ordered differently between prover and verifier.
Impact: Verification succeeds for wrong values. Proofs prove wrong things.
Fix: Strict public input ordering. Test prover/verifier integration.
Missing replay protection
highProofs that can be replayed to repeat an action.
Impact: Same proof used multiple times. Actions repeated unintentionally.
Fix: Include nonces, timestamps, or nullifiers in public inputs.
Application Integration Mistakes
Errors connecting ZK proofs to applications.
Proof not bound to action
highProof proves something but does not specify what action it authorizes.
Impact: Proof generated for one action used to authorize another.
Fix: Include action identifier in public inputs.
Not storing used nullifiers
criticalAccepting proofs without recording their nullifiers.
Impact: Same proof used repeatedly. Double-spending.
Fix: Store all spent nullifiers. Check before accepting proofs.
Client-generated proofs without validation
highAccepting proofs from clients without validating the public inputs make sense.
Impact: Malicious clients submit proofs with manipulated public inputs.
Fix: Validate public inputs server-side independent of the proof.
Performance and Implementation Mistakes
Errors causing inefficiency or bugs in production.
Unnecessary constraint multiplication
mediumUsing multiplications in constraints where additions suffice.
Impact: Proving time increases significantly. Higher costs.
Fix: Optimize constraint degree. Use linear constraints when possible.
No witness generation timeout
mediumWitness computation without time limits can hang indefinitely.
Impact: Malicious inputs cause denial of service. Provers hang.
Fix: Timeout on witness generation. Validate input complexity.
Inconsistent endianness
highMixing big and little endian in bit operations.
Impact: Values computed incorrectly. Proofs verify wrong data.
Fix: Standardize endianness across all operations. Document clearly.
Memory exhaustion on large inputs
mediumCircuits that allocate based on input size without limits.
Impact: Large inputs crash prover. Denial of service.
Fix: Fixed maximum input sizes. Validate before circuit execution.
Debug code in production circuits
mediumLeaving console logs or debug constraints in deployed circuits.
Impact: Information leakage. Unnecessary constraint overhead.
Fix: Strip debug code for production builds. Code review.
Hardcoded test values
criticalTest private keys or constants left in production code.
Impact: Anyone can use test keys to forge proofs.
Fix: Separate test and production configurations. CI/CD checks.
Testing and Auditing Mistakes
Errors in verification and quality assurance.
Only testing happy path
criticalTesting only valid proofs without testing rejection of invalid ones.
Impact: Invalid proofs might be accepted. Soundness broken.
Fix: Test malicious inputs. Fuzz testing. Adversarial tests.
No formal verification
highRelying solely on manual review for critical circuits.
Impact: Subtle constraint bugs missed by human reviewers.
Fix: Use formal verification tools like ecne, Circomspect.
Insufficient test coverage for edge cases
highNot testing boundary values and special cases.
Impact: Edge case inputs break circuit logic.
Fix: Test min/max values. Zero values. Field boundary values.
Not testing across proof systems
mediumAssuming circuit behaves identically across Groth16, PLONK, etc.
Impact: Bugs appear only in specific proof system deployment.
Fix: Test with target proof system. Understand system differences.
Ignoring compiler warnings
highDismissing Circom or other compiler warnings as noise.
Impact: Warnings often indicate real constraint issues.
Fix: Zero-warning policy. Investigate all warnings.
Pro Tips
If in doubt, add more constraints. Under-constrained circuits are the most dangerous bugs.
Use formal verification for critical circuits. Manual review alone is insufficient.
Keep circuit complexity low. Simpler circuits are easier to audit and prove.
More for ZK Engineer
Ready to build your Web3 career?
Browse hundreds of open roles across the decentralized ecosystem.
Explore Jobs