add example contract how to integrate self verifier (#198)

This commit is contained in:
nicoshark
2025-02-22 15:15:53 -08:00
committed by GitHub
parent 002b383ea9
commit 01ceaa9f44
8 changed files with 203 additions and 261 deletions

View File

@@ -1,161 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
import {IIdentityRegistryV1} from "../interfaces/IIdentityRegistryV1.sol";
import {CircuitConstants} from "../constants/CircuitConstants.sol";
import {IPassportAirdropRoot} from "../interfaces/IPassportAirdropRoot.sol";
/**
* @title PassportAirdropRoot
* @notice Abstract contract to manage passport airdrop functionality, including registration with vc and disclose proof.
* @dev Provides the core registration logic and verification of proofs. Inherits from IPassportAirdropRoot.
*/
abstract contract PassportAirdropRoot is
IPassportAirdropRoot
{
// ====================================================
// Storage Variables
// ====================================================
/// @notice Expected scope for the proof verification.
uint256 internal immutable _scope;
/// @notice Expected attestation identifier for the identity behind the proof.
uint256 internal immutable _attestationId;
/// @notice Target root timestamp used for additional verification.
uint256 internal immutable _targetRootTimestamp;
/// @notice Verification configuration settings.
IPassportAirdropRoot.VerificationConfig internal _verificationConfig;
/// @notice Instance of the Identity Verification Hub.
IIdentityVerificationHubV1 internal immutable _identityVerificationHub;
/// @notice Instance of the Identity Registry.
IIdentityRegistryV1 internal immutable _identityRegistry;
/// @notice Mapping recording used nullifiers to prevent double registration.
mapping(uint256 => uint256) internal _nullifiers;
/// @notice Mapping tracking registered user identifiers.
mapping(uint256 => bool) internal _registeredUserIdentifiers;
// ====================================================
// Events
// ====================================================
/**
* @notice Emitted when a new user identifier is successfully registered.
* @param registeredUserIdentifier The user identifier that has been registered.
* @param nullifier The nullifier associated with the registered commitment.
*/
event UserIdentifierRegistered(uint256 indexed registeredUserIdentifier, uint256 indexed nullifier);
// ====================================================
// Errors
// ====================================================
/// @dev Reverts if the provided nullifier has already been registered.
error RegisteredNullifier();
/// @dev Reverts if the attestation identifier in the proof is invalid.
error InvalidAttestationId();
/// @dev Reverts if the proof scope does not match the expected scope.
error InvalidScope();
/// @dev Reverts if the identity root timestamp is not valid.
error InvalidTimestamp();
/// @dev Reverts if the user identifier is not valid.
error InvalidUserIdentifier();
/**
* @notice Initializes the PassportAirdropRoot contract.
* @dev Sets up the identity verification hub, identity registry, expected scope, attestation, and timestamp along with verification configuration.
* @param identityVerificationHub The address of the Identity Verification Hub.
* @param identityRegistry The address of the Identity Registry.
* @param scope The expected proof scope.
* @param attestationId The expected attestation identifier.
* @param targetRootTimestamp The target timestamp for root verification (set to 0 to disable).
* @param olderThanEnabled Flag indicating if the 'olderThan' attribute should be verified.
* @param olderThan Value to compare against for 'olderThan' verification.
* @param forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
* @param forbiddenCountriesListPacked Packed list of forbidden countries.
* @param ofacEnabled Array of flags indicating if each OFAC verification is enabled.
*/
constructor(
address identityVerificationHub,
address identityRegistry,
uint256 scope,
uint256 attestationId,
uint256 targetRootTimestamp,
bool olderThanEnabled,
uint256 olderThan,
bool forbiddenCountriesEnabled,
uint256[4] memory forbiddenCountriesListPacked,
bool[3] memory ofacEnabled
) {
_identityVerificationHub = IIdentityVerificationHubV1(identityVerificationHub);
_identityRegistry = IIdentityRegistryV1(identityRegistry);
_scope = scope;
_attestationId = attestationId;
_targetRootTimestamp = targetRootTimestamp;
_verificationConfig.olderThanEnabled = olderThanEnabled;
_verificationConfig.olderThan = olderThan;
_verificationConfig.forbiddenCountriesEnabled = forbiddenCountriesEnabled;
_verificationConfig.forbiddenCountriesListPacked = forbiddenCountriesListPacked;
_verificationConfig.ofacEnabled = ofacEnabled;
}
/**
* @notice Internal function to register a user address based on a valid VC and Disclose proof.
* @dev Verifies the proof against the expected scope, attestation identifier, and, if applicable,
* ensures the identity commitment root was generated at the target timestamp. Records
* the nullifier and marks the corresponding user identifier as registered.
* @param proof The VC and Disclose proof containing public signals and proof data.
* @return userIdentifier The user identifier extracted from the proof.
*/
function _registerAddress(
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
)
internal
returns (uint256 userIdentifier)
{
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
revert InvalidScope();
}
if (_nullifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_NULLIFIER_INDEX]] != 0) {
revert RegisteredNullifier();
}
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
revert InvalidAttestationId();
}
if (proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX] == 0) {
revert InvalidUserIdentifier();
}
IIdentityVerificationHubV1.VcAndDiscloseVerificationResult memory result = _identityVerificationHub.verifyVcAndDisclose(
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
olderThanEnabled: _verificationConfig.olderThanEnabled,
olderThan: _verificationConfig.olderThan,
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
ofacEnabled: _verificationConfig.ofacEnabled,
vcAndDiscloseProof: proof
})
);
if (_targetRootTimestamp != 0) {
if (_identityRegistry.rootTimestamps(result.identityCommitmentRoot) != _targetRootTimestamp) {
revert InvalidTimestamp();
}
}
_nullifiers[result.nullifier] = proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
_registeredUserIdentifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX]] = true;
emit UserIdentifierRegistered(proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX], result.nullifier);
return proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
}
}

View File

@@ -0,0 +1,110 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
import {ISelfVerificationRoot} from "../interfaces/ISelfVerificationRoot.sol";
import {CircuitConstants} from "../constants/CircuitConstants.sol";
/**
* @title SelfVerificationRoot
* @notice Abstract base contract to be integrated with self's verification infrastructure
* @dev Provides base functionality for verifying and disclosing identity credentials
*/
abstract contract SelfVerificationRoot is ISelfVerificationRoot {
// ====================================================
// Storage Variables
// ====================================================
/// @notice The scope value that proofs must match
/// @dev Used to validate that submitted proofs match the expected scope
uint256 internal _scope;
/// @notice The attestation ID that proofs must match
/// @dev Used to validate that submitted proofs contain the correct attestation
uint256 internal _attestationId;
/// @notice Configuration settings for the verification process
/// @dev Contains settings for age verification, country restrictions, and OFAC checks
ISelfVerificationRoot.VerificationConfig internal _verificationConfig;
/// @notice Reference to the identity verification hub contract
/// @dev Immutable reference used for proof verification
IIdentityVerificationHubV1 internal immutable _identityVerificationHub;
// ====================================================
// Errors
// ====================================================
/// @notice Error thrown when the proof's scope doesn't match the expected scope
/// @dev Triggered in verifySelfProof when scope validation fails
error InvalidScope();
/// @notice Error thrown when the proof's attestation ID doesn't match the expected ID
/// @dev Triggered in verifySelfProof when attestation ID validation fails
error InvalidAttestationId();
/**
* @notice Initializes the SelfVerificationRoot contract.
* @param identityVerificationHub The address of the Identity Verification Hub.
* @param scope The expected proof scope for user registration.
* @param attestationId The expected attestation identifier required in proofs.
* @param olderThanEnabled Flag indicating if 'olderThan' verification is enabled.
* @param olderThan Value for 'olderThan' verification.
* @param forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
* @param forbiddenCountriesListPacked Packed list of forbidden countries.
* @param ofacEnabled Array of flags indicating which OFAC checks are enabled. [passportNo, nameAndDob, nameAndYob]
*/
constructor(
address identityVerificationHub,
uint256 scope,
uint256 attestationId,
bool olderThanEnabled,
uint256 olderThan,
bool forbiddenCountriesEnabled,
uint256[4] memory forbiddenCountriesListPacked,
bool[3] memory ofacEnabled
) {
_identityVerificationHub = IIdentityVerificationHubV1(identityVerificationHub);
_scope = scope;
_attestationId = attestationId;
_verificationConfig.olderThanEnabled = olderThanEnabled;
_verificationConfig.olderThan = olderThan;
_verificationConfig.forbiddenCountriesEnabled = forbiddenCountriesEnabled;
_verificationConfig.forbiddenCountriesListPacked = forbiddenCountriesListPacked;
_verificationConfig.ofacEnabled = ofacEnabled;
}
/**
* @notice Verifies a self-proof
* @dev Validates scope and attestation ID before performing verification through the identity hub
* @param proof The proof data for verification and disclosure
*/
function verifySelfProof(
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
)
public
virtual
{
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
revert InvalidScope();
}
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
revert InvalidAttestationId();
}
_identityVerificationHub.verifyVcAndDisclose(
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
olderThanEnabled: _verificationConfig.olderThanEnabled,
olderThan: _verificationConfig.olderThan,
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
ofacEnabled: _verificationConfig.ofacEnabled,
vcAndDiscloseProof: proof
})
);
}
}

View File

@@ -3,11 +3,12 @@ pragma solidity 0.8.28;
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {PassportAirdropRoot} from "../abstract/PassportAirdropRoot.sol";
import {IPassportAirdropRoot} from "../interfaces/IPassportAirdropRoot.sol";
import {SelfVerificationRoot} from "../abstract/SelfVerificationRoot.sol";
import {ISelfVerificationRoot} from "../interfaces/ISelfVerificationRoot.sol";
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {CircuitConstants} from "../constants/CircuitConstants.sol";
/**
* @title Airdrop (Experimental)
@@ -16,7 +17,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
* **WARNING:** This contract has not been audited and is NOT intended for production use.
* @dev Inherits from PassportAirdropRoot for registration logic and Ownable for administrative control.
*/
contract Airdrop is PassportAirdropRoot, Ownable {
contract Airdrop is SelfVerificationRoot, Ownable {
using SafeERC20 for IERC20;
// ====================================================
@@ -34,6 +35,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
/// @notice Indicates whether the claim phase is active.
bool public isClaimOpen;
mapping(uint256 => uint256) internal _nullifiers;
mapping(uint256 => bool) internal _registeredUserIdentifiers;
// ====================================================
// Errors
// ====================================================
@@ -51,6 +55,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
/// @notice Reverts when a claim is attempted while claiming is not enabled.
error ClaimNotOpen();
error RegisteredNullifier();
error InvalidUserIdentifier();
// ====================================================
// Events
// ====================================================
@@ -69,6 +76,8 @@ contract Airdrop is PassportAirdropRoot, Ownable {
/// @notice Emitted when the claim phase is closed.
event ClaimClose();
event UserIdentifierRegistered(uint256 indexed registeredUserIdentifier, uint256 indexed nullifier);
// ====================================================
// Constructor
// ====================================================
@@ -78,11 +87,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
* @dev Initializes the airdrop parameters, zero-knowledge verification configuration,
* and sets the ERC20 token to be distributed.
* @param _identityVerificationHub The address of the Identity Verification Hub.
* @param _identityRegistry The address of the Identity Registry.
* @param _scope The expected proof scope for user registration.
* @param _attestationId The expected attestation identifier required in proofs.
* @param _token The address of the ERC20 token for airdrop.
* @param _targetRootTimestamp The target root timestamp for additional verification (0 to disable).
* @param _olderThanEnabled Flag indicating if 'olderThan' verification is enabled.
* @param _olderThan Value for 'olderThan' verification.
* @param _forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
@@ -91,23 +98,19 @@ contract Airdrop is PassportAirdropRoot, Ownable {
*/
constructor(
address _identityVerificationHub,
address _identityRegistry,
uint256 _scope,
uint256 _attestationId,
address _token,
uint256 _targetRootTimestamp,
bool _olderThanEnabled,
uint256 _olderThan,
bool _forbiddenCountriesEnabled,
uint256[4] memory _forbiddenCountriesListPacked,
bool[3] memory _ofacEnabled
)
PassportAirdropRoot(
SelfVerificationRoot(
_identityVerificationHub,
_identityRegistry,
_scope,
_attestationId,
_targetRootTimestamp,
_olderThanEnabled,
_olderThan,
_forbiddenCountriesEnabled,
@@ -138,7 +141,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
* @param newVerificationConfig The new verification configuration.
*/
function setVerificationConfig(
IPassportAirdropRoot.VerificationConfig memory newVerificationConfig
ISelfVerificationRoot.VerificationConfig memory newVerificationConfig
) external onlyOwner {
_verificationConfig = newVerificationConfig;
}
@@ -184,13 +187,48 @@ contract Airdrop is PassportAirdropRoot, Ownable {
* @dev Reverts if the registration phase is not open.
* @param proof The VC and Disclose proof data used to verify and register the user.
*/
function registerAddress(
function verifySelfProof(
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
) external {
)
public
override
{
if (!isRegistrationOpen) {
revert RegistrationNotOpen();
}
_registerAddress(proof);
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
revert InvalidScope();
}
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
revert InvalidAttestationId();
}
if (_nullifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_NULLIFIER_INDEX]] != 0) {
revert RegisteredNullifier();
}
if (proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX] == 0) {
revert InvalidUserIdentifier();
}
IIdentityVerificationHubV1.VcAndDiscloseVerificationResult memory result = _identityVerificationHub.verifyVcAndDisclose(
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
olderThanEnabled: _verificationConfig.olderThanEnabled,
olderThan: _verificationConfig.olderThan,
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
ofacEnabled: _verificationConfig.ofacEnabled,
vcAndDiscloseProof: proof
})
);
_nullifiers[result.nullifier] = proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
_registeredUserIdentifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX]] = true;
emit UserIdentifierRegistered(proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX], result.nullifier);
}
/**
@@ -222,7 +260,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
* @notice Retrieves the current verification configuration.
* @return The verification configuration used for registration.
*/
function getVerificationConfig() external view returns (IPassportAirdropRoot.VerificationConfig memory) {
function getVerificationConfig() external view returns (ISelfVerificationRoot.VerificationConfig memory) {
return _verificationConfig;
}
@@ -266,7 +304,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof();
// Mark as claimed and transfer tokens.
_setClaimed(index);
_setClaimed();
IERC20(token).safeTransfer(msg.sender, amount);
emit Claimed(index, msg.sender, amount);
@@ -279,9 +317,8 @@ contract Airdrop is PassportAirdropRoot, Ownable {
/**
* @notice Internal function to mark the caller as having claimed their tokens.
* @dev Updates the claimed mapping.
* @param index The index of the claim (unused in storage, provided for event consistency).
*/
function _setClaimed(uint256 index) internal {
function _setClaimed() internal {
claimed[msg.sender] = true;
}
}

View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IVcAndDiscloseCircuitVerifier} from "./IVcAndDiscloseCircuitVerifier.sol";
interface ISelfVerificationRoot {
struct VerificationConfig {
bool olderThanEnabled;
uint256 olderThan;
bool forbiddenCountriesEnabled;
uint256[4] forbiddenCountriesListPacked;
bool[3] ofacEnabled;
}
function verifySelfProof(
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
) external;
}

View File

@@ -68,18 +68,14 @@ describe("Airdrop", () => {
commitment
);
const root = await deployedActors.registry.getIdentityCommitmentMerkleRoot();
const timestamp = await deployedActors.registry.rootTimestamps(root);
countriesListPacked = splitHexFromBack(reverseBytes(Formatter.bytesToHexString(new Uint8Array(formatCountriesList(forbiddenCountriesList)))));
const airdropFactory = await ethers.getContractFactory("Airdrop");
airdrop = await airdropFactory.connect(deployedActors.owner).deploy(
deployedActors.hub.target,
deployedActors.registry.target,
castFromScope("test-airdrop"),
ATTESTATION_ID.E_PASSPORT,
token.target,
timestamp,
true,
20,
true,
@@ -198,7 +194,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
const tx = await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
const tx = await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
const receipt = await tx.wait();
const event = receipt?.logs.find(
@@ -227,7 +223,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).closeRegistration();
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "RegistrationNotOpen");
});
@@ -246,7 +242,7 @@ describe("Airdrop", () => {
);
await airdrop.connect(owner).openRegistration();
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "InvalidScope");
});
@@ -254,8 +250,8 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "RegisteredNullifier");
});
@@ -287,7 +283,7 @@ describe("Airdrop", () => {
);
await airdrop.connect(owner).openRegistration();
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "InvalidAttestationId");
});
@@ -310,58 +306,19 @@ describe("Airdrop", () => {
);
await airdrop.connect(owner).openRegistration();
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "InvalidUserIdentifier");
});
it("should not able to register address when rootTimestamp is different", async () => {
const {registry, owner, user1, mockPassport} = deployedActors;
const secondCommitment = generateCommitment(registerSecret, ATTESTATION_ID.INVALID_ATTESTATION_ID, mockPassport);
await registry.devAddIdentityCommitment(
ATTESTATION_ID.E_PASSPORT,
nullifier,
secondCommitment
);
const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]);
const invalidImt = new LeanIMT<bigint>(hashFunction);
invalidImt.insert(BigInt(commitment));
invalidImt.insert(BigInt(secondCommitment));
vcAndDiscloseProof = await generateVcAndDiscloseProof(
registerSecret,
BigInt(ATTESTATION_ID.E_PASSPORT).toString(),
deployedActors.mockPassport,
"test-airdrop",
new Array(88).fill("1"),
"1",
invalidImt,
"20",
undefined,
undefined,
undefined,
undefined,
forbiddenCountriesList,
(await deployedActors.user1.getAddress()).slice(2)
);
await airdrop.connect(owner).openRegistration();
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
.to.be.revertedWithCustomError(airdrop, "InvalidTimestamp");
});
it("should allow registration when targetRootTimestamp is 0", async () => {
const { hub, registry, owner, user1 } = deployedActors;
const airdropFactory = await ethers.getContractFactory("Airdrop");
const newAirdrop = await airdropFactory.connect(owner).deploy(
hub.target,
registry.target,
castFromScope("test-airdrop"),
ATTESTATION_ID.E_PASSPORT,
token.target,
0,
true,
20,
true,
@@ -371,34 +328,10 @@ describe("Airdrop", () => {
await newAirdrop.waitForDeployment();
await newAirdrop.connect(owner).openRegistration();
await expect(newAirdrop.connect(user1).registerAddress(vcAndDiscloseProof))
await expect(newAirdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
.to.not.be.reverted;
});
it("should revert with InvalidTimestamp when root timestamp does not match", async () => {
const { hub, registry, owner, user1 } = deployedActors;
const airdropFactory = await ethers.getContractFactory("Airdrop");
const newAirdrop = await airdropFactory.connect(owner).deploy(
hub.target,
registry.target,
castFromScope("test-airdrop"),
ATTESTATION_ID.E_PASSPORT,
token.target,
123456789,
true,
20,
true,
countriesListPacked,
[true, true, true],
);
await newAirdrop.waitForDeployment();
await newAirdrop.connect(owner).openRegistration();
await expect(newAirdrop.connect(user1).registerAddress(vcAndDiscloseProof))
.to.be.revertedWithCustomError(newAirdrop, "InvalidTimestamp");
});
it("should return correct scope", async () => {
const scope = await airdrop.getScope();
expect(scope).to.equal(castFromScope("test-airdrop"));
@@ -427,7 +360,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await airdrop.connect(owner).closeRegistration();
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
@@ -464,7 +397,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
const root = tree.getHexRoot();
@@ -484,7 +417,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await airdrop.connect(owner).closeRegistration();
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
@@ -504,7 +437,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await airdrop.connect(owner).closeRegistration();
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
const root = tree.getHexRoot();
@@ -529,7 +462,7 @@ describe("Airdrop", () => {
const { owner, user1 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await airdrop.connect(owner).closeRegistration();
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
const root = tree.getHexRoot();
@@ -550,7 +483,7 @@ describe("Airdrop", () => {
const { owner, user1, user2 } = deployedActors;
await airdrop.connect(owner).openRegistration();
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
await airdrop.connect(owner).closeRegistration();
const tree = new BalanceTree([

View File

@@ -168,7 +168,6 @@ export async function generateVcAndDiscloseRawProof(
forbiddenCountriesList,
userIdentifier
);
console.log("forbiddenCountriesList: ", vcAndDiscloseCircuitInputs.forbidden_countries_list);
console.log(CYAN, "=== Start generateVcAndDiscloseRawProof ===", RESET);
const startTime = performance.now();

View File

@@ -0,0 +1,2 @@
END_POINT=
SCOPE=

View File

@@ -34,3 +34,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
.env