Skip to content

Commit 4d978e6

Browse files
authored
[FEAT] Add CommitmentRegistry deploy script and local network config (#62)
* [FEAT] Add CommitmentRegistry deploy script and local network config * [FEAT] Use hardhat-upgrades for proxy deploy, add pagination tests
1 parent 9232380 commit 4d978e6

8 files changed

Lines changed: 155 additions & 67 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# DO NOT USE IN PRODUCTION
2+
# Same deployer key as host-chain (address: 0x4e6206fC78674E5eFf48Dcd0166060f95a832c60)
3+
KEY=0xb03608c1c1f1461ed55c1c2315ab27fe82e2fe4c289ff753dea99078848d27dd

contracts/internal/registry-chain/contracts/ERC1967Proxy.sol

Lines changed: 0 additions & 39 deletions
This file was deleted.

contracts/internal/registry-chain/hardhat.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ const config: HardhatUserConfig = {
1919
defaultNetwork: "hardhat",
2020
networks: {
2121
hardhat: { allowUnlimitedContractSize: true },
22+
localfhenix: {
23+
url: "http://127.0.0.1:42069",
24+
accounts: process.env.KEY ? [process.env.KEY] : [],
25+
},
26+
localfhenixk8s: {
27+
url: "http://hostchain:8547",
28+
accounts: process.env.KEY ? [process.env.KEY] : [],
29+
},
2230
arbitrumSepolia: {
2331
chainId: 421614,
2432
url: "https://little-convincing-fog.arbitrum-sepolia.quiknode.pro/e925be62bdfa8faab560daa332c0c95e26189870/",

contracts/internal/registry-chain/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"test": "hardhat test --network hardhat",
77
"test:gas": "REPORT_GAS=true hardhat test --network hardhat",
88
"compile": "hardhat compile",
9+
"task:deploy": "hardhat run scripts/deploy.ts",
910
"clean": "rimraf ./artifacts ./cache ./types ./.openzeppelin/*"
1011
},
1112
"author": "Fhenix",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import hre from "hardhat";
2+
import { deployUUPSProxy } from "../utils/deploy";
3+
4+
// OZ Relayer signer address (deterministic from dev keystore)
5+
const DEFAULT_POSTER_ADDRESS = "0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E";
6+
const OZ_RELAYER_ADDRESS = process.env.POSTER_ADDRESS || DEFAULT_POSTER_ADDRESS;
7+
8+
// Commitment version to activate (must match COMMITMENT_VERSION in fhe-engine)
9+
const INITIAL_VERSION = "0x0000000000000000000000000000000000000000000000000000000000000001";
10+
11+
async function main() {
12+
const [deployer] = await hre.ethers.getSigners();
13+
if (!process.env.POSTER_ADDRESS) {
14+
console.warn(`WARNING: POSTER_ADDRESS not set, using default dev address: ${DEFAULT_POSTER_ADDRESS}`);
15+
}
16+
console.log("Deploying CommitmentRegistry with account:", deployer.address);
17+
18+
const { proxy: registry, address: proxyAddress } = await deployUUPSProxy(
19+
"CommitmentRegistry",
20+
[deployer.address, OZ_RELAYER_ADDRESS],
21+
);
22+
23+
console.log("Owner:", deployer.address);
24+
console.log("Poster:", OZ_RELAYER_ADDRESS);
25+
26+
// Activate initial version
27+
const tx = await registry.setVersionStatus(INITIAL_VERSION, 1); // 1 = Active
28+
await tx.wait();
29+
console.log("Version", INITIAL_VERSION, "activated");
30+
31+
// Output the address in a parseable format for the deploy script
32+
console.log(`COMMITMENT_REGISTRY_ADDRESS=${proxyAddress}`);
33+
}
34+
35+
main().catch((error) => {
36+
console.error(error);
37+
process.exitCode = 1;
38+
});

contracts/internal/registry-chain/test/commitmentRegistry/CommitmentRegistry.behavior.ts

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect } from "chai";
22
import hre from "hardhat";
33
const { ethers } = hre;
4+
import { upgrades } from "hardhat";
45

56
function randomBytes32(): string {
67
return ethers.hexlify(ethers.randomBytes(32));
@@ -50,29 +51,23 @@ export function shouldBehaveLikeCommitmentRegistry(): void {
5051

5152
it("should revert when initializing with zero owner", async function () {
5253
const CommitmentRegistry = await ethers.getContractFactory("CommitmentRegistry");
53-
const impl = await CommitmentRegistry.deploy();
54-
await impl.waitForDeployment();
55-
const ERC1967Proxy = await ethers.getContractFactory("ERC1967Proxy");
56-
const initData = CommitmentRegistry.interface.encodeFunctionData("initialize", [
57-
ethers.ZeroAddress,
58-
this.poster.address,
59-
]);
6054
await expect(
61-
ERC1967Proxy.deploy(await impl.getAddress(), initData)
55+
upgrades.deployProxy(
56+
CommitmentRegistry,
57+
[ethers.ZeroAddress, this.poster.address],
58+
{ kind: "uups", initializer: "initialize" },
59+
)
6260
).to.be.reverted;
6361
});
6462

6563
it("should revert when initializing with zero poster", async function () {
6664
const CommitmentRegistry = await ethers.getContractFactory("CommitmentRegistry");
67-
const impl = await CommitmentRegistry.deploy();
68-
await impl.waitForDeployment();
69-
const ERC1967Proxy = await ethers.getContractFactory("ERC1967Proxy");
70-
const initData = CommitmentRegistry.interface.encodeFunctionData("initialize", [
71-
this.owner.address,
72-
ethers.ZeroAddress,
73-
]);
7465
await expect(
75-
ERC1967Proxy.deploy(await impl.getAddress(), initData)
66+
upgrades.deployProxy(
67+
CommitmentRegistry,
68+
[this.owner.address, ethers.ZeroAddress],
69+
{ kind: "uups", initializer: "initialize" },
70+
)
7671
).to.be.reverted;
7772
});
7873
});
@@ -593,6 +588,70 @@ export function shouldBehaveLikeCommitmentRegistry(): void {
593588
expect(await this.registry.getSize(VERSION_1)).to.equal(1);
594589
});
595590

591+
it("should return handles with getHandles pagination", async function () {
592+
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
593+
const handles = Array.from({ length: 10 }, () => randomBytes32());
594+
const commitHashes = Array.from({ length: 10 }, () => randomBytes32());
595+
const registryAsPoster = this.registry.connect(this.poster);
596+
await registryAsPoster.postCommitments(VERSION_1, handles, commitHashes);
597+
598+
// First page
599+
const page1 = await this.registry.getHandles(VERSION_1, 0, 5);
600+
expect(page1.length).to.equal(5);
601+
for (let i = 0; i < 5; i++) {
602+
expect(page1[i]).to.equal(handles[i]);
603+
}
604+
605+
// Second page
606+
const page2 = await this.registry.getHandles(VERSION_1, 5, 5);
607+
expect(page2.length).to.equal(5);
608+
for (let i = 0; i < 5; i++) {
609+
expect(page2[i]).to.equal(handles[5 + i]);
610+
}
611+
});
612+
613+
it("should return empty array when offset exceeds total", async function () {
614+
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
615+
const registryAsPoster = this.registry.connect(this.poster);
616+
await registryAsPoster.postCommitments(VERSION_1, [randomBytes32()], [randomBytes32()]);
617+
618+
const result = await this.registry.getHandles(VERSION_1, 100, 10);
619+
expect(result.length).to.equal(0);
620+
});
621+
622+
it("should clamp limit when it exceeds remaining items", async function () {
623+
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
624+
const handles = Array.from({ length: 3 }, () => randomBytes32());
625+
const commitHashes = Array.from({ length: 3 }, () => randomBytes32());
626+
const registryAsPoster = this.registry.connect(this.poster);
627+
await registryAsPoster.postCommitments(VERSION_1, handles, commitHashes);
628+
629+
const result = await this.registry.getHandles(VERSION_1, 1, 100);
630+
expect(result.length).to.equal(2);
631+
expect(result[0]).to.equal(handles[1]);
632+
expect(result[1]).to.equal(handles[2]);
633+
});
634+
635+
it("should return handle by index", async function () {
636+
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
637+
const handles = Array.from({ length: 5 }, () => randomBytes32());
638+
const commitHashes = Array.from({ length: 5 }, () => randomBytes32());
639+
const registryAsPoster = this.registry.connect(this.poster);
640+
await registryAsPoster.postCommitments(VERSION_1, handles, commitHashes);
641+
642+
for (let i = 0; i < 5; i++) {
643+
expect(await this.registry.getHandleByIndex(VERSION_1, i)).to.equal(handles[i]);
644+
}
645+
});
646+
647+
it("should revert when getHandleByIndex is out of bounds", async function () {
648+
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
649+
const registryAsPoster = this.registry.connect(this.poster);
650+
await registryAsPoster.postCommitments(VERSION_1, [randomBytes32()], [randomBytes32()]);
651+
652+
await expect(this.registry.getHandleByIndex(VERSION_1, 1)).to.be.reverted;
653+
});
654+
596655
it("should still return commitments after version is Revoked", async function () {
597656
await this.registry.setVersionStatus(VERSION_1, VersionStatus.Active);
598657
const handle = randomBytes32();
Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import hre from "hardhat";
22
const { ethers } = hre;
3+
import { upgrades } from "hardhat";
34
import { BaseContract } from "ethers";
45

56
export interface CommitmentRegistryFixture {
@@ -13,18 +14,12 @@ export async function deployCommitmentRegistryFixture(): Promise<CommitmentRegis
1314
const [owner, poster, otherAccount] = await ethers.getSigners();
1415

1516
const CommitmentRegistry = await ethers.getContractFactory("CommitmentRegistry");
16-
const impl = await CommitmentRegistry.deploy();
17-
await impl.waitForDeployment();
18-
19-
const ERC1967Proxy = await ethers.getContractFactory("ERC1967Proxy");
20-
const initData = CommitmentRegistry.interface.encodeFunctionData("initialize", [
21-
owner.address,
22-
poster.address,
23-
]);
24-
const proxy = await ERC1967Proxy.deploy(await impl.getAddress(), initData);
25-
await proxy.waitForDeployment();
26-
27-
const registry = CommitmentRegistry.attach(await proxy.getAddress());
17+
const deployed = await upgrades.deployProxy(
18+
CommitmentRegistry,
19+
[owner.address, poster.address],
20+
{ kind: "uups", initializer: "initialize" },
21+
);
22+
const registry = await deployed.waitForDeployment();
2823

2924
return { registry, owner, poster, otherAccount };
3025
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ethers, upgrades } from "hardhat";
2+
import { Contract } from "ethers";
3+
4+
/**
5+
* Deploys a UUPS proxy for the given contract.
6+
* @param contractName The contract to deploy behind a proxy
7+
* @param initArgs Arguments passed to the initialize function
8+
* @returns The proxy contract instance and its address
9+
*/
10+
export async function deployUUPSProxy(
11+
contractName: string,
12+
initArgs: unknown[],
13+
): Promise<{ proxy: Contract; address: string }> {
14+
const factory = await ethers.getContractFactory(contractName);
15+
const deployed = await upgrades.deployProxy(factory, initArgs, {
16+
kind: "uups",
17+
initializer: "initialize",
18+
});
19+
const proxy = (await deployed.waitForDeployment()) as unknown as Contract;
20+
const address = await proxy.getAddress();
21+
console.log(`Deployed ${contractName} proxy to: ${address}`);
22+
return { proxy, address };
23+
}

0 commit comments

Comments
 (0)