Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion l1-contracts/lib/circuits
Submodule circuits updated 410 files
2 changes: 1 addition & 1 deletion l1-contracts/script/StakingAssetHandler.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ contract StakingAssetHandlerScript is Test {
bytes32 public constant DEPOSIT_MERKLE_ROOT = bytes32(0);

ZKPassportVerifier internal constant zkPassportVerifier =
ZKPassportVerifier(0xf7480fd0A9289c062C52532f11D31e0b7A30ABe3);
ZKPassportVerifier(0x3101Bad9eA5fACadA5554844a1a88F7Fe48D4DE0);

TestERC20 public constant stakingAsset = TestERC20(0x6732CEDafCBF85Afa9B5C83f0385967840BBCe47);
IRegistry public constant registry = IRegistry(0xc2F24280F5c7F4897370dFDEb30f79Ded14f1c81);
Expand Down
48 changes: 28 additions & 20 deletions l1-contracts/src/mock/StakingAssetHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {IMintableERC20} from "@aztec/shared/interfaces/IMintableERC20.sol";
import {G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
import {Ownable} from "@oz/access/Ownable.sol";
import {MerkleProof} from "@oz/utils/cryptography/MerkleProof.sol";
import {ZKPassportVerifier, ProofVerificationParams, BoundData} from "@zkpassport/ZKPassportVerifier.sol";
import {
ZKPassportVerifier, ProofVerificationParams, BoundData, OS, FaceMatchMode
} from "@zkpassport/ZKPassportVerifier.sol";

/**
* @title StakingAssetHandler
Expand Down Expand Up @@ -56,6 +58,7 @@ interface IStakingAssetHandler {
error InvalidAge();
error InvalidCountry();
error InvalidValidityPeriod();
error InvalidFaceMatch();
error ExtraDiscloseDataNonZero();
error SybilDetected(bytes32 _nullifier);
error AttesterDoesNotExist(address _attester);
Expand Down Expand Up @@ -120,6 +123,12 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {
string internal constant IRN = "IRN";
string internal constant CUB = "CUB";

// Minimum age
uint8 public constant MIN_AGE = 18;

// Validity period in seconds
uint256 public constant VALIDITY_PERIOD = 7 days;

IMintableERC20 public immutable STAKING_ASSET;
IRegistry public immutable REGISTRY;

Expand All @@ -143,9 +152,6 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {
// ZKPassport constraints
string public validDomain;
string public validScope;
uint256 public validValidityPeriodInSeconds = 7 days;
uint8 public minAge = 18;
string[] internal excludedCountries;

constructor(StakingAssetHandlerArgs memory _args) Ownable(_args.owner) {
require(_args.depositsPerMint > 0, CannotMintZeroAmount());
Expand Down Expand Up @@ -181,12 +187,6 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {
validDomain = _args.domain;
validScope = _args.scope;

excludedCountries = new string[](4);
excludedCountries[0] = CUB;
excludedCountries[1] = IRN;
excludedCountries[2] = PKR;
excludedCountries[3] = UKR;

skipBindCheck = _args.skipBindCheck;
skipMerkleCheck = _args.skipMerkleCheck;
}
Expand Down Expand Up @@ -323,18 +323,19 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {
function _validatePassportProof(address _attester, ProofVerificationParams calldata _params) internal {
// Must NOT be using dev mode - https://docs.zkpassport.id/getting-started/dev-mode
// If active, nullifiers will end up being zero, but it is user provided input, so we are sanity checking it
require(_params.devMode == false, InvalidProof());
require(_params.serviceConfig.devMode == false, InvalidProof());

require(keccak256(bytes(_params.domain)) == keccak256(bytes(validDomain)), InvalidDomain());
require(keccak256(bytes(_params.scope)) == keccak256(bytes(validScope)), InvalidScope());
require(keccak256(bytes(_params.serviceConfig.domain)) == keccak256(bytes(validDomain)), InvalidDomain());
require(keccak256(bytes(_params.serviceConfig.scope)) == keccak256(bytes(validScope)), InvalidScope());
require(_params.serviceConfig.validityPeriodInSeconds == VALIDITY_PERIOD, InvalidValidityPeriod());

(bool verified, bytes32 nullifier) = zkPassportVerifier.verifyProof(_params);

require(verified, InvalidProof());
require(!nullifiers[nullifier], SybilDetected(nullifier));

if (!skipBindCheck) {
BoundData memory boundData = zkPassportVerifier.getBoundData(_params);
BoundData memory boundData = zkPassportVerifier.getBoundData(_params.commitments);

// Make sure the bound user address is the same as the _attester
require(boundData.senderAddress == _attester, InvalidBoundAddress(boundData.senderAddress, _attester));
Expand All @@ -343,19 +344,26 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {
// Make sure the custom data is empty
require(bytes(boundData.customData).length == 0, ExtraDiscloseDataNonZero());

// Validity period check
require(validValidityPeriodInSeconds == _params.validityPeriodInSeconds, InvalidValidityPeriod());

// Age check
bool isAgeValid = zkPassportVerifier.isAgeAboveOrEqual(minAge, _params);
bool isAgeValid = zkPassportVerifier.isAgeAboveOrEqual(MIN_AGE, _params.commitments, _params.serviceConfig);
require(isAgeValid, InvalidAge());

// Country exclusion check
bool isCountryValid = zkPassportVerifier.isNationalityOut(excludedCountries, _params);
string[] memory excludedCountries = new string[](4);
excludedCountries[0] = CUB;
excludedCountries[1] = IRN;
excludedCountries[2] = PKR;
excludedCountries[3] = UKR;
bool isCountryValid = zkPassportVerifier.isNationalityOut(excludedCountries, _params.commitments);
require(isCountryValid, InvalidCountry());

// Sanctions check
zkPassportVerifier.enforceSanctionsRoot(_params);
zkPassportVerifier.enforceSanctionsRoot(_params.commitments);

// Face match check
bool isFaceMatchValid =
zkPassportVerifier.isFaceMatchVerified(FaceMatchMode.STRICT, OS.ANY, _params.commitments, _params.serviceConfig);
require(isFaceMatchValid, InvalidFaceMatch());
}

// Set nullifier to consumed
Expand Down
8 changes: 5 additions & 3 deletions l1-contracts/test/staking_asset_handler/addValidator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,11 @@ contract AddValidatorTest is StakingAssetHandlerBase {
_attester, validMerkleProof, _proof, BN254Lib.g1Zero(), BN254Lib.g2Zero(), BN254Lib.g1Zero()
);

uint256 uniqueIdentifierLocation = _proof.publicInputs.length - 1;
uint256 uniqueIdentifierLocation = _proof.proofVerificationData.publicInputs.length - 1;
vm.expectRevert(
abi.encodeWithSelector(IStakingAssetHandler.SybilDetected.selector, _proof.publicInputs[uniqueIdentifierLocation])
abi.encodeWithSelector(
IStakingAssetHandler.SybilDetected.selector, _proof.proofVerificationData.publicInputs[uniqueIdentifierLocation]
)
);
// Call from somebody else
vm.prank(_caller);
Expand All @@ -201,7 +203,7 @@ contract AddValidatorTest is StakingAssetHandlerBase {
givenPassportProofIsValid
{
// it reverts
_proof.devMode = true;
_proof.serviceConfig.devMode = true;

vm.assume(
_attester != address(0) && _caller != address(this) && _attester != address(this) && _attester != unhinged
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,34 @@ pragma solidity >=0.8.27;

import {ZKPassportVerifier, ProofVerificationParams} from "@zkpassport/ZKPassportVerifier.sol";
import {IRootRegistry} from "@zkpassport/IRootRegistry.sol";
import {HonkVerifier as OuterVerifier7} from "@zkpassport/ultra-honk-verifiers/OuterCount7.sol";
import {HonkVerifier as OuterVerifier8} from "@zkpassport/ultra-honk-verifiers/OuterCount8.sol";
import {MockRootRegistry} from "./MockRootRegistry.sol";
import {MockZKPassportVerifier} from "@aztec/mock/staking_asset_handler/MockZKPassportVerifier.sol";
import {CommittedInputLen} from "@zkpassport/Constants.sol";
import {ProofVerificationData, Commitments, ServiceConfig} from "@zkpassport/Types.sol";

import {Test} from "forge-std/Test.sol";

contract ZKPassportBase is Test {
ZKPassportVerifier public zkPassportVerifier;
MockZKPassportVerifier public mockZKPassportVerifier;

OuterVerifier7 public verifier;
OuterVerifier8 public verifier;
IRootRegistry public rootRegistry;

ProofVerificationParams internal fakeProof;
ProofVerificationParams internal realProof;

// Path to the proof file - using files directly in project root
// Fixtures copied from within the zk passport subrepo
bytes32 constant VKEY_HASH = 0x2992c925ad8932475d5784bf202b58f1c9d043d6ec04e236a7c761593caea5ce;
bytes32 constant VKEY_HASH = 0x254314c80a8cc3efc785643a0a6aeeba6ae268a45e69a98affd4a4155f01e186;

// From fixtures - see lib/circuits/src/solidity/test/SampleContract.t.sol
string constant CORRECT_DOMAIN = "zkpassport.id";
string constant CORRECT_SCOPE = "bigproof";

// Time when the proof was generated - 2025-09-26T15:46:45.835Z
uint256 public PROOF_GENERATION_TIMESTAMP = 1_758_901_597;
// Time when the proof was generated - October 19, 2025 7:29:51Z
uint256 public PROOF_GENERATION_TIMESTAMP = 1_760_906_062;

// Using this base contract will make a zkpassport verifier and proof available for testing purposes
constructor() {
Expand All @@ -40,7 +41,7 @@ contract ZKPassportBase is Test {
// Deploy wrapper verifier
zkPassportVerifier = new ZKPassportVerifier(address(rootRegistry));
// Deploy actual circuit verifier
verifier = new OuterVerifier7();
verifier = new OuterVerifier8();

// Add to the zk passport verifier
bytes32[] memory vkeyHashes = new bytes32[](1);
Expand All @@ -66,22 +67,22 @@ contract ZKPassportBase is Test {
bytes memory committedInputs = loadBytesFromFile("valid_committed_inputs.hex");

// Order of bytes of committed inputs for each disclosure proof
uint256[] memory committedInputCounts = new uint256[](4);
uint256[] memory committedInputCounts = new uint256[](5);
committedInputCounts[0] = CommittedInputLen.BIND;
committedInputCounts[1] = CommittedInputLen.SANCTIONS;
committedInputCounts[2] = CommittedInputLen.EXCL_NATIONALITY;
committedInputCounts[3] = CommittedInputLen.COMPARE_AGE;
committedInputCounts[4] = CommittedInputLen.FACEMATCH;

params = ProofVerificationParams({
vkeyHash: VKEY_HASH,
proof: proof,
publicInputs: publicInputs,
committedInputs: committedInputs,
committedInputCounts: committedInputCounts,
validityPeriodInSeconds: 7 days,
domain: "zkpassport.id",
scope: "bigproof",
devMode: false
proofVerificationData: ProofVerificationData({vkeyHash: VKEY_HASH, proof: proof, publicInputs: publicInputs}),
commitments: Commitments({committedInputs: committedInputs, committedInputCounts: committedInputCounts}),
serviceConfig: ServiceConfig({
validityPeriodInSeconds: 7 days,
domain: CORRECT_DOMAIN,
scope: CORRECT_SCOPE,
devMode: false
})
});
}

Expand All @@ -102,15 +103,14 @@ contract ZKPassportBase is Test {
committedInputCounts[7] = 25;

params = ProofVerificationParams({
vkeyHash: VKEY_HASH,
proof: proof,
publicInputs: publicInputs,
committedInputs: committedInputs,
committedInputCounts: committedInputCounts,
validityPeriodInSeconds: 7 days,
domain: "zkpassport.id",
scope: "bigproof",
devMode: true
proofVerificationData: ProofVerificationData({vkeyHash: VKEY_HASH, proof: proof, publicInputs: publicInputs}),
commitments: Commitments({committedInputs: committedInputs, committedInputCounts: committedInputCounts}),
serviceConfig: ServiceConfig({
validityPeriodInSeconds: 7 days,
domain: "zkpassport.id",
scope: "bigproof",
devMode: true
})
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0801001404fb06e8bf44ec60b6a99d2f98551172b2f2ded80200027a690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009099699583ea7729a4a05821667645e927b74feb4e6e5382c6e4370e35ed2b23c0543554249524e50524b554b52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000068d6b1141200
0801001404fb06e8bf44ec60b6a99d2f98551172b2f2ded80200027a690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009099699583ea7729a4a05821667645e927b74feb4e6e5382c6e4370e35ed2b23c0543554249524e50524b554b52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000068f54aab12000a2532418a107c5306fa8308c22255792cf77e4a290cbce8a840a642a3e591340b011fa73686cf510f8f85757b0602de0dd72a13e68ae2092462be8b72662e7f179b000000000000000000000000000000000000000000000000000000000000000002

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"inputs": [
"0x27eb6ee351be62a96a3209749074c8641d2b15845a37d3f312ad805b0f4ec4d0",
"0x1b84a41b213ad424e50a306f4ea6c961a66caac76915241df4dc93b6757dd9cd",
"0x0000000000000000000000000000000000000000000000000000000068d6b132",
"0x166a7b95f72ab538ed181b0888ccee18204f98dca373187c42503aacc290a72c",
"0x2d88250ced89385b0135ba36f190f858fd329b2694f479c5a605884c7f194384",
"0x0000000000000000000000000000000000000000000000000000000068f54abb",
"0x008d535e2a7f4ee38a4d12aa88bcf21d2c2f6fa051d12eafba6655bf37e8c11c",
"0x00f54fbb0f658e7013ec2114ef095a29bb3e2f95b96dbd93e46f12f67863111a",
"0x00ed45ee6335b3285f58a3c472e398fc6754d1eaa9d7043a60b2daa0a67332e7",
"0x000105354ff92c66a5d42a8d34033ace18d259e4dc04b35a584dc370c00586ba",
"0x0037e4a54fb3f1500058797f475d37f2f8cd9b87f20762c21497a2ab2f655f64",
"0x00123482330ec434a086016334db04fdd2ac4764617511c8904dcf2a0343327b",
"0x0031f315a5531bb674ebe625f9ff8298ed0c0a07a173287b47e57691138fb09e",
"0x00dcec2b86a5267e6e92db9cc0017a2e89d62df782c4254d856bff5eaef8c391",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x171de101deed3f056917faecfe6cc04db2ef02689a8a483962a688948ce44461"
]
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/zkPassportVerifierAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
* The address of the zk passport verifier on sepolia
* get address from: ROOT/l1-contracts/lib/circuits/src/solidity/deployments/deployment-11155111.json
*/
export const ZK_PASSPORT_VERIFIER_ADDRESS = EthAddress.fromString('0xBec82dec0747C9170D760D5aba9cc44929B17C05');
export const ZK_PASSPORT_VERIFIER_ADDRESS = EthAddress.fromString('0x3101Bad9eA5fACadA5554844a1a88F7Fe48D4DE0');
/**
* The default domain of the zk passport site
*/
Expand Down
Loading
Loading