diff --git a/README.md b/README.md
index 3c051a1..90d54db 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ If you would like to add a "bug in the wild" or a "common vulnerability", there
9. [PlonK: Frozen Heart](#plonk-1)
10. [Zcash: Trusted Setup Leak](#zcash-1)
11. [MiMC Hash: Missing Constraint](#mimc-1)
+ 12. [PSE & Scroll zkEVM: Missing Constraint](#zkevm-1)
#### [Common Vulnerabilities](#common-vulnerabilities-header)
1. [Under-constrained Circuits](#under-constrained-circuits)
@@ -553,6 +554,68 @@ outs[0] <== S[nInputs - 1].xL_out;
1. [TornadoCash Explanation](https://tornado-cash.medium.com/tornado-cash-got-hacked-by-us-b1e012a3c9a8)
2. [Actual Github Fix](https://github.com/iden3/circomlib/pull/22/files)
+## 12. PSE & Scroll zkEVM: Missing Constraint
+
+**Summary**
+
+Related Vulnerabilities: 1. Under-constrained Circuits, 2. Nondeterministic Circuits
+
+Identified By: [PSE Security Team](https://twitter.com/PrivacyScaling)
+
+The PSE & Scroll zkEVM modulo circuit was missing a constraint, which would allow a malicious prover to create a valid proof of a false modulo operation. Since the modulo operation is a basic building block for the zkEVM, the prover could convince the verifier of a wrong state update.
+
+**Background**
+
+The PSE & Scroll zkEVM circuits are programmed using their own fork of [Zcash's Halo2](https://github.com/zcash/halo2). Small components of the large zkEVM circuit can be broken down into what are called gadgets. In this case, the modulo gadget was missing a constraint.
+
+The Modulo gadget is intended to constrain:
+
+```jsx
+a mod n = r, if n!=0
+r = 0, if n==0
+```
+
+The prover must supply `a, n, r, and k`, where they are all less than `2^256`. The Modulo gadget uses the MulAddWords gadget which constrains:
+
+```jsx
+a * b + c == d (modulo 2**256)
+```
+
+And the prover must supply `a, b, c, and d`. So the Modulo gadget inputs `k, n, r, a` for `a, b, c, d`. This creates the following constraint:
+
+```jsx
+k * n + r == a (modulo 2**256)
+```
+
+This constraint is intended to prove that `r = a mod n`.
+
+**The Vulnerability**
+
+The vulnerability arises from the fact that the MulAddWords gadget is done modulo `2^256` and that `k * n + r` can also be greater than `2^256`. This is because even though `k, n, r` are all less than `2^256`, their multiplication and sum can be greater than that. Since the prover can manipulate `k` freely for a given `n, r and a`, the prover can use `k` to overflow the sum and get a successful modulo operation.
+
+For example, let:
+
+```jsx
+n = 3
+k = 2^255
+r = 0
+a = 2^255
+```
+
+The statement `0 = 2^255mod3` is false. But this statement will prove successfully in the circuit. This is because this is the actual constraint that is checked (which is true in this case):
+
+`3 * 2^255 + 0 = 2^255 (mod 2^256).`
+
+Since the prover can prove these false modulo operations, they can convince the verifier of incorrect state updates that rely on these operations. The modulo operation is a basic building block of the zkEVM, so there are many possible incorrect state updates that a prover can make that will succesfully be verified.
+
+**The Fix**
+
+The fix for this issue is to add another constraint forcing `k * n + r` to be less than `2^256` so that no overflows happen. This is enough to avoid the overflow and accurately prove that `r = a mod n` for any `r, a, and n` less than `2^256`.
+
+**References**
+
+1. [Github Issue](https://github.com/privacy-scaling-explorations/zkevm-circuits/issues/996)
+2. [Commit of the Fix](https://github.com/privacy-scaling-explorations/zkevm-circuits/pull/999)
# Common Vulnerabilities