Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Potential Smart Contract Range Check #2

Open
sebastiantf opened this issue Feb 20, 2024 · 3 comments
Open

[WIP] Potential Smart Contract Range Check #2

sebastiantf opened this issue Feb 20, 2024 · 3 comments

Comments

@sebastiantf
Copy link
Collaborator

sebastiantf commented Feb 20, 2024

Description

Came across a few bugs while looking at some bugs reported in https://github.com/0xPARC/zk-bug-tracker that are similar:

Essentially the smart contracts used with the projects seem to be missing range checks for public inputs to ensure they're less than the SNARK_SCALAR_FIELD , since uint256 values in Solidity could overflow the field and cause issues

uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;

Wondering if similar checks should be present in the Summa contracts where uint256 public inputs are used like:

and possibly others.

This is just an initial observation and need more work & help to validate/invalidate this. Nevertheless documenting it here

PS: Semaphore has since changed their logic to have no stark restrictions on groupIds. But the other codebases listed above still seem to use such range checks

@0xnirlin
Copy link
Collaborator

I think there could be an issue with the public input and root, both of them will be hashes, probably bytes 32 hashes converted into uint256, now I don't know how are these values further handled but the hash converted into uint256 may cross this value

uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;

Run this simple code

Screenshot 2024-02-21 at 2 15 58 AM

@flyingnobita
Copy link
Collaborator

These values are being inputs to submitCommitment() and verifyInclusionProof(), both in Summa.sol

For submitCommitment(), the contract simply acts as an immutable storage for these submitted values. They are read for off-chain verification of exchange liabilities thus they aren't being computed or have risk of overflow in the contract.

For verifyInclusionProof(), the solidity verifier, InclusionVerifier.sol, is generated by halo2-solidity-verifier from MstInclusionCircuit (in circuits\merkle_sum_tree.rs). This circuit contain the RangeCheck chip that we've been looking at. So I don't think further range check is necessary in Summa.sol.

@sebastiantf
Copy link
Collaborator Author

The values submitted & stored in the submitCommitment() are being checked against the inputs in verifyInclusionProof():

require(
commitments[timestamp].mstRoot == publicInputs[1],
"Invalid MST root"
);
for (uint i = 2; i < publicInputs.length; i++) {
require(
commitments[timestamp].rootBalances[i - 2] == publicInputs[i],
"Invalid root balance"
);
}

In the zkDrops contract, nullifierHash is being range checked even if it is being fed into the verifier contract that is also generated based on the circuits: https://github.com/a16z/zkdrops/blob/a4e58bdad8391ffc133c3643c449be5d18b69832/zkdrops-contracts/contracts/PrivateAirdrop.sol#L38-L46
Screenshot 2024-02-27 at 11 55 27 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants