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 764 files
6 changes: 3 additions & 3 deletions l1-contracts/script/StakingAssetHandler.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ contract StakingAssetHandlerScript is Test {
bytes32 public constant DEPOSIT_MERKLE_ROOT = bytes32(0);

ZKPassportVerifier internal constant zkPassportVerifier =
ZKPassportVerifier(0x62e33cC35e29130e135341586e8Cf9C2BAbFB3eE);
ZKPassportVerifier(0xBec82dec0747C9170D760D5aba9cc44929B17C05);

TestERC20 public constant stakingAsset = TestERC20(0x0C04089ED32638ae3cDf649F54F90544aC3Fc199);
IRegistry public constant registry = IRegistry(0xEc4156431d0F3DF66d4E24ba3D30dCb4c85FA309);
TestERC20 public constant stakingAsset = TestERC20(0xad6618B0f91d3fe156eF4CbEb08844C32954f089);
IRegistry public constant registry = IRegistry(0x2e48aDdcA360dA61e4d6C21ff2B1961Af56eB83b);

function setUp() public {}

Expand Down
52 changes: 44 additions & 8 deletions l1-contracts/src/mock/StakingAssetHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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} from "@zkpassport/ZKPassportVerifier.sol";
import {ZKPassportVerifier, ProofVerificationParams, ProofType} from "@zkpassport/ZKPassportVerifier.sol";

/**
* @title StakingAssetHandler
Expand Down Expand Up @@ -50,8 +50,13 @@ interface IStakingAssetHandler {
error InvalidProof();
error InvalidScope();
error InvalidDomain();
error ProofNotBoundToAddress(address _expected, address _received);
error ProofNotBoundToChainId(uint256 _expected, uint256 _received);
error InvalidBoundAddress(address _expected, address _received);
error InvalidChainId(uint256 _expected, uint256 _received);
error InvalidAge();
error InvalidCountry();
error InvalidCurrentDate();
error InvalidValidityPeriod();
error ExtraDiscloseDataNonZero();
error SybilDetected(bytes32 _nullifier);
error AttesterDoesNotExist(address _attester);
error NoNullifier();
Expand Down Expand Up @@ -126,8 +131,18 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {

address public withdrawer;

// ZKPassport constraints
string public validDomain;
string public validScope;
uint256 public validValidityPeriodInSeconds = 7 days;
uint256 public validMinAge = 18;
uint256 public validMaxAge = 0;

// ZKPassport - Excluded counties
bytes32 internal pkr = keccak256(bytes("PRK"));
bytes32 internal ukr = keccak256(bytes("UKR"));
bytes32 internal irn = keccak256(bytes("IRN"));
bytes32 internal cub = keccak256(bytes("CUB"));

constructor(StakingAssetHandlerArgs memory _args) Ownable(_args.owner) {
require(_args.depositsPerMint > 0, CannotMintZeroAmount());
Expand Down Expand Up @@ -303,13 +318,34 @@ contract StakingAssetHandler is IStakingAssetHandler, Ownable {

if (!skipBindCheck) {
bytes memory data = zkPassportVerifier.getBindProofInputs(_params.committedInputs, _params.committedInputCounts);
// Use the getBoundData function to get the formatted data
// which includes the user's address, chainId and any custom data
(address boundAddress, uint256 chainId,) = zkPassportVerifier.getBoundData(data);

(address boundAddress, uint256 chainId, string memory customData) = zkPassportVerifier.getBoundData(data);
// Make sure the bound user address is the same as the _attester
require(boundAddress == _attester, ProofNotBoundToAddress(boundAddress, _attester));
require(boundAddress == _attester, InvalidBoundAddress(boundAddress, _attester));
// Make sure the chainId is the same as the current chainId
require(chainId == block.chainid, ProofNotBoundToChainId(chainId, block.chainid));
require(chainId == block.chainid, InvalidChainId(chainId, block.chainid));
// Make sure the custom data is empty
require(bytes(customData).length == 0, ExtraDiscloseDataNonZero());

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

// Age check
(uint256 currentDate, uint8 minAge, uint8 maxAge) =
zkPassportVerifier.getAgeProofInputs(_params.committedInputs, _params.committedInputCounts);
require(block.timestamp >= currentDate, InvalidCurrentDate());
require(validMinAge == minAge && validMaxAge == maxAge, InvalidAge());

// Country exclusion check
string[] memory exclusionCountryList = zkPassportVerifier.getCountryProofInputs(
_params.committedInputs, _params.committedInputCounts, ProofType.NATIONALITY_EXCLUSION
);
require(keccak256(bytes(exclusionCountryList[0])) == cub, InvalidCountry());
require(keccak256(bytes(exclusionCountryList[1])) == irn, InvalidCountry());
require(keccak256(bytes(exclusionCountryList[2])) == pkr, InvalidCountry());
require(keccak256(bytes(exclusionCountryList[3])) == ukr, InvalidCountry());

zkPassportVerifier.enforceSanctionsRoot(_params.committedInputs, _params.committedInputCounts);
}

// Set nullifier to consumed
Expand Down
4 changes: 1 addition & 3 deletions l1-contracts/test/staking_asset_handler/bind.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ contract BindTest is StakingAssetHandlerBase {

vm.assume(_attester != BOUND_ADDRESS && _attester != address(this));

vm.expectRevert(
abi.encodeWithSelector(IStakingAssetHandler.ProofNotBoundToAddress.selector, BOUND_ADDRESS, _attester)
);
vm.expectRevert(abi.encodeWithSelector(IStakingAssetHandler.InvalidBoundAddress.selector, BOUND_ADDRESS, _attester));
vm.prank(_attester);
stakingAssetHandler.addValidator(
_attester, validMerkleProof, realProof, BN254Lib.g1Zero(), BN254Lib.g2Zero(), BN254Lib.g1Zero()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,34 @@ pragma solidity >=0.8.27;

import {ZKPassportVerifier, ProofVerificationParams} from "@zkpassport/ZKPassportVerifier.sol";
import {IRootRegistry} from "@zkpassport/IRootRegistry.sol";
import {HonkVerifier as OuterVerifier5} from "@zkpassport/OuterCount5.sol";
import {HonkVerifier as OuterVerifier7} from "@zkpassport/OuterCount7.sol";
import {MockRootRegistry} from "./MockRootRegistry.sol";
import {MockZKPassportVerifier} from "@aztec/mock/staking_asset_handler/MockZKPassportVerifier.sol";
import {CommittedInputLen} from "@zkpassport/Constants.sol";

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

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

OuterVerifier5 public verifier;
OuterVerifier7 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 = bytes32(uint256(0x2ab349ef31f5d516da820a3f55f93c53f9c899b0b991c93fc341199cc1e3b36c));
bytes32 constant CERTIFICATE_REGISTRY_ROOT =
bytes32(uint256(0x130b5775fe59204b0490bdfcdd02bd7cc2bbf5fe3f3fee34cee13c3a3f9b7bbb));
bytes32 constant VKEY_HASH = 0x2992c925ad8932475d5784bf202b58f1c9d043d6ec04e236a7c761593caea5ce;

// 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 - Tue Sep 09 2025 13:20:59 UTC
uint256 public PROOF_GENERATION_TIMESTAMP = 1_757_424_059;

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

// Add to the zk passport verifier
bytes32[] memory vkeyHashes = new bytes32[](1);
Expand All @@ -48,11 +50,9 @@ contract ZKPassportBase is Test {
verifiers[0] = address(verifier);

zkPassportVerifier.addVerifiers(vkeyHashes, verifiers);
zkPassportVerifier.addCertificateRegistryRoot(CERTIFICATE_REGISTRY_ROOT);

// ( When the proof was made )
// Set the timestamp to 2025-07-16 20:26:48 UTC
vm.warp(1_752_697_608);
// Set the timestamp to PROOF_GENERATION_TIMESTAMP
vm.warp(PROOF_GENERATION_TIMESTAMP);
realProof = makeValidProof();
fakeProof = makeFakeProof();

Expand All @@ -66,17 +66,19 @@ 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[](2);
committedInputCounts[0] = 181;
committedInputCounts[1] = 501;
uint256[] memory committedInputCounts = new uint256[](4);
committedInputCounts[0] = CommittedInputLen.BIND;
committedInputCounts[1] = CommittedInputLen.SANCTIONS;
committedInputCounts[2] = CommittedInputLen.EXCL_NATIONALITY;
committedInputCounts[3] = CommittedInputLen.COMPARE_AGE;

params = ProofVerificationParams({
vkeyHash: VKEY_HASH,
proof: proof,
publicInputs: publicInputs,
committedInputs: committedInputs,
committedInputCounts: committedInputCounts,
validityPeriodInDays: 7,
validityPeriodInSeconds: 7 days,
domain: "zkpassport.id",
scope: "bigproof",
devMode: false
Expand Down Expand Up @@ -105,7 +107,7 @@ contract ZKPassportBase is Test {
publicInputs: publicInputs,
committedInputs: committedInputs,
committedInputCounts: committedInputCounts,
validityPeriodInDays: 7,
validityPeriodInSeconds: 7 days,
domain: "zkpassport.id",
scope: "bigproof",
devMode: true
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
00010100000001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100010101010101010101000100000000000000000000000000000000000000000000000000503c00000053494c56455248414e443c3c4a4f484e4e593c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c50413132333435363700415553383831313132004d000000000000000000000000000000000000000000000000000801001404fb06e8bf44ec60b6a99d2f98551172b2f2ded80200027a6903002a656d61696c3a7465737440746573742e636f6d2c637573746f6d65725f69643a3132333435363738393000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0801001404fb06e8bf44ec60b6a99d2f98551172b2f2ded80200027a690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009099699583ea7729a4a05821667645e927b74feb4e6e5382c6e4370e35ed2b23c0543554249524e50524b554b52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000068c027891200

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
{
"inputs": [
"0x07eb76cc780e3a054342917c91fd2717cefef6e8994286c6414e2cfe0b470f6a",
"0x27c36e90dafc5d889cf2e92c2f46009b4c61203f316da84d5fe173845b9dc72a",
"0x0000000000000000000000000000000000000000000000000000000000000032",
"0x0000000000000000000000000000000000000000000000000000000000000030",
"0x0000000000000000000000000000000000000000000000000000000000000032",
"0x0000000000000000000000000000000000000000000000000000000000000035",
"0x0000000000000000000000000000000000000000000000000000000000000030",
"0x0000000000000000000000000000000000000000000000000000000000000037",
"0x0000000000000000000000000000000000000000000000000000000000000031",
"0x0000000000000000000000000000000000000000000000000000000000000036",
"0x034608472e44e3d796a30320dea6693df95c42294c3a119fda9f3c2d39053ae9",
"0x0e74ef920d724a7a23120f66991b1cbed34c207b593df6e421113b7c287283ac",
"0x0000000000000000000000000000000000000000000000000000000068c027a3",
"0x008d535e2a7f4ee38a4d12aa88bcf21d2c2f6fa051d12eafba6655bf37e8c11c",
"0x00f54fbb0f658e7013ec2114ef095a29bb3e2f95b96dbd93e46f12f67863111a",
"0x00727b8cb376e4e4ac36880437f277de0c33748a1f505725160a94be705917d0",
"0x00ac375d5fafd70528bdebe251b9be49a9ac1428c5cb794e8b01e740df5760d1",
"0x00ed45ee6335b3285f58a3c472e398fc6754d1eaa9d7043a60b2daa0a67332e7",
"0x000105354ff92c66a5d42a8d34033ace18d259e4dc04b35a584dc370c00586ba",
"0x0037e4a54fb3f1500058797f475d37f2f8cd9b87f20762c21497a2ab2f655f64",
"0x004e3c2357bff38ea9c5d68fc06b8279435cdba99ee27fa272f0fe6091ca08f4",
"0x0a70167613fa7c456b46f57e91d4fc40c1a7895f55bb7d36ef0ac17ff05045e6"
]
}
}
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('0x62e33cC35e29130e135341586e8Cf9C2BAbFB3eE');
export const ZK_PASSPORT_VERIFIER_ADDRESS = EthAddress.fromString('0xBec82dec0747C9170D760D5aba9cc44929B17C05');
/**
* The default domain of the zk passport site
*/
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/stdlib/src/zkpassport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type ViemZkPassportProofParams = {
publicInputs: `0x${string}`[];
committedInputs: `0x${string}`;
committedInputCounts: bigint[];
validityPeriodInDays: bigint;
validityPeriodInSeconds: bigint;
domain: string;
scope: string;
devMode: boolean;
Expand All @@ -26,7 +26,7 @@ export class ZkPassportProofParams {
public publicInputs: Fr[],
public committedInputs: Buffer,
public committedInputCounts: bigint[],
public validityPeriodInDays: bigint,
public validityPeriodInSeconds: bigint,
public domain: string,
public scope: string,
) {}
Expand All @@ -43,7 +43,7 @@ export class ZkPassportProofParams {
this.committedInputs,
this.committedInputCounts.length,
this.committedInputCounts,
this.validityPeriodInDays,
this.validityPeriodInSeconds,
this.domain,
this.scope,
]);
Expand All @@ -64,7 +64,7 @@ export class ZkPassportProofParams {
publicInputs,
committedInputs,
committedInputCounts,
BigInt(100),
BigInt(100 * 60 * 60 * 24),
'sequencer.alpha-testnet.aztec.network',
'personhood',
);
Expand Down Expand Up @@ -93,7 +93,7 @@ export class ZkPassportProofParams {
params.publicInputs.map(input => Fr.fromString(input)),
Buffer.from(withoutHexPrefix(params.committedInputs), 'hex'),
params.committedInputCounts,
params.validityPeriodInDays,
params.validityPeriodInSeconds,
params.domain,
params.scope,
);
Expand All @@ -107,7 +107,7 @@ export class ZkPassportProofParams {
publicInputs: this.publicInputs.map(input => input.toString()),
committedInputs: `0x${this.committedInputs.toString('hex')}`,
committedInputCounts: this.committedInputCounts,
validityPeriodInDays: this.validityPeriodInDays,
validityPeriodInSeconds: this.validityPeriodInSeconds,
domain: this.domain,
scope: this.scope,
};
Expand Down
Loading