Files
self/contracts/test/unit/IdentityVerificationHub.test.ts
2025-02-19 05:48:07 +01:00

488 lines
23 KiB
TypeScript

import { expect } from "chai";
import { deploySystemFixtures } from "../utils/deployment";
import { DeployedActors } from "../utils/types";
import { ethers } from "hardhat";
import { RegisterVerifierId, DscVerifierId } from "../../../common/src/constants/constants";
describe("Unit Tests for IdentityVerificationHub", () => {
let deployedActors: DeployedActors;
let snapshotId: string;
before(async () => {
deployedActors = await deploySystemFixtures();
snapshotId = await ethers.provider.send("evm_snapshot", []);
});
afterEach(async () => {
await ethers.provider.send("evm_revert", [snapshotId]);
snapshotId = await ethers.provider.send("evm_snapshot", []);
});
describe("Initialization", () => {
it("should initialize hub with correct parameters", async () => {
const {hub, registry, vcAndDisclose, register, dsc} = deployedActors;
// Check initial state
expect(await hub.registry()).to.equal(registry.target);
expect(await hub.vcAndDiscloseCircuitVerifier()).to.equal(vcAndDisclose.target);
const registerId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096;
const dscId = DscVerifierId.dsc_sha256_rsa_65537_4096;
expect(await hub.sigTypeToRegisterCircuitVerifiers(registerId)).to.equal(register.target);
expect(await hub.sigTypeToDscCircuitVerifiers(dscId)).to.equal(dsc.target);
const filter = hub.filters.HubInitialized;
const hubInitializedEvents = await hub.queryFilter(filter);
expect(hubInitializedEvents.length).to.equal(1);
const hubInitializedEvent = hubInitializedEvents[0];
expect(hubInitializedEvent.args.registry).to.equal(registry.target);
expect(hubInitializedEvent.args.vcAndDiscloseCircuitVerifier).to.equal(vcAndDisclose.target);
expect(hubInitializedEvent.args.registerCircuitVerifierIds).to.deep.equal([registerId]);
expect(hubInitializedEvent.args.registerCircuitVerifiers).to.deep.equal([register.target]);
expect(hubInitializedEvent.args.dscCircuitVerifierIds).to.deep.equal([dscId]);
expect(hubInitializedEvent.args.dscCircuitVerifiers).to.deep.equal([dsc.target]);
const initFilter = hub.filters.Initialized;
const initEvents = await hub.queryFilter(initFilter);
expect(initEvents.length).to.equal(1);
const initEvent = initEvents[0];
expect(initEvent.args.version).to.equal(1);
});
it("should not allow direct initialization of hub implementation", async () => {
const {owner, registry, vcAndDisclose} = deployedActors;
const HubFactory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubImpl = await HubFactory.deploy();
await expect(
hubImpl.initialize(
registry.target,
vcAndDisclose.target,
[],
[],
[],
[]
)
).to.be.revertedWithCustomError(hubImpl, "InvalidInitialization");
});
it("should revert when register circuit verifier arrays length mismatch", async () => {
const {owner, registry, vcAndDisclose} = deployedActors;
const HubFactory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubImpl = await HubFactory.deploy();
await hubImpl.waitForDeployment();
const initializeData = hubImpl.interface.encodeFunctionData("initialize", [
registry.target,
vcAndDisclose.target,
[1],
[],
[],
[]
]);
const hubProxyFactory = await ethers.getContractFactory("IdentityVerificationHub", owner);
await expect(
hubProxyFactory.deploy(hubImpl.target, initializeData)
).to.be.revertedWithCustomError(hubImpl, "LENGTH_MISMATCH");
});
it("should revert when DSC circuit verifier arrays length mismatch", async () => {
const {owner, registry, vcAndDisclose} = deployedActors;
const HubFactory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubImpl = await HubFactory.deploy();
await hubImpl.waitForDeployment();
const initializeData = hubImpl.interface.encodeFunctionData("initialize", [
registry.target,
vcAndDisclose.target,
[],
[],
[1],
[]
]);
const hubProxyFactory = await ethers.getContractFactory("IdentityVerificationHub", owner);
await expect(
hubProxyFactory.deploy(hubImpl.target, initializeData)
).to.be.revertedWithCustomError(hubImpl, "LENGTH_MISMATCH");
});
it("should not allow initialization after initialized", async () => {
const { hub, registry, vcAndDisclose } = deployedActors;
await expect(
hub.initialize(
registry.target,
vcAndDisclose.target,
[],
[],
[],
[]
)
).to.be.revertedWithCustomError(hub, "InvalidInitialization");
});
});
describe("Update functions", () => {
it("should update registry address", async () => {
const { hub, user1 } = deployedActors;
const newRegistryAddress = await user1.getAddress();
await expect(hub.updateRegistry(newRegistryAddress))
.to.emit(hub, "RegistryUpdated")
.withArgs(newRegistryAddress);
expect(await hub.registry()).to.equal(newRegistryAddress);
});
it("should not update registry address if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const newRegistryAddress = await user1.getAddress();
await expect(hub.connect(user1).updateRegistry(newRegistryAddress)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it ("should not update registry address if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const newRegistryAddress = await user1.getAddress();
await expect(hubImpl.updateRegistry(newRegistryAddress)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should update vc and disclose circuit verifier", async () => {
const { hub, user1 } = deployedActors;
const newVerifierAddress = await user1.getAddress();
await expect(hub.updateVcAndDiscloseCircuit(newVerifierAddress))
.to.emit(hub, "VcAndDiscloseCircuitUpdated")
.withArgs(newVerifierAddress);
expect(await hub.vcAndDiscloseCircuitVerifier()).to.equal(newVerifierAddress);
});
it("should not update vc and disclose circuit verifier if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const newVerifierAddress = await user1.getAddress();
await expect(hub.connect(user1).updateVcAndDiscloseCircuit(newVerifierAddress)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it("should not update vc and disclose circuit verifier if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const newVerifierAddress = await user1.getAddress();
await expect(hubImpl.updateVcAndDiscloseCircuit(newVerifierAddress)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should update register circuit verifier", async () => {
const { hub, user1 } = deployedActors;
const verifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hub.updateRegisterCircuitVerifier(verifierId, newVerifierAddress))
.to.emit(hub, "RegisterCircuitVerifierUpdated")
.withArgs(verifierId, newVerifierAddress);
expect(await hub.sigTypeToRegisterCircuitVerifiers(verifierId)).to.equal(newVerifierAddress);
});
it("should not update register circuit verifier if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const verifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hub.connect(user1).updateRegisterCircuitVerifier(verifierId, newVerifierAddress)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it("should not update register circuit verifier if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const verifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hubImpl.updateRegisterCircuitVerifier(verifierId, newVerifierAddress)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should update DSC verifier", async () => {
const { hub, user1 } = deployedActors;
const verifierId = DscVerifierId.dsc_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hub.updateDscVerifier(verifierId, newVerifierAddress))
.to.emit(hub, "DscCircuitVerifierUpdated")
.withArgs(verifierId, newVerifierAddress);
expect(await hub.sigTypeToDscCircuitVerifiers(verifierId)).to.equal(newVerifierAddress);
});
it("should not update DSC verifier if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const verifierId = DscVerifierId.dsc_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hub.connect(user1).updateDscVerifier(verifierId, newVerifierAddress)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it("should not update DSC verifier if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const verifierId = DscVerifierId.dsc_sha256_rsa_65537_4096;
const newVerifierAddress = await user1.getAddress();
await expect(hubImpl.updateDscVerifier(verifierId, newVerifierAddress)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should batch update register circuit verifiers", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hub.batchUpdateRegisterCircuitVerifiers(verifierIds, newVerifierAddresses))
.to.emit(hub, "RegisterCircuitVerifierUpdated")
.withArgs(verifierIds[0], newVerifierAddresses[0])
.to.emit(hub, "RegisterCircuitVerifierUpdated")
.withArgs(verifierIds[1], newVerifierAddresses[1]);
for (let i = 0; i < verifierIds.length; i++) {
expect(await hub.sigTypeToRegisterCircuitVerifiers(verifierIds[i]))
.to.equal(newVerifierAddresses[i]);
}
});
it("should not batch update register circuit verifiers if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hub.connect(user1).batchUpdateRegisterCircuitVerifiers(verifierIds, newVerifierAddresses)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it("should not batch update register circuit verifiers if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hubImpl.batchUpdateRegisterCircuitVerifiers(verifierIds, newVerifierAddresses))
.to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should not batch update register verifiers if length is not the same", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(
hub.batchUpdateRegisterCircuitVerifiers(verifierIds, newVerifierAddresses)
).to.be.revertedWithCustomError(hub, "LENGTH_MISMATCH");
});
it("should batch update DSC circuit verifiers", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hub.batchUpdateDscCircuitVerifiers(verifierIds, newVerifierAddresses))
.to.emit(hub, "DscCircuitVerifierUpdated")
.withArgs(verifierIds[0], newVerifierAddresses[0])
.to.emit(hub, "DscCircuitVerifierUpdated")
.withArgs(verifierIds[1], newVerifierAddresses[1]);
for (let i = 0; i < verifierIds.length; i++) {
expect(await hub.sigTypeToDscCircuitVerifiers(verifierIds[i]))
.to.equal(newVerifierAddresses[i]);
}
});
it("should not batch update DSC circuit verifiers if caller is not owner", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hub.connect(user1).batchUpdateDscCircuitVerifiers(verifierIds, newVerifierAddresses)).to.be.revertedWithCustomError(hub, "OwnableUnauthorizedAccount");
});
it("should not batch update DSC circuit verifiers if caller is not proxy", async () => {
const { hubImpl, user1 } = deployedActors;
const verifierIds = [1, 2];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(hubImpl.batchUpdateDscCircuitVerifiers(verifierIds, newVerifierAddresses))
.to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should not batch update dsc verifiers if length is not the same", async () => {
const { hub, user1 } = deployedActors;
const verifierIds = [1];
const newVerifierAddresses = [await user1.getAddress(), await user1.getAddress()];
await expect(
hub.batchUpdateDscCircuitVerifiers(verifierIds, newVerifierAddresses)
).to.be.revertedWithCustomError(hub, "LENGTH_MISMATCH");
});
});
describe("View functions", () => {
it("should return correct registry address", async () => {
const { hub, registry } = deployedActors;
expect(await hub.registry()).to.equal(registry.target);
});
it("should not return when view function is called by non-proxy", async () => {
const { hubImpl } = deployedActors;
await expect(hubImpl.registry()).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should return correct vcAndDiscloseCircuitVerifier address", async () => {
const { hub, vcAndDisclose } = deployedActors;
expect(await hub.vcAndDiscloseCircuitVerifier()).to.equal(vcAndDisclose.target);
});
it("should not return when view function is called by non-proxy", async () => {
const { hubImpl } = deployedActors;
await expect(hubImpl.vcAndDiscloseCircuitVerifier()).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should return correct register circuit verifier address", async () => {
const { hub, register } = deployedActors;
const verifierId = RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096;
expect(await hub.sigTypeToRegisterCircuitVerifiers(verifierId)).to.equal(register.target);
});
it("should not return when view function is called by non-proxy", async () => {
const { hubImpl } = deployedActors;
await expect(hubImpl.sigTypeToRegisterCircuitVerifiers(1)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
it("should return correct dsc circuit verifier address", async () => {
const { hub, dsc } = deployedActors;
const verifierId = DscVerifierId.dsc_sha256_rsa_65537_4096;
expect(await hub.sigTypeToDscCircuitVerifiers(verifierId)).to.equal(dsc.target);
});
it("should not return when view function is called by non-proxy", async () => {
const { hubImpl } = deployedActors;
await expect(hubImpl.sigTypeToDscCircuitVerifiers(1)).to.be.revertedWithCustomError(hubImpl, "UUPSUnauthorizedCallContext");
});
});
describe("Upgradeabilitiy", () => {
it("should preserve state after upgrade", async () => {
const {hub, owner} = deployedActors;
const registryAddressBefore = await hub.registry();
const vcAndDiscloseCircuitVerifierBefore = await hub.vcAndDiscloseCircuitVerifier();
const registerCircuitVerifierIdsBefore = await hub.sigTypeToRegisterCircuitVerifiers(
RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096
);
const dscCircuitVerifierIdsBefore = await hub.sigTypeToDscCircuitVerifiers(
DscVerifierId.dsc_sha256_rsa_65537_4096
);
const HubV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubV2Implementation = await HubV2Factory.deploy();
await hubV2Implementation.waitForDeployment();
const hubAsImpl = await ethers.getContractAt(
"IdentityVerificationHubImplV1",
hub.target
);
await hubAsImpl.connect(owner).upgradeToAndCall(
hubV2Implementation.target,
"0x"
);
const hubV2 = await ethers.getContractAt("IdentityVerificationHubImplV1", hub.target);
const registryAddressAfter = await hubV2.registry();
expect(registryAddressAfter).to.equal(registryAddressBefore);
expect(await hubV2.vcAndDiscloseCircuitVerifier()).to.equal(vcAndDiscloseCircuitVerifierBefore);
expect(await hubV2.sigTypeToRegisterCircuitVerifiers(
RegisterVerifierId.register_sha256_sha256_sha256_rsa_65537_4096
)).to.equal(registerCircuitVerifierIdsBefore);
expect(await hubV2.sigTypeToDscCircuitVerifiers(
DscVerifierId.dsc_sha256_rsa_65537_4096
)).to.equal(dscCircuitVerifierIdsBefore);
const implementationSlot = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
const implementationAddress = await ethers.provider.getStorage(hub.target, implementationSlot);
expect(ethers.zeroPadValue(implementationAddress, 32))
.to.equal(ethers.zeroPadValue(hubV2Implementation.target.toString(), 32));
});
it("should not allow non-proxy to upgrade implementation", async() => {
const {hub, hubImpl, owner, user1} = deployedActors;
const HubV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubV2Implementation = await HubV2Factory.deploy();
await hubV2Implementation.waitForDeployment();
const hubAsImpl = await ethers.getContractAt(
"IdentityVerificationHubImplV1",
hub.target
);
await expect(
hubImpl.connect(owner).upgradeToAndCall(
hubV2Implementation.target,
"0x"
)
).to.be.revertedWithCustomError(hubAsImpl, "UUPSUnauthorizedCallContext");
});
it("should not allow non-owner to upgrade implementation", async () => {
const {hub, owner, user1} = deployedActors;
const HubV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubV2Implementation = await HubV2Factory.deploy();
await hubV2Implementation.waitForDeployment();
const hubAsImpl = await ethers.getContractAt(
"IdentityVerificationHubImplV1",
hub.target
);
await expect(
hubAsImpl.connect(user1).upgradeToAndCall(
hubV2Implementation.target,
"0x"
)
).to.be.revertedWithCustomError(hubAsImpl, "OwnableUnauthorizedAccount");
});
it("should not allow implementation contract to be initialized directly", async () => {
const {hub, owner} = deployedActors;
const HubV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubV2Implementation = await HubV2Factory.deploy();
await hubV2Implementation.waitForDeployment();
await expect(
hubV2Implementation.initialize(
ethers.ZeroAddress,
ethers.ZeroAddress,
[],
[],
[],
[]
)
).to.be.revertedWithCustomError(hub, "InvalidInitialization");
});
it("should not allow direct calls to implementation contract", async () => {
const {hub, owner} = deployedActors;
const HubV2Factory = await ethers.getContractFactory("IdentityVerificationHubImplV1", owner);
const hubV2Implementation = await HubV2Factory.deploy();
await hubV2Implementation.waitForDeployment();
await expect(
hubV2Implementation.updateRegistry(ethers.ZeroAddress)
).to.be.revertedWithCustomError(hubV2Implementation, "UUPSUnauthorizedCallContext");
});
});
});