Skip to content

Commit 2d02af1

Browse files
daverogaAndriianChestnykhvolodymyr-basiukOBrezhniev
authored
V3.0.0 (#342)
* new universal verifier multi-query * Discussion results * Discussion results 2 * update universal verifier multi query * remove ZKP * add auth validators * Broader discussion results * Add agreed universal verifier solution * update universal verifier multi query with agreed design * query status and submit response * get request type from 30 byte of the requestId * add EthIdentityValidator * updates from review * Discussion result * updates from discussion * check response field values from linked response fields * fix some errors in compilation * test universal verifier multi-query * different validators for sig and authv2 * check specific storage values * overrides solidity compiler optimizations for specific contract * remove some methods * fix solhint * update from discussion * set group of requests and check linkID * fix solhint * updates from review * fix cyclomatic-complexity * some fixes from review * updates from tech spec * add auth validator stub and fix test * add changes for user authentication structs * fix solhint * reestructure link between userID and address and mapping for authentication timestamp * auth proofs different structure * add custom errors to UniversalVerifierMultiQuery * add __gap in proofs storage for future updates and array of proofs for history * param names in returned structs from solidity * Initial verifier authentication (#323) Co-authored-by: daveroga <[email protected]> * updates for iteration 2 * fix test multi-query * update verifiers tests * fix validators tests and solhint * partial changes review * override _setRequest to avoid loops and fix solhint * remove embedded zkp verifier * update Query to MultiRequest * update submitResponse * fix solhint * address centered model instead of userID and some fixes * fix solhint and custom errors * updates from review * check grouped requests 2 requests at least * fix error cyclomatic-complexity from solhint * move _state in storage * check link responses with bool * fix solhint * remove history in proofs from requests * check nullifierSessionID on request creation * fix cyclomatic-complexity in solhint * check verifierID in requests for V3 * add test for authv2 validator * Feature/pid 2720 implement linked multi query validator (#328) * WIP * WIP 2: LinkedMultiQueryValidator * Fix compilation * Fix compilation after merge * First working test * Fix after merge * New Verifier tests * fix ownable upgradeable like the other validator contracts * fix solhint compiler version >=0.7.0 <0.9.0 does not satisfy the >=0.8.4 semver requirement --------- Co-authored-by: daveroga <[email protected]> * update tests with updated stub validator * check requestId correctness * add logic from skip tests in verifier test * add auth validator stub set verify results method * idType for verifier and some updates to verifier test * fix enumerable and check existence in proof response fields * fix requestId calculation * remove specific multi-request test that now is included in verifier test * add test wrappers and tests for RequestDisableable, RequestOwnership and validatorWhitelist * increase coverage * updates from review * reorganize universal verifier tests * test all the events from universal verifier * add embedded verifier test * some fixes and increase coverage * increase coverage * Integration tests (#332) * LinkedMultiQuery small fixes * Add more linked multi query tests * Improve Linked Multi Query tests * Scaffold verifier integration-test * WIP * Fix getValidatorVerification helpers method * Fix lmk10 groth16 wrapper in constants * Remove console from Verifier.sol * Fix lmk tests * update multi-request integration test * check multi-request components exist * small general updates * fix solhint * remove VerifierLib and move functionality to Verifier * fix solhint * update missing unified addresses for validators * add test to calculate create2 proxy addresses * update test script to check unified addresses for all the contracts * fix create2Calldata statelib * update unified address for some contracts * remove ICircuitValidator references * move getters for storage data back to the beginning * resolve solhint warnings * update from review comments * update AuthV2Validator * add function getResponseFields to verifier * Remove unused tests and comments * updates from review * update requestId calculation * fix solhint * update RequestStatus for RequestProofStatus * more updates from review * more updates from review * change AuthType to AuthMethod * precalculate keccack256 of field names * solve solhint warning explicit type * fix solhint warnings * fix solhint warnings for custom errors * fix circuitId for linkedMultiQuery10-beta.1 * comment requestId calculation * v3.0.0 * remove unused verifier contracts and some renaming in fields * Remove obsolete TODO comment * fix smtlib unified address and solhint warning * Hotfix deployValidators.ts script * Fix: Check V3 query in request group (#348) * fix: patch hardhat ledger in general way + fix vulnerabilities (#344) * patch hardhat ledger in general way + fix vulnerabilities * control error in eth_accounts * fix @openzeppelin/hardhat-upgrades to version 3.0.5 * update readme for patch fix * fix upgrade safe error in universal verifier (#345) * audit fix: payERC20Permit is vulnerable to DOS via frontrunning (#347) * audit fix: payERC20Permit is vulnerable to DOS via frontrunning * bump version * Fix: check claim existence when adding a new claim (#346) * check claim existence when adding a new claim * fix solhint * update package version * update according to conventions and param for custom error * check userID in response fields * fix identityLib * fix bool * check inputIndexOf for userID at least in 1 request * fix cyclomatic-complexity in solhint * private function following conventions * check requests with and without group for userID input * fix constants for userID --------- Co-authored-by: volodymyr-basiuk <[email protected]> * Fix linkID != 0 in grouped request proofs (#349) * Fix linkID != 0 in grouped request proofs * Fix linter errors * Fix auth method enable check * Reduce optimizer runs to shrink code size * Check if auth method can be disabled by only owner * Audit: Simplify getRequestParams + setRequests front-running protection (#350) * simplify getRequestParams * protect request creation from front-running * add test InvalidRequestOwner * fix comments * check request owner in verifier and override it in universal verifier * remove unnecessary deployment cross-chain verifier script for testing * small updates * fix solhint * Adjust verification interfaces for future upgrades (#353) * add rawValue to ResponseField and update verify params * reorganize _checkRequestOwner internal method * reduce memory variables in validators verify method * Enforce groupID to be hash generated from its requestIds (#355) * add rawValue to ResponseField and update verify params * reorganize _checkRequestOwner internal method * reduce memory variables in validators verify method * calculate groupID as hash of requestIds * helper functions and groupInfo struct * Small renaming * Fix comment --------- Co-authored-by: Andriian Chestnykh <[email protected]> * Refactor Validators (#354) * Refactor Validators * Additional checks in _setGroth16Verifier() * Remove requestParamIndexOf() method * Disable initializers in all upgradeable contracts * Fix exports * Constants renaming * Renaming * Rename verifer test * Simplify _checkLinkID code * Simplify _checkRequestOwner code * Update check for groupID and linkID * Fix check-unified-addresses.test.ts * Hash based multiRequestId * Fix tests * Update Ignition modules for constant Proxy bytecode * Bump validator versions and target deploy addresses (#360) * Bump validator versions and target deploy addresses * Fix contract version * Fix naming * Clean up deployUniversalVerifier.ts * Add Eth Identity Validator deployment via ignition script * Deployment to Billions Testnet (#361) * deployment libraries to billions testnet * add chainIdInfoMap for Billions * Remove artifacts * State Contract Deployment to billions-test artifacts * State Contract Deployment to billions-test artifacts * State Contract Deployment to billions-test artifacts * update verification params for billions network * update billions main chainid --------- Co-authored-by: Andriian Chestnykh <[email protected]> Co-authored-by: Oleksandr Brezhniev <[email protected]> * Modify EthIdentityValidatorModule * EthIdentityValidator test * EthIdentityValidator to use GenesisUtils.getIdType * Remove state link from EthIdentityValidator * Get idType via GenesisUtils.getIdType(..) in V3 validator * Rename lmk to lmq * Fix linter * Fix deploy scripts for validators * Remove obsolete files after merge * Put audit report into Readme --------- Co-authored-by: Andriian Chestnykh <[email protected]> Co-authored-by: Andriian Chestnykh <[email protected]> Co-authored-by: volodymyr-basiuk <[email protected]> Co-authored-by: Oleksandr Brezhniev <[email protected]>
1 parent d6b6b25 commit 2d02af1

File tree

141 files changed

+8449
-5086
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+8449
-5086
lines changed

.openzeppelin/unknown-6913.json

Lines changed: 460 additions & 0 deletions
Large diffs are not rendered by default.

.solhintignore

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77
**/lib/VerifierStateTransition.sol
88
**/lib/VerifierV3.sol
99
**/lib/VerifierV3Wrapper.sol
10-
**/lib/groth16-verifiers/Groth16VerifierMTP.sol
11-
**/lib/groth16-verifiers/Groth16VerifierMTPWrapper.sol
12-
**/lib/groth16-verifiers/Groth16VerifierSig.sol
13-
**/lib/groth16-verifiers/Groth16VerifierSigWrapper.sol
14-
**/lib/groth16-verifiers/Groth16VerifierStateTransition.sol
15-
**/lib/groth16-verifiers/Groth16VerifierV3.sol
16-
**/lib/groth16-verifiers/Groth16VerifierV3Wrapper.sol
10+
**/lib/groth16-verifiers
1711
**/node_modules
12+

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ We have deployed contracts across the following mainnets and testnets so far (**
6060
2. [Nethermind](https://www.nethermind.io/smart-contract-audits) has performed a second security audit of our core smart contracts (State, IdentityBase, GenesisUtils, OnChainIdentity) and compiled a report on Sep 13, 2023:
6161
[NM0113-FINAL-POLYGONID.pdf](https://iden3-circuits-bucket.s3.eu-west-1.amazonaws.com/audit_reports/NM0113-FINAL-POLYGONID.pdf)
6262

63+
3. [Nethermind](https://www.nethermind.io/smart-contract-audits) has performed a third security audit of our core smart contracts (all contracts in cross-chain/*, payment/*, verifiers/* and validators/* folders) and compiled a report on Apr 4, 2025:
64+
[NM_0379_Final_PRIVADO_iD.pdf](https://iden3-circuits-bucket.s3.eu-west-1.amazonaws.com/audit_reports/NM_0379_Final_PRIVADO_iD.pdf)
65+
6366
## Deployment methodology with CREATE2 and ledger
6467

6568
Note, that this methodology is not what expected to be used by the repository users as its purpose is mainly for our team to deploy and maintain the contracts across many networks in a unified way. However, it can be used as a reference for the deployment process.

contracts/AlwaysRevert.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// SPDX-License-Identifier: GPL-3.0
22
pragma solidity 0.8.27;
33

4+
error TheContractIsDisabled();
5+
46
/// @title This contract as a dummy implementation for Proxy contract if we need to revert all calls
57
// This can be applied to disable all methods of a proxy contract with explicit error message
68
contract AlwaysRevert {
79
fallback() external payable {
8-
revert("The contract is disabled");
10+
revert TheContractIsDisabled();
911
}
1012
}

contracts/Create2AddressAnchor.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// SPDX-License-Identifier: GPL-3.0
22
pragma solidity 0.8.27;
33

4+
/* solhint-disable no-empty-blocks */
45
contract Create2AddressAnchor {}
6+
/* solhint-enable no-empty-blocks */

contracts/cross-chain/CrossChainProofValidator.sol

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import {ICrossChainProofValidator} from "../interfaces/ICrossChainProofValidator
66
import {IState} from "../interfaces/IState.sol";
77
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
88

9+
error IdentityStateProofInvalid();
10+
error GlobalStateProofInvalid();
11+
error GlobalStateProofSigningAddressInvalid(address recovered);
12+
error IdentityStateProofSigningAddressInvalid(address recovered);
13+
error OracleTimestampCannotBeInThePast();
14+
error OracleReplacedAtTimestampCannotBeInTheFuture();
15+
916
/**
1017
* @dev Contract which provides proof validation from identity state
1118
* and global state proofs from trusted oracle with signature from any network.
@@ -93,11 +100,12 @@ contract CrossChainProofValidator is Ownable, EIP712, ICrossChainProofValidator
93100
gsu.globalStateMsg,
94101
gsu.signature
95102
);
96-
require(isValid, "Global state proof is not valid");
97-
require(
98-
recovered == _oracleSigningAddress,
99-
"Global state proof signing address is not valid"
100-
);
103+
if (!isValid) {
104+
revert GlobalStateProofInvalid();
105+
}
106+
if (recovered != _oracleSigningAddress) {
107+
revert GlobalStateProofSigningAddressInvalid(recovered);
108+
}
101109

102110
return
103111
IState.GlobalStateProcessResult({
@@ -127,11 +135,12 @@ contract CrossChainProofValidator is Ownable, EIP712, ICrossChainProofValidator
127135
isu.idStateMsg,
128136
isu.signature
129137
);
130-
require(isValid, "Identity state proof is not valid");
131-
require(
132-
recovered == _oracleSigningAddress,
133-
"Identity state proof signing address is not valid"
134-
);
138+
if (!isValid) {
139+
revert IdentityStateProofInvalid();
140+
}
141+
if (recovered != _oracleSigningAddress) {
142+
revert IdentityStateProofSigningAddressInvalid(recovered);
143+
}
135144

136145
return
137146
IState.IdentityStateProcessResult({
@@ -223,13 +232,13 @@ contract CrossChainProofValidator is Ownable, EIP712, ICrossChainProofValidator
223232
uint256 replacedAtTimestamp
224233
) internal view returns (uint256 replacedAt) {
225234
if (oracleTimestamp < block.timestamp - MAX_TIMESTAMP_LAG) {
226-
revert("Oracle timestamp cannot be in the past");
235+
revert OracleTimestampCannotBeInThePast();
227236
}
228237

229238
replacedAt = replacedAtTimestamp == 0 ? oracleTimestamp : replacedAtTimestamp;
230239

231240
if (replacedAt > block.timestamp + MAX_REPLACED_AT_AHEAD_OF_TIME) {
232-
revert("Oracle replacedAtTimestamp or oracle timestamp cannot be in the future");
241+
revert OracleReplacedAtTimestampCannotBeInTheFuture();
233242
}
234243

235244
// this should never happen as block.timestamp is always greater than 0

contracts/identitytreestore/IdentityTreeStore.sol

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import {IOnchainCredentialStatusResolver} from "../interfaces/IOnchainCredential
88
import {IRHSStorage} from "../interfaces/IRHSStorage.sol";
99
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
1010

11+
error NodeNotFound();
12+
error InvalidStateNode();
13+
error InvalidNodeType();
14+
error UnsupportedLength();
15+
1116
/**
1217
* @dev Contract which provides onchain Reverse Hash Service (RHS)
1318
* for checking revocation status of claims.
@@ -40,10 +45,12 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
4045

4146
// keccak256(abi.encode(uint256(keccak256("iden3.storage.IdentityTreeStore.ReverseHashLibData")) - 1)) &
4247
// ~bytes32(uint256(0xff));
48+
// solhint-disable-next-line const-name-snakecase
4349
bytes32 private constant ReverseHashLibDataStorageLocation =
4450
0x0f7e3bdc6cc0e880d509aa1f6b8d1a88e5fcb7274e18dfba772424a36fe9b400;
4551

4652
function _getReverseHashLibDataStorage() private pure returns (ReverseHashLib.Data storage $) {
53+
// solhint-disable-next-line no-inline-assembly
4754
assembly {
4855
$.slot := ReverseHashLibDataStorageLocation
4956
}
@@ -55,6 +62,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
5562
}
5663

5764
// keccak256(abi.encode(uint256(keccak256("iden3.storage.IdentityTreeStore.Main")) - 1)) & ~bytes32(uint256(0xff));
65+
// solhint-disable-next-line const-name-snakecase
5866
bytes32 private constant IdentityTreeStoreMainStorageLocation =
5967
0x95ca427007e091a13a7ccfcb233b8a2ed19d987330a248c445b1b483a35bb800;
6068

@@ -64,6 +72,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
6472
pure
6573
returns (IdentityTreeStoreMainStorage storage $)
6674
{
75+
// solhint-disable-next-line no-inline-assembly
6776
assembly {
6877
$.slot := IdentityTreeStoreMainStorageLocation
6978
}
@@ -96,7 +105,9 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
96105
*/
97106
function getNode(uint256 key) public view returns (uint256[] memory) {
98107
uint256[] memory preim = _getReverseHashLibDataStorage().getPreimage(key);
99-
require(preim.length > 0, "Node not found");
108+
if (preim.length == 0) {
109+
revert NodeNotFound();
110+
}
100111
return preim;
101112
}
102113

@@ -122,6 +133,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
122133
* @return CredentialStatus
123134
*/
124135
function getRevocationStatusByIdAndState(
136+
// solhint-disable-next-line no-unused-vars
125137
uint256 id,
126138
uint256 state,
127139
uint64 nonce
@@ -134,7 +146,9 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
134146
uint64 nonce
135147
) internal view returns (CredentialStatus memory) {
136148
uint256[] memory roots = getNode(state);
137-
require(_nodeType(roots) == NodeType.State, "Invalid state node");
149+
if (_nodeType(roots) != NodeType.State) {
150+
revert InvalidStateNode();
151+
}
138152

139153
CredentialStatus memory status = CredentialStatus({
140154
issuer: IdentityStateRoots({
@@ -200,7 +214,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
200214
proof.siblings[i] = children[1];
201215
}
202216
} else {
203-
revert("Invalid node type");
217+
revert InvalidNodeType();
204218
}
205219
}
206220

@@ -234,6 +248,6 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I
234248
if (preimage.length == 3) {
235249
return PoseidonUnit3L.poseidon([preimage[0], preimage[1], preimage[2]]);
236250
}
237-
revert("Unsupported length");
251+
revert UnsupportedLength();
238252
}
239253
}

contracts/imports.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
// SPDX-License-Identifier: UNLICENSED
1+
// SPDX-License-Identifier: GPL-3.0
22
pragma solidity 0.8.27;
33

44
// We import these here to force Hardhat to compile them.
55
// This ensures that their artifacts are available for Hardhat Ignition to use.
6+
/* solhint-disable no-unused-import */
67
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
78
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
9+
/* solhint-enable no-unused-import */
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: GPL-3.0
2+
pragma solidity 0.8.27;
3+
4+
/**
5+
* @dev IAuthValidator. Interface for verification of auth data.
6+
*/
7+
interface IAuthValidator {
8+
/**
9+
* @dev AuthResponseField. Information about response fields from verification. Used in verify function.
10+
* @param name Name of the response field
11+
* @param value Value of the response field
12+
*/
13+
struct AuthResponseField {
14+
string name;
15+
uint256 value;
16+
}
17+
18+
/**
19+
* @dev Get version of the contract
20+
*/
21+
function version() external view returns (string memory);
22+
23+
/**
24+
* @dev Verify the proof with the supported method informed in the auth query data
25+
* packed as bytes and that the proof was generated by the sender.
26+
* @param sender Sender of the proof.
27+
* @param proof Proof packed as bytes to verify.
28+
* @param params Request query data of the credential to verify.
29+
* @return userID User Id for the auth proof verified and response fields.
30+
* @return authResponseFields Additional response fields.
31+
*/
32+
function verify(
33+
address sender,
34+
bytes calldata proof,
35+
bytes calldata params
36+
) external returns (uint256 userID, AuthResponseField[] memory authResponseFields);
37+
}

contracts/interfaces/ICircuitValidator.sol

Lines changed: 0 additions & 85 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: GPL-3.0
2+
pragma solidity 0.8.27;
3+
4+
/**
5+
* @dev IGroth16Verifier. Interface for verification of groth16 proofs.
6+
*/
7+
interface IGroth16Verifier {
8+
/**
9+
* @dev Verify the circuit with the groth16 proof π=([πa]1,[πb]2,[πc]1).
10+
* @param a πa element of the groth16 proof.
11+
* @param b πb element of the groth16 proof.
12+
* @param c πc element of the groth16 proof.
13+
* @param signals Public inputs and outputs of the circuit.
14+
* @return r true if the proof is verified.
15+
*/
16+
function verify(
17+
uint256[2] calldata a,
18+
uint256[2][2] calldata b,
19+
uint256[2] calldata c,
20+
uint256[] calldata signals
21+
) external view returns (bool r);
22+
}

0 commit comments

Comments
 (0)