diff --git a/contracts/verifiers/TimeWindowSBTIdentityVerifier.sol b/contracts/verifiers/TimeWindowSBTIdentityVerifier.sol index 3287ef0..eb7b73a 100644 --- a/contracts/verifiers/TimeWindowSBTIdentityVerifier.sol +++ b/contracts/verifiers/TimeWindowSBTIdentityVerifier.sol @@ -37,16 +37,17 @@ contract TimeWindowSBTIdentityVerifier is ITimeWindowSBTIdentityVerifier, SBTIde function _proveIdentity(ProveIdentityParams calldata proveIdentityParams_) internal override { _verify(TIME_WINDOW_SBT_IDENTITY_PROOF_QUERY_ID, proveIdentityParams_); - require( - addressToIdentityId[msg.sender] == 0, - "TimeWindowSBTIdentityVerifier: Msg sender address has already been used to prove the another identity." - ); - IQueryValidator queryValidator_ = IQueryValidator( zkpQueriesStorage.getQueryValidator(TIME_WINDOW_SBT_IDENTITY_PROOF_QUERY_ID) ); uint256 identityId_ = proveIdentityParams_.inputs[queryValidator_.getUserIdIndex()]; + uint256 storedIdentityId_ = addressToIdentityId[msg.sender]; + + require( + storedIdentityId_ == 0 || storedIdentityId_ == identityId_, + "TimeWindowSBTIdentityVerifier: Msg sender address has already been used to prove the another identity." + ); require( !isIdentityProved(identityId_), diff --git a/deploy/4_identity_contracts_deploy.ts b/deploy/4_identity_contracts_deploy.ts index 4de0b3d..70c5c5f 100644 --- a/deploy/4_identity_contracts_deploy.ts +++ b/deploy/4_identity_contracts_deploy.ts @@ -6,6 +6,7 @@ import { getDeployedStateContract, getDeployedQueryValidatorContract, getDeployedVerifierContract, + getDeployedSBTTokenInfo, } from "@/deploy/helpers/deploy_helper"; const ERC1967Proxy = artifacts.require("ERC1967Proxy"); @@ -48,8 +49,8 @@ export = async (deployer: Deployer, logger: Logger) => { (await getDeployedQueryValidatorContract(config.validatorContractInfo.isMtpValidator)).address, ]; const verifierInfo = [ - config.identityVerifierInfo.isSBTIdentityVerifier ? "SBTIdentityVerifier" : "IdentityVerifier", - (await getDeployedVerifierContract(config.identityVerifierInfo.isSBTIdentityVerifier)).address, + config.identityVerifierInfo.identityVerifierType, + (await getDeployedVerifierContract(config.identityVerifierInfo.identityVerifierType)).address, ]; logger.logContracts( @@ -57,6 +58,7 @@ export = async (deployer: Deployer, logger: Logger) => { validatorsInfo, verifierInfo, ["ZKPQueriesStorage", zkpQueriesStorage.address], - ["PoseidonFacade", poseidonFacade.address] + ["PoseidonFacade", poseidonFacade.address], + await getDeployedSBTTokenInfo(config.identityVerifierInfo.identityVerifierType) ); }; diff --git a/deploy/data/config.json b/deploy/data/config.json index d22cd98..405f811 100644 --- a/deploy/data/config.json +++ b/deploy/data/config.json @@ -23,10 +23,11 @@ "verifiedSBTInfo": { "name": "testSBT", "symbol": "TSBT", - "tokenURI": "test uri" + "tokenURI": "test uri", + "expirationPeriod": "3600" } }, - "isSBTIdentityVerifier": "true" + "identityVerifierType": "TimeWindowSBTIdentityVerifier" }, "zkpQueries": [ { diff --git a/deploy/helpers/config_parser.ts b/deploy/helpers/config_parser.ts index 2b8aeb3..644da92 100644 --- a/deploy/helpers/config_parser.ts +++ b/deploy/helpers/config_parser.ts @@ -3,6 +3,12 @@ import { ZERO_ADDR } from "@/scripts/utils/constants"; import { ethers } from "hardhat"; import { BigNumberish } from "@ethersproject/bignumber"; +export enum IdentityVerifierType { + IdentityVerifer = "IdentityVerifier", + SBTIdentityVerifer = "SBTIdentityVerifier", + TimeWindowSBTIdentityVerifer = "TimeWindowSBTIdentityVerifier", +} + export type Config = { validatorContractInfo: ValidatorContractInfo; stateContractInfo: StateContractInfo; @@ -27,7 +33,7 @@ export type StateContractInfo = { export type IdentityVerifierInfo = { identityVerifierAddr?: string; verifierInitParams?: IdentityVerifierInitParams; - isSBTIdentityVerifier: boolean | string; + identityVerifierType: IdentityVerifierType; }; export type StateInitParams = { @@ -46,6 +52,7 @@ export type VerifiedSBTInfo = { name: string; symbol: string; tokenURI: string; + expirationPeriod?: BigNumberish; }; export type ZKPQueryInfo = { @@ -119,9 +126,14 @@ function validateStateInitParams(stateInitParams: StateInitParams) { } function validateIdentityVerifierInfo(identityVerifierInfo: IdentityVerifierInfo) { - identityVerifierInfo.isSBTIdentityVerifier = identityVerifierInfo.isSBTIdentityVerifier == "true"; + if (!Object.values(IdentityVerifierType).includes(identityVerifierInfo.identityVerifierType)) { + throw new Error("Invalid identityVerifierType field"); + } - if (identityVerifierInfo.isSBTIdentityVerifier) { + if ( + identityVerifierInfo.identityVerifierType == IdentityVerifierType.SBTIdentityVerifer || + identityVerifierInfo.identityVerifierType == IdentityVerifierType.TimeWindowSBTIdentityVerifer + ) { if (identityVerifierInfo.verifierInitParams == undefined) { throw new Error(`Invalid SBT identity verifier init params.`); } @@ -134,6 +146,13 @@ function validateIdentityVerifierInfo(identityVerifierInfo: IdentityVerifierInfo nonEmptyFiled(identityVerifierInfo.verifierInitParams.verifiedSBTInfo.name, "verifiedSBT name"); nonEmptyFiled(identityVerifierInfo.verifierInitParams.verifiedSBTInfo.symbol, "verifiedSBT symbol"); nonEmptyFiled(identityVerifierInfo.verifierInitParams.verifiedSBTInfo.tokenURI, "verifiedSBT tokenURI"); + + if (identityVerifierInfo.identityVerifierType == IdentityVerifierType.TimeWindowSBTIdentityVerifer) { + nonEmptyFiled( + identityVerifierInfo.verifierInitParams.verifiedSBTInfo.expirationPeriod?.toString(), + "timeWindowSBT expirationPeriod" + ); + } } } } diff --git a/deploy/helpers/deploy_helper.ts b/deploy/helpers/deploy_helper.ts index 33419d1..6bf8c32 100644 --- a/deploy/helpers/deploy_helper.ts +++ b/deploy/helpers/deploy_helper.ts @@ -1,6 +1,6 @@ import { Deployer, Logger } from "@solarity/hardhat-migrate"; import { ethers, artifacts } from "hardhat"; -import { Config, isZeroAddr } from "./config_parser"; +import { Config, IdentityVerifierType, isZeroAddr } from "./config_parser"; const { poseidonContract } = require("circomlibjs"); @@ -18,6 +18,7 @@ const SmtLib = artifacts.require("SmtLib"); const StateLib = artifacts.require("StateLib"); const VerifiedSBT = artifacts.require("VerifiedSBT"); +const TimeWindowSBT = artifacts.require("TimeWindowSBT"); const QueryMTPValidator = artifacts.require("QueryMTPValidator"); const QuerySigValidator = artifacts.require("QuerySigValidator"); @@ -29,6 +30,7 @@ const ZKPQueriesStorage = artifacts.require("ZKPQueriesStorage"); const IdentityVerifier = artifacts.require("IdentityVerifier"); const SBTIdentityVerifier = artifacts.require("SBTIdentityVerifier"); +const TimeWindowSBTIdentityVerifier = artifacts.require("TimeWindowSBTIdentityVerifier"); import * as dotenv from "dotenv"; dotenv.config(); @@ -105,10 +107,18 @@ export async function deployState(deployer: Deployer, logger: Logger, config: Co } export async function deployVerifier(deployer: Deployer, logger: Logger, config: Config) { - if (config.identityVerifierInfo.isSBTIdentityVerifier) { - await deploySBTIdentityVerifier(deployer, logger, config); - } else { - await deployIdentityVerifier(deployer, logger, config); + switch (config.identityVerifierInfo.identityVerifierType) { + case IdentityVerifierType.IdentityVerifer: + await deployIdentityVerifier(deployer, logger, config); + break; + case IdentityVerifierType.SBTIdentityVerifer: + await deploySBTIdentityVerifier(deployer, logger, config); + break; + case IdentityVerifierType.TimeWindowSBTIdentityVerifer: + await deployTimeWindowSBTIdentityVerifier(deployer, logger, config); + break; + default: + throw new Error("Unsupported Identity verifier type"); } } @@ -120,8 +130,26 @@ export async function getDeployedStateContract(isLightweight: boolean | string) return isLightweight ? await LightweightState.deployed() : await State.deployed(); } -export async function getDeployedVerifierContract(isSBTIdentityVerifier: boolean | string) { - return isSBTIdentityVerifier ? await SBTIdentityVerifier.deployed() : await IdentityVerifier.deployed(); +export async function getDeployedVerifierContract(identityVerifierType: IdentityVerifierType) { + switch (identityVerifierType) { + case IdentityVerifierType.IdentityVerifer: + return await IdentityVerifier.deployed(); + case IdentityVerifierType.SBTIdentityVerifer: + return await SBTIdentityVerifier.deployed(); + case IdentityVerifierType.TimeWindowSBTIdentityVerifer: + return await TimeWindowSBTIdentityVerifier.deployed(); + } +} + +export async function getDeployedSBTTokenInfo(identityVerifierType: IdentityVerifierType) { + switch (identityVerifierType) { + case IdentityVerifierType.IdentityVerifer: + return ["", ""]; + case IdentityVerifierType.SBTIdentityVerifer: + return ["VerifiedSBT", (await VerifiedSBT.deployed()).address]; + case IdentityVerifierType.TimeWindowSBTIdentityVerifer: + return ["TimeWindowSBT", (await TimeWindowSBT.deployed()).address]; + } } async function deployMTPValidator( @@ -308,3 +336,52 @@ async function deploySBTIdentityVerifier(deployer: Deployer, logger: Logger, con await SBTIdentityVerifier.setAsDeployed(sbtIdentityVerifier); } + +async function deployTimeWindowSBTIdentityVerifier(deployer: Deployer, logger: Logger, config: Config) { + let timeWindowSBTIdentityVerifier; + + if (isZeroAddr(config.identityVerifierInfo.identityVerifierAddr)) { + const timeWindowSBTIdentityVerifierImpl = await deployer.deploy(TimeWindowSBTIdentityVerifier); + const timeWindowSBTIdentityVerifierProxy = await deployer.deploy( + ERC1967Proxy, + timeWindowSBTIdentityVerifierImpl.address, + [] + ); + + timeWindowSBTIdentityVerifier = await TimeWindowSBTIdentityVerifier.at(timeWindowSBTIdentityVerifierProxy.address); + + const zkpQueriesStorage = await ZKPQueriesStorage.deployed(); + let timeWindowSBT; + + if (isZeroAddr(config.identityVerifierInfo.verifierInitParams?.verifiedSBTAddr)) { + const timeWindowSBTImpl = await deployer.deploy(TimeWindowSBT); + const timeWindowSBTProxy = await deployer.deploy(ERC1967Proxy, timeWindowSBTImpl.address, []); + + timeWindowSBT = await TimeWindowSBT.at(timeWindowSBTProxy.address); + + logger.logTransaction( + await timeWindowSBT.__TimeWindowSBT_init( + timeWindowSBTIdentityVerifier.address, + config.identityVerifierInfo.verifierInitParams?.verifiedSBTInfo?.expirationPeriod, + config.identityVerifierInfo.verifierInitParams?.verifiedSBTInfo?.name, + config.identityVerifierInfo.verifierInitParams?.verifiedSBTInfo?.symbol, + config.identityVerifierInfo.verifierInitParams?.verifiedSBTInfo?.tokenURI + ), + "Initialize TimeWindowSBT contract" + ); + } else { + timeWindowSBT = await TimeWindowSBT.at(config.identityVerifierInfo.verifierInitParams?.verifiedSBTAddr); + } + + logger.logTransaction( + await timeWindowSBTIdentityVerifier.__SBTIdentityVerifier_init(zkpQueriesStorage.address, timeWindowSBT.address), + "Initialize TimeWindowSBTIdentityVerifier contract" + ); + } else { + timeWindowSBTIdentityVerifier = await TimeWindowSBTIdentityVerifier.at( + config.identityVerifierInfo.identityVerifierAddr + ); + } + + await TimeWindowSBTIdentityVerifier.setAsDeployed(timeWindowSBTIdentityVerifier); +}