🌊Arithmetic Over/Under Flows
Zk cryptography often involves modular arithmetic over a scalar field. This means that all operations are done modulo the order of the field. Circom circuits are built over a scalar field with the following order:
It’s easy to forget this fact, and not account for over/under flows. This means that the following arithmetic statements are true in Circom:
This can cause unintended consequences if there are no checks preventing these patterns.
Attack Scenario
For example, consider the following circuit that computes a user’s new balance:
If a user inputs a withdrawAmount
that is greater than their currentBalance
, the newBalance
output will underflow and will be an extremely large number close to p
. This is clearly not what was intended by the circuit writer.
The fix
We can use the LessThan
and Num2Bits
templates defined by Circomlib to ensure the values we are working with are within the correct bounds, and will not cause overflows or underflows:
Here, Num2Bits(n)
is used as a range check to ensure that the input lies in the interval [0, 2^n)
. In particular, if n
is small enough this ensures that the input is positive. If we forgot these range checks a malicious user could input a withdrawAmount
equal to p - 1
. This would satisfy the constraints defined by LessThan
as long as the current balance is non-negative since p - 1 = -1 < currentBalance
.
Last updated