It would have absolutely caught this!
High level, the way you should understand this bug:
- If you can spend a note using the wrong nullifier, you can double spend.
- Nullifier derivation requires the circuit to prove an EC scalar multiplication. (e.g. Y = xG)
- The particular scalar mul code nullifiers used had a vulnerability, that you lie about it. (You can put a value Z, even though Z != xG)
Now the formal verification spec would assert the high level statement:
"If this circuit is satisfied, then Z = xG".
That theorem could not succeed, because the formal verification language could not prove it. (its a false statement!)
The way formal verification stuff works, is its like:
Premise: All dogs that are well-trained obey commands.
Premise: All dogs that obey commands can safely go off-leash.
Premise: Any dog that can safely go off-leash is allowed in the park.
Premise: Any dog allowed in the park receives a park badge.
Premise: Woofer does not have a park badge.
Conclusion: Woofer is not well-trained.
And then the language will go produce a ton of steps to prove to you that the conclusion is either true or false. (in this case true)
It could not prove that Z = xG here, because of the missing constraint!