Skip to content

Commit

Permalink
added simple test code for sbt contract and mock contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
motemotech committed Oct 6, 2024
1 parent d60e749 commit 77fda8b
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 0 deletions.
12 changes: 12 additions & 0 deletions common/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@ export function castCSCAProof(proof: any): Proof {
}
}

export type SBTProof = {
nullifier: string,
revealedData_packed: string[],
attestation_id: string,
merkle_root: string,
scope: string,
current_date: number[] | string[],
user_identifier: string,
a: [string, string],
b: [[string, string], [string, string]],
c: [string, string]
}
50 changes: 50 additions & 0 deletions contracts/contracts/mocks/MockRegister.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {IRegister} from "../interfaces/IRegister.sol";

contract MockRegister is IRegister {

function validateProof(
RegisterProof calldata proof,
CSCAProof calldata proof_csca,
uint256 signature_algorithm,
uint256 signature_algorithm_csca
) external {}

function verifyProofRegister(
RegisterProof calldata proof,
uint256 signature_algorithm
) external view returns (bool) {
return true;
}

function verifyProofCSCA(
CSCAProof calldata proof,
uint256 signature_algorithm_csca
) external view returns (bool) {
return true;
}

function checkRoot(uint root) external view returns (bool) {
if (root == uint(1)) {
return false;
}
return true;
}

function getMerkleTreeSize() external view returns (uint) {
return uint(16);
}

function getMerkleRoot() external view returns (uint) {
return uint(0);
}

function indexOf(uint commitment) external view returns (uint) {
return uint(0);
}

function devAddCommitment(uint commitment) external {}

}
16 changes: 16 additions & 0 deletions contracts/contracts/mocks/MockVerifier_disclose.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract MockVerifier_disclose {
function verifyProof(
uint[2] calldata _pA,
uint[2][2] calldata _pB,
uint[2] calldata _pC,
uint[14] calldata _pubSignals
) public view returns (bool) {
if (_pubSignals[0] == 1) {
return false;
}
return true;
}
}
236 changes: 236 additions & 0 deletions contracts/test/TestSBT.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import { ethers } from "hardhat";
import { expect, assert } from "chai";
import { BigNumberish, Block, dataLength } from "ethers";
import { genMockPassportData } from "../../common/src/utils/genMockPassportData";
import {
generateCircuitInputsProve,
generateCircuitInputsDisclose
} from "../../common/src/utils/generateInputs";
import { getCSCAModulusMerkleTree } from "../../common/src/utils/csca";
import { formatRoot } from "../../common/src/utils/utils";
import { SBTProof } from "../../common/src/utils/types";
import { IMT } from "../../common/node_modules/@zk-kit/imt";

describe("Test SBT Contract", function () {

let verifier_disclose: any;
let formatter: any;
let registry: any;
let sbt: any;

let owner: any;
let addr1: any;
let addr2: any;

let merkleTree: IMT;

this.beforeEach(async function () {
// TODO: I need to figure out what is deploy options

[owner, addr1, addr2] = await ethers.getSigners();

const verifierDiscloseFactory = await ethers.getContractFactory("Verifier_disclose");
verifier_disclose = await verifierDiscloseFactory.deploy();
await verifier_disclose.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`);

const formatterFactory = await ethers.getContractFactory("Formatter");
formatter = await formatterFactory.deploy();
await formatter.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `formatter deployed to ${formatter.target}`);

const registryFactory = await ethers.getContractFactory("Registry");
// I need to figure out this merkle root
merkleTree = getCSCAModulusMerkleTree();
registry = await registryFactory.deploy(formatRoot(merkleTree.root))
// console.log("merkleRoot: ", formatRoot(merkleTree.root));
await registry.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `register deployed to ${registry.target}`);

const sbtFactory = await ethers.getContractFactory("SBT");
sbt = await sbtFactory.deploy(
verifier_disclose,
formatter,
registry
);
await sbt.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${sbt.target}`);
});

describe("Test mint and attr functions in SBT", function () {
this.beforeEach(async function () {
console.log('\x1b[36m%s\x1b[0m', `Deploy sbt with mock verifier again`);
const verifierDiscloseFactory = await ethers.getContractFactory("MockVerifier_disclose");
verifier_disclose = await verifierDiscloseFactory.deploy();
await verifier_disclose.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`);

const registerFactory = await ethers.getContractFactory("MockRegister");
registry = await registerFactory.deploy();
await registry.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `registry deployed to ${registry.target}`);

const sbtFactory = await ethers.getContractFactory("SBT");
sbt = await sbtFactory.deploy(
verifier_disclose,
formatter,
registry
);
await sbt.waitForDeployment();
console.log('\x1b[34m%s\x1b[0m', `sbt deployed to ${sbt.target}`);
});

it("Test: mint, should be reverted if register.checkRoot returns false", async function() {
let mockSBTProof: SBTProof = {
nullifier: "0",
revealedData_packed: ["31", "32", "33"],
attestation_id: "0",
merkle_root: "1",
scope: "1",
current_date: getDateNum(),
user_identifier: addr1.address,
a: ["1", "1"],
b: [["1", "1"], ["1", "1"]],
c: ["1", "1"],
};

await expect(sbt.mint(mockSBTProof)).to.be.revertedWith("Invalid merkle root");
});

it("Test:mint, should be reverted if currentTimestamp is not within a +1 day range", async function() {
let passedTwoDays = new Date();
passedTwoDays.setUTCDate(passedTwoDays.getUTCDate() + 2);

let mockSBTProof: SBTProof = {
nullifier: "0",
revealedData_packed: ["31", "32", "33"],
attestation_id: "0",
merkle_root: formatRoot(merkleTree.root),
scope: "1",
current_date: getDateNum(passedTwoDays),
user_identifier: addr1.address,
a: ["1", "1"],
b: [["1", "1"], ["1", "1"]],
c: ["1", "1"],
};

await expect(sbt.mint(mockSBTProof)).to.be.revertedWith("Current date is not within the valid range");
});

it("Test:mint, should be reverted if currentTimestamp is not within a -1 day range", async function() {
let twoDaysBefore = new Date();
twoDaysBefore.setUTCDate(twoDaysBefore.getUTCDate() - 2);

let mockSBTProof: SBTProof = {
nullifier: "0",
revealedData_packed: ["31", "32", "33"],
attestation_id: "0",
merkle_root: formatRoot(merkleTree.root),
scope: "1",
current_date: getDateNum(twoDaysBefore),
user_identifier: addr1.address,
a: ["1", "1"],
b: [["1", "1"], ["1", "1"]],
c: ["1", "1"],
};

await expect(sbt.mint(mockSBTProof)).to.be.revertedWith("Current date is not within the valid range");
});

it("Test:mint, should be reverted if verifyProof returns false", async function () {
let mockSBTProof: SBTProof = {
nullifier: "1",
revealedData_packed: ["31", "32", "33"],
attestation_id: "0",
merkle_root: formatRoot(merkleTree.root),
scope: "1",
current_date: getDateNum(),
user_identifier: addr1.address,
a: ["1", "1"],
b: [["1", "1"], ["1", "1"]],
c: ["1", "1"],
};

await expect(sbt.mint(mockSBTProof)).to.be.revertedWith("Invalid Proof");
});

it("Test:mint, should mint token if all validation was passed", async function () {
let mockSBTProof: SBTProof = {
nullifier: "0",
revealedData_packed: ["31", "32", "33"],
attestation_id: "0",
merkle_root: formatRoot(merkleTree.root),
scope: "1",
current_date: getDateNum(),
user_identifier: addr1.address,
a: ["1", "1"],
b: [["1", "1"], ["1", "1"]],
c: ["1", "1"],
};

await sbt.mint(mockSBTProof);

expect(await sbt.totalSupply()).to.be.equal(1);
expect(await sbt.ownerOf(0)).to.be.equal(addr1.address);
});

});

describe("Test utils functions in SBT", function() {

it("Test: getCurrentTimestamp, should matches with actual timestamp within 1 day", async function () {

const dateNum = getDateNum();
const block = await ethers.provider.getBlock("latest") as Block;
const blockTimestamp = BigInt(block.timestamp);
const currentTimestamp = await sbt.getCurrentTimestamp(dateNum);

const difference = currentTimestamp - blockTimestamp;
const differenceAbs = (difference < 0n) ? -difference : difference;

// Check if generated timestamp is within 1 day of block.timestamp
expect(differenceAbs).to.be.lte(86400);
});

it ("Test: isStringEqual, Should return true when pass same string to isStringEqual", async function () {
let string_a = "openpassport";
let string_b = "openpassport";
expect(await sbt.isStringEqual(string_a, string_b)).to.equal(true);
});

it ("Test: isStringEqual, Should return false when pass different string to isStringEqual", async function () {
let string_a = "openpassport";
let string_b = "closepassport";
expect(await sbt.isStringEqual(string_a, string_b)).to.equal(false);
});

it ("Test: substring, Should return specified substring", async function () {
const originalStr = "openpassport";
const start = 4;
const end = 9;
const expectedSubstr = "openpassport".substring(start, end);
const originalBytes = ethers.toUtf8Bytes(originalStr);
const resultBytes: string = await sbt.substring(originalBytes, start, end);
const resultStr = ethers.toUtf8String(resultBytes);
expect(resultStr).to.equal(expectedSubstr);
});
});
});

function getDateNum(date: Date = new Date()): number[] {

const year = date.getUTCFullYear() % 100;
const month = date.getUTCMonth() + 1;
const day = date.getUTCDate();

const dateNum = [
Math.floor(year / 10),
year % 10,
Math.floor(month / 10),
month % 10,
Math.floor(day / 10),
day % 10,
];

return dateNum;
}

0 comments on commit 77fda8b

Please sign in to comment.