Skip to content

Commit

Permalink
feat(contracts): add registry integration
Browse files Browse the repository at this point in the history
- [x] Add deploy poll task
- [x] Add init poll task
- [x] Link registry and poll
- [x] Add deploy poll registry method for MACI
  • Loading branch information
0xmad committed Aug 28, 2024
1 parent f0ff7c2 commit c29b336
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/hardhat-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ jobs:
run: |
cp ./deploy-config-example.json ./deploy-config.json
pnpm deploy:localhost
pnpm deploy-poll:localhost
pnpm initPoll:localhost --poll 0
working-directory: packages/contracts

- name: Stop Hardhat
Expand Down
4 changes: 4 additions & 0 deletions packages/contracts/contracts/interfaces/IPoll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ import { IOwnable } from "./IOwnable.sol";
interface IPoll is IPollBase, IOwnable {
/// @notice The initialization function.
function init() external;

/// @notice Set the poll registry.
/// @param registryAddress The registry address
function setRegistry(address registryAddress) external;
}
18 changes: 17 additions & 1 deletion packages/contracts/contracts/maci/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { SignUpGatekeeper } from "maci-contracts/contracts/gatekeepers/SignUpGat
import { ICommon } from "../interfaces/ICommon.sol";
import { IPoll } from "../interfaces/IPoll.sol";
import { IRegistryManager } from "../interfaces/IRegistryManager.sol";
import { EASRegistry } from "../registry/EASRegistry.sol";

/// @title MACI - Minimum Anti-Collusion Infrastructure
/// @notice A contract which allows users to sign up, and deploy new polls
Expand Down Expand Up @@ -49,12 +50,27 @@ contract MACI is Ownable, BaseMACI, ICommon {
)
{}

/// @notice Deploy a new instance of the registry contract
/// @param max The maximum number of projects that can be registered
/// @param url The metadata url
/// @param easAddress The EAS address
function deployPollRegistry(
uint256 max,
bytes32 url,
address easAddress
) public onlyOwner returns (address) {
EASRegistry registry = new EASRegistry(max, url, easAddress, address(registryManager));

return address(registry);
}

/// @notice Initialize the poll by given poll id and transfer poll ownership to the caller.
/// @param pollId The poll id
function initPoll(uint256 pollId) public onlyOwner {
function initPoll(uint256 pollId, address registryAddress) public onlyOwner {
PollContracts memory pollAddresses = polls[pollId];
IPoll poll = IPoll(pollAddresses.poll);

poll.setRegistry(registryAddress);
poll.init();
poll.transferOwnership(msg.sender);
}
Expand Down
25 changes: 24 additions & 1 deletion packages/contracts/contracts/maci/Poll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@ pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Poll as BasePoll } from "maci-contracts/contracts/Poll.sol";

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

/// @title Poll
/// @notice A Poll contract allows voters to submit encrypted messages
/// which can be either votes or key change messages.
/// @dev Do not deploy this directly. Use PollFactory.deploy() which performs some
/// checks on the Poll constructor arguments.
contract Poll is Ownable, BasePoll {
contract Poll is Ownable, BasePoll, ICommon {
/// @notice Poll specific registry
address public registry;

/// @notice custom errors
error RegistryAlreadyInitialized();

/// @notice Each MACI instance can have multiple Polls.
/// When a Poll is deployed, its voting period starts immediately.
/// @param duration The duration of the voting period, in seconds
/// @param treeDepths The depths of the merkle trees
/// @param coordinatorPubKey The coordinator's public key
/// @param extContracts The external contracts
/// @param emptyBallotRoot The empty ballot root
constructor(
uint256 duration,
TreeDepths memory treeDepths,
Expand All @@ -28,6 +37,20 @@ contract Poll is Ownable, BasePoll {
BasePoll(duration, treeDepths, coordinatorPubKey, extContracts, emptyBallotRoot)
{}

/// @notice Set poll registry.
/// @param registryAddress The registry address
function setRegistry(address registryAddress) public onlyOwner {
if (registryAddress == address(0)) {
revert InvalidAddress();
}

if (address(registry) != address(0)) {
revert RegistryAlreadyInitialized();
}

registry = registryAddress;
}

/// @notice The initialization function.
function init() public override onlyOwner {
super.init();
Expand Down
14 changes: 14 additions & 0 deletions packages/contracts/deploy-config-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
Expand Down Expand Up @@ -101,6 +103,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0xaEF4103A04090071165F78D45D83A0C0782c2B2a"
},
"VkRegistry": {
Expand Down Expand Up @@ -167,6 +171,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
Expand Down Expand Up @@ -233,6 +239,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
Expand Down Expand Up @@ -299,6 +307,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
Expand Down Expand Up @@ -365,6 +375,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
Expand Down Expand Up @@ -436,6 +448,8 @@
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"maxRecipients": 25,
"metadataUrl": "url",
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
Expand Down
2 changes: 2 additions & 0 deletions packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "hardhat-artifactor";
import "hardhat-contract-sizer";
import "maci-contracts/tasks/deploy";
import "maci-contracts/tasks/runner/deployFull";
import "maci-contracts/tasks/runner/deployPoll";
import "maci-contracts/tasks/runner/verifyFull";
import "solidity-docgen";

Expand All @@ -13,6 +14,7 @@ import type { HardhatUserConfig } from "hardhat/config";
// Don't forget to import new tasks here
import "./tasks/deploy";
import { EChainId, ESupportedChains, getEtherscanApiKeys, getNetworkRpcUrls } from "./tasks/helpers/constants";
import "./tasks/runner/initPoll";

dotenv.config();

Expand Down
6 changes: 5 additions & 1 deletion packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
"coverage": "BLOCK_GAS_LIMIT=1599511627775 hardhat coverage",
"test": "hardhat test --network hardhat",
"deploy": "hardhat deploy-full",
"deploy:localhost": "pnpm run deploy"
"initPoll": "hardhat initPoll",
"deploy-poll": "hardhat deploy-poll",
"deploy:localhost": "pnpm run deploy",
"deploy-poll:localhost": "pnpm run deploy-poll",
"initPoll:localhost": "pnpm run initPoll"
},
"dependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/tasks/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from "path";
/**
* The same as individual imports but doesn't require to add new import line every time
*/
["maci"].forEach((folder) => {
["maci", "poll"].forEach((folder) => {
const tasksPath = path.resolve(__dirname, folder);

if (fs.existsSync(tasksPath)) {
Expand Down
Loading

0 comments on commit c29b336

Please sign in to comment.