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

chore(contracts): add registry manager deploy task #280

Merged
merged 1 commit into from
Aug 26, 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
16 changes: 15 additions & 1 deletion packages/contracts/contracts/maci/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,62 @@
import { InitialVoiceCreditProxy } from "maci-contracts/contracts/initialVoiceCreditProxy/InitialVoiceCreditProxy.sol";
import { SignUpGatekeeper } from "maci-contracts/contracts/gatekeepers/SignUpGatekeeper.sol";

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

/// @title MACI - Minimum Anti-Collusion Infrastructure
/// @notice A contract which allows users to sign up, and deploy new polls
contract MACI is Ownable, BaseMACI {
contract MACI is Ownable, BaseMACI, ICommon {
/// @notice Registry manager
IRegistryManager public registryManager;

/// @notice Create a new instance of the MACI contract.
/// @param pollFactory The PollFactory contract
/// @param messageProcessorFactory The MessageProcessorFactory contract
/// @param tallyFactory The TallyFactory contract
/// @param signUpGatekeeper The SignUpGatekeeper contract
/// @param initialVoiceCreditProxy The InitialVoiceCreditProxy contract
/// @param stateTreeDepth The depth of the state tree
/// @param emptyBallotRoots The roots of the empty ballot trees
constructor(
IPollFactory pollFactory,
IMessageProcessorFactory messageProcessorFactory,
ITallyFactory tallyFactory,
SignUpGatekeeper signUpGatekeeper,
InitialVoiceCreditProxy initialVoiceCreditProxy,
uint8 stateTreeDepth,
uint256[5] memory emptyBallotRoots
)
payable
Ownable(msg.sender)
BaseMACI(
pollFactory,
messageProcessorFactory,
tallyFactory,
signUpGatekeeper,
initialVoiceCreditProxy,
stateTreeDepth,
emptyBallotRoots
)
{}

/// @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 {
PollContracts memory pollAddresses = polls[pollId];
IPoll poll = IPoll(pollAddresses.poll);

poll.init();
poll.transferOwnership(msg.sender);
}

/// @notice Set RegistryManager for MACI
function setRegistryManager(address registryManagerAddress) public onlyOwner {
ctrlc03 marked this conversation as resolved.
Show resolved Hide resolved
if (registryManagerAddress == address(0)) {
revert InvalidAddress();
}

registryManager = IRegistryManager(registryManagerAddress);
}
}

Check warning

Code scanning / Slither

Contracts that lock Ether Medium

Contract locking ether found:
Contract MACI has payable functions:
- MACI.constructor(IPollFactory,IMessageProcessorFactory,ITallyFactory,SignUpGatekeeper,InitialVoiceCreditProxy,uint8,uint256[5])
But does not have a function to withdraw the ether
42 changes: 35 additions & 7 deletions packages/contracts/deploy-config-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
},
"MACI": {
"stateTreeDepth": 10,
"gatekeeper": "EASGatekeeper"
"gatekeeper": "EASGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down Expand Up @@ -93,7 +97,11 @@
},
"MACI": {
"stateTreeDepth": 10,
"gatekeeper": "ZupassGatekeeper"
"gatekeeper": "ZupassGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0xaEF4103A04090071165F78D45D83A0C0782c2B2a"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down Expand Up @@ -155,7 +163,11 @@
},
"MACI": {
"stateTreeDepth": 6,
"gatekeeper": "EASGatekeeper"
"gatekeeper": "EASGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
"stateTreeDepth": 6,
Expand Down Expand Up @@ -217,7 +229,11 @@
},
"MACI": {
"stateTreeDepth": 10,
"gatekeeper": "FreeForAllGatekeeper"
"gatekeeper": "FreeForAllGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down Expand Up @@ -279,7 +295,11 @@
},
"MACI": {
"stateTreeDepth": 10,
"gatekeeper": "FreeForAllGatekeeper"
"gatekeeper": "FreeForAllGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down Expand Up @@ -341,7 +361,11 @@
},
"MACI": {
"stateTreeDepth": 10,
"gatekeeper": "FreeForAllGatekeeper"
"gatekeeper": "FreeForAllGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down Expand Up @@ -408,7 +432,11 @@
},
"MACI": {
"stateTreeDepth": 14,
"gatekeeper": "FreeForAllGatekeeper"
"gatekeeper": "FreeForAllGatekeeper",
"registryManager": "EASRegistryManager"
},
"EASRegistryManager": {
"easAddress": "0x4200000000000000000000000000000000000021"
},
"VkRegistry": {
"stateTreeDepth": 10,
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"ethers": "^6.13.2",
"hardhat": "^2.22.8",
"lowdb": "^1.0.0",
"maci-contracts": "^2.2.1",
"maci-contracts": "0.0.0-ci.17a38c9",
"maci-core": "^2.2.0",
"maci-domainobjs": "^2.2.0",
"solidity-docgen": "^0.6.0-beta.36"
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/tasks/deploy/maci/05-pollFactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ContractStorage, Deployment, EContracts, type IDeployParams } from "maci-contracts";
import { ContractStorage, Deployment, type IDeployParams } from "maci-contracts";

import { EDeploySteps } from "../../helpers/constants";
import { EDeploySteps, EContracts } from "../../helpers/constants";

const deployment = Deployment.getInstance();
const storage = ContractStorage.getInstance();
Expand Down
5 changes: 2 additions & 3 deletions packages/contracts/tasks/deploy/maci/08-maci.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
ContractStorage,
Deployment,
EContracts,
genEmptyBallotRoots,
type IDeployParams,
type GitcoinPassportGatekeeper,
Expand All @@ -12,7 +11,7 @@ import {
} from "maci-contracts";

import { MACI } from "../../../typechain-types";
import { EDeploySteps } from "../../helpers/constants";
import { EDeploySteps, EContracts } from "../../helpers/constants";

const deployment = Deployment.getInstance();
const storage = ContractStorage.getInstance();
Expand Down Expand Up @@ -53,7 +52,7 @@ deployment.deployTask(EDeploySteps.Maci, "Deploy MACI contract").then((task) =>
hre.network.name,
);
const gatekeeper =
deployment.getDeployConfigField<EContracts | null>(EContracts.MACI, "gatekeeper") ||
deployment.getDeployConfigField<keyof typeof EContracts | null>(EContracts.MACI, "gatekeeper") ||
EContracts.FreeForAllGatekeeper;
const gatekeeperContractAddress = storage.mustGetAddress(gatekeeper, hre.network.name);
const pollFactoryContractAddress = storage.mustGetAddress(EContracts.PollFactory, hre.network.name);
Expand Down
60 changes: 60 additions & 0 deletions packages/contracts/tasks/deploy/maci/10-registryManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ContractStorage, Deployment, type IDeployParams } from "maci-contracts";

import type { MACI } from "../../../typechain-types";

import { EDeploySteps, EContracts } from "../../helpers/constants";

const deployment = Deployment.getInstance();
const storage = ContractStorage.getInstance();

/**
* Deploy step registration and task itself
*/
deployment.deployTask(EDeploySteps.RegistryManager, "Deploy registry manager").then((task) =>
task.setAction(async ({ incremental }: IDeployParams, hre) => {
deployment.setHre(hre);
const deployer = await deployment.getDeployer();

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

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

if (incremental && registryManagerContractAddress) {
return;
}

const easAddress = deployment.getDeployConfigField<keyof typeof EContracts | null, keyof typeof EContracts>(
registryManagerType,
"easAddress",
);

const args = easAddress ? [easAddress] : [];

const registryManagerContract = await deployment.deployContract(
{
name: registryManagerType,
signer: deployer,
},
...args,
);

const maciContractAddress = storage.mustGetAddress(EContracts.MACI, hre.network.name);

const maciContract = await deployment.getContract<MACI>({
name: "contracts/maci/MACI.sol:MACI" as Parameters<typeof deployment.getContract>[0]["name"],
address: maciContractAddress,
});

const contractAddress = await registryManagerContract.getAddress();
await maciContract.setRegistryManager(contractAddress).then((tx) => tx.wait());

await storage.register({
id: registryManagerType,
contract: registryManagerContract,
args,
network: hre.network.name,
});
}),
);
20 changes: 18 additions & 2 deletions packages/contracts/tasks/helpers/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { EDeploySteps as EMaciDeploySteps } from "maci-contracts";
import { EDeploySteps as EMaciDeploySteps, EContracts as EMaciContracts } from "maci-contracts";

/**
* Deploy steps for maci-platform related constacts
*/
export enum EPlatformDeployStep {
Registry = "full:deploy-registry",
RegistryManager = "full:deploy-registry-manager",
}

/**
Expand All @@ -15,6 +15,22 @@ export const EDeploySteps = {
...EPlatformDeployStep,
};

/**
* Contracts for maci-platform related constacts
*/
export enum EPlatformContracts {
RegistryManager = "RegistryManager",
EASRegistryManager = "EASRegistryManager",
}

/**
* Contracts for maci and maci-platform
*/
export const EContracts = {
...EMaciContracts,
...EPlatformContracts,
};

/**
* Supported networks for deployment and task running
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from "chai";
import { Signer } from "ethers";
import { Verifier, VkRegistry, EMode, getSigners } from "maci-contracts";
import { Signer, ZeroAddress } from "ethers";
import { Verifier, VkRegistry, EMode, getSigners, deployContract } from "maci-contracts";
import { MaciState } from "maci-core";
import { Keypair, Message, PubKey } from "maci-domainobjs";

Expand Down Expand Up @@ -96,5 +96,30 @@ describe("Poll", () => {
);
await expect(pollContract.init()).to.be.revertedWithCustomError(pollContract, "PollAlreadyInit");
});

it("should not be possible to set zero address as registry manager", async () => {
await expect(maciContract.setRegistryManager(ZeroAddress)).to.be.revertedWithCustomError(
maciContract,
"InvalidAddress",
);
});

it("should not be possible to set registry manager by non-owner", async () => {
const registryManager = await deployContract("RegistryManager", owner, true);

await expect(
maciContract.connect(user).setRegistryManager(await registryManager.getAddress()),
).to.be.revertedWithCustomError(maciContract, "OwnableUnauthorizedAccount");
});

it("should set registry manager properly", async () => {
const registryManager = await deployContract("RegistryManager", owner, true);
const registryManagerContractAddress = await registryManager.getAddress();

const tx = await maciContract.setRegistryManager(registryManagerContractAddress);
await tx.wait();

expect(await maciContract.registryManager()).to.equal(registryManagerContractAddress);
});
});
});
Loading
Loading