Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contracts): add registry integration #288

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
3 changes: 2 additions & 1 deletion packages/contracts/contracts/maci/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ contract MACI is Ownable, BaseMACI, ICommon {

/// @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
94 changes: 92 additions & 2 deletions packages/contracts/contracts/maci/Poll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,35 @@ 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 The timestamp of the block at which the Poll was deployed
uint256 internal initTime;

/// @notice events
event SetRegistry(address indexed registry);

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

/// @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,8 +45,81 @@ contract Poll is Ownable, BasePoll {
BasePoll(duration, treeDepths, coordinatorPubKey, extContracts, emptyBallotRoot)
{}

/// @notice Check if poll is initialized
modifier isPollInitialized() {
if (!isInit) {
revert PollNotInitialized();
}

_;
}

/// @notice Check if registry is initialized
modifier isRegistryInitialized() {
if (address(registry) == address(0)) {
revert RegistryNotInitialized();
}

_;
}

/// @notice Check if registry is valid and not initialized
/// @param registryAddress Registry address
modifier isRegistryNotInitialized(address registryAddress) {
if (registryAddress == address(0)) {
revert InvalidAddress();
}

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

_;
}

/// @notice A modifier that causes the function to revert if the voting period is
/// not over.
modifier isAfterVotingDeadline() override {
uint256 secondsPassed = block.timestamp - initTime;

if (secondsPassed <= duration) {
revert VotingPeriodNotOver();
}

_;
}

/// @notice A modifier that causes the function to revert if the voting period is
/// over
modifier isWithinVotingDeadline() override {
uint256 secondsPassed = block.timestamp - initTime;

if (secondsPassed >= duration) {
revert VotingPeriodOver();
}

_;
}

/// @notice Set poll registry.
/// @param registryAddress The registry address
function setRegistry(address registryAddress) public onlyOwner isRegistryNotInitialized(registryAddress) {
registry = registryAddress;

emit SetRegistry(registryAddress);
}

/// @notice The initialization function.
function init() public override onlyOwner {
function init() public override onlyOwner isRegistryInitialized {
initTime = block.timestamp;
super.init();
}

/// @inheritdoc BasePoll
function publishMessage(
Message memory message,
PubKey calldata encPubKey
) public override isPollInitialized isWithinVotingDeadline {
super.publishMessage(message, encPubKey);
}
}
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
8 changes: 6 additions & 2 deletions 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 All @@ -44,7 +48,7 @@
"ethers": "^6.13.2",
"hardhat": "^2.22.8",
"lowdb": "^1.0.0",
"maci-contracts": "0.0.0-ci.17a38c9",
"maci-contracts": "0.0.0-ci.a97f395",
"maci-core": "^2.2.0",
"maci-domainobjs": "^2.2.0",
"solidity-docgen": "^0.6.0-beta.36"
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ deployment.deployTask(EDeploySteps.RegistryManager, "Deploy registry manager").t

const registryManagerType =
deployment.getDeployConfigField<keyof typeof EContracts | null>(EContracts.MACI, "registryManager") ||
EContracts.RegistryManager;
EContracts.EASRegistryManager;

const registryManagerContractAddress = storage.getAddress(registryManagerType, hre.network.name);

Expand Down
Loading
Loading