Skip to content

Commit

Permalink
fix unit test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
yuetloo committed Jan 17, 2024
1 parent 96831f8 commit 8f451fa
Show file tree
Hide file tree
Showing 17 changed files with 865 additions and 754 deletions.
4 changes: 2 additions & 2 deletions common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"dependencies": {
"@openzeppelin/merkle-tree": "^1.0.5",
"ethers": "^6.9.2",
"maci-crypto": "0.0.0-ci.2e62774",
"maci-domainobjs": "0.0.0-ci.2e62774"
"maci-crypto": "0.0.0-ci.ae1f52e",
"maci-domainobjs": "0.0.0-ci.ae1f52e"
},
"repository": {
"type": "git",
Expand Down
8 changes: 4 additions & 4 deletions contracts/cli/newClrFund.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* If token is not provided, a new ERC20 token will be created
*/
import { BigNumber } from 'ethers'
import { parseUnits } from 'ethers'
import { ethers, network } from 'hardhat'
import { getEventArg } from '../utils/contracts'
import { newMaciPrivateKey } from '../utils/maci'
Expand Down Expand Up @@ -143,7 +143,7 @@ async function main(args: any) {
// set token
let tokenAddress = args.token
if (!tokenAddress) {
const initialTokenSupply = UNIT.mul(args.initialTokenSupply)
const initialTokenSupply = UNIT * BigInt(args.initialTokenSupply)
const tokenContract = await deployContract({
name: 'AnyOldERC20Token',
contractArgs: [initialTokenSupply],
Expand Down Expand Up @@ -205,9 +205,9 @@ async function main(args: any) {
}
}

function parseDeposit(deposit: string): BigNumber {
function parseDeposit(deposit: string): bigint {
try {
return ethers.utils.parseUnits(deposit)
return parseUnits(deposit)
} catch (e) {
throw new Error(`Error parsing deposit ${(e as Error).message}`)
}
Expand Down
4 changes: 4 additions & 0 deletions contracts/contracts/ClrFund.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ contract ClrFund is OwnableUpgradeable, DomainObjs, Params {
error NotOwnerOfMaciFactory();
error InvalidFundingRoundFactory();
error InvalidMaciFactory();
error RecipientRegistryNotSet();

/**
* @dev Initialize clrfund instance with MACI factory and new round templates
Expand Down Expand Up @@ -207,6 +208,9 @@ contract ClrFund is OwnableUpgradeable, DomainObjs, Params {
if (address(currentRound) != address(0) && !currentRound.isFinalized()) {
revert NotFinalized();
}

if (address(recipientRegistry) == address(0)) revert RecipientRegistryNotSet();

// Make sure that the max number of recipients is set correctly
MaxValues memory maxValues = maciFactory.maxValues();
recipientRegistry.setMaxRecipients(maxValues.maxVoteOptions);
Expand Down
136 changes: 55 additions & 81 deletions contracts/contracts/FundingRound.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ contract FundingRound is
error NotCoordinator();
error InvalidPoll();
error InvalidTally();
error InvalidMessageProcessor();
error MaciAlreadySet();
error ContributionAmountIsZero();
error ContributionAmountTooLarge();
Expand All @@ -61,12 +62,12 @@ contract FundingRound is
error IncorrectTallyResult();
error IncorrectSpentVoiceCredits();
error IncorrectPerVOSpentVoiceCredits();
error VotingIsNotOver();
error FundsAlreadyClaimed();
error TallyHashNotPublished();
error BudgetGreaterThanVotes();
error IncompleteTallyResults();
error IncompleteTallyResults(uint256 total, uint256 actual);
error NoVotes();
error MaciNotSet();
error PollNotSet();
error InvalidMaci();
error InvalidNativeToken();
error InvalidUserRegistry();
Expand Down Expand Up @@ -118,8 +119,8 @@ contract FundingRound is
TopupToken public topupToken;
IUserRegistry public userRegistry;
IRecipientRegistry public recipientRegistry;
ITallySubsidyFactory public immutable tallyFactory;
IMessageProcessorFactory public immutable messageProcessorFactory;
ITallySubsidyFactory public tallyFactory;
IMessageProcessorFactory public messageProcessorFactory;
string public tallyHash;

// The alpha used in quadratic funding formula
Expand Down Expand Up @@ -150,56 +151,27 @@ contract FundingRound is

/**
* @dev Set round parameters.
* @param _duration the funding round duration
* @param _clrfund the clrfund contract containing information
* to deploy a funding round, e.g. nativeToke, coordinator address
* coordinator public key, etc.
*/
constructor(
uint256 _duration,
IClrFund _clrfund
ERC20 _nativeToken,
IUserRegistry _userRegistry,
IRecipientRegistry _recipientRegistry,
address _coordinator
)
{
_validate(_clrfund);
nativeToken = _clrfund.nativeToken();
if (isAddressZero(address(_nativeToken))) revert InvalidNativeToken();
if (isAddressZero(address(_userRegistry))) revert InvalidUserRegistry();
if (isAddressZero(address(_recipientRegistry))) revert InvalidRecipientRegistry();
if (isAddressZero(_coordinator)) revert invalidCoordinator();

nativeToken = _nativeToken;
voiceCreditFactor = (MAX_CONTRIBUTION_AMOUNT * uint256(10) ** nativeToken.decimals()) / MAX_VOICE_CREDITS;
voiceCreditFactor = voiceCreditFactor > 0 ? voiceCreditFactor : 1;

userRegistry = _clrfund.userRegistry();
recipientRegistry = _clrfund.recipientRegistry();
coordinator = _clrfund.coordinator();
userRegistry = _userRegistry;
recipientRegistry = _recipientRegistry;
coordinator = _coordinator;
topupToken = new TopupToken();

IMACIFactory maciFactory = _clrfund.maciFactory();
Factories memory factories = maciFactory.factories();
tallyFactory = ITallySubsidyFactory(factories.tallyFactory);
messageProcessorFactory = IMessageProcessorFactory(factories.messageProcessorFactory);

maci = maciFactory.deployMaci(
SignUpGatekeeper(this),
InitialVoiceCreditProxy(this),
address(topupToken),
address(this)
);
if (isAddressZero(address(maci))) revert InvalidMaci();

MACI.PollContracts memory pollContracts = maci.deployPoll(
_duration,
maciFactory.maxValues(),
maciFactory.treeDepths(),
_clrfund.coordinatorPubKey(),
address(maciFactory.verifier()),
address(maciFactory.vkRegistry()),
// pass false to not deploy the subsidy contract
false
);

_setPollAndTally(pollContracts);

// transfer poll contracts ownership to coordinator for vote tallying
Ownable(pollContracts.poll).transferOwnership(coordinator);
Ownable(pollContracts.messageProcessor).transferOwnership(coordinator);
Ownable(pollContracts.tally).transferOwnership(coordinator);
}

/**
Expand All @@ -209,29 +181,10 @@ contract FundingRound is
return (addressValue == address(0));
}

/**
* @dev validate that the clrfund contract has been initialized properly
* with non zero addresses
* @param _clrfund the clrfund contract
*/
function _validate(IClrFund _clrfund) private view {
if (isAddressZero(address(_clrfund.nativeToken()))) revert InvalidNativeToken();
if (isAddressZero(address(_clrfund.userRegistry()))) revert InvalidUserRegistry();
if (isAddressZero(address(_clrfund.recipientRegistry()))) revert InvalidRecipientRegistry();
if (isAddressZero(_clrfund.coordinator())) revert invalidCoordinator();
if (isAddressZero(address(_clrfund.maciFactory()))) revert invalidMaciFactory();

IMACIFactory maciFactory = _clrfund.maciFactory();
MACICommon.Factories memory factories = maciFactory.factories();
if (isAddressZero(factories.tallyFactory)) revert InvalidTallyFactory();
if (isAddressZero(factories.messageProcessorFactory)) revert InvalidMessageProcessorFactory();
}


/**
* @dev Have the votes been tallied
*/
function isTallied() internal view returns (bool) {
function isTallied() private view returns (bool) {
(uint256 numSignUps, ) = poll.numSignUpsAndMessages();
(, uint256 tallyBatchSize, ) = poll.batchSizes();
uint256 tallyBatchNum = tally.tallyBatchNum();
Expand All @@ -244,10 +197,9 @@ contract FundingRound is
* @dev Set the tally contract
* @param _tally The tally contract address
*/
function _setTally(address _tally)
private
function _setTally(address _tally) private
{
if (_tally == address(0)) {
if (isAddressZero(_tally)) {
revert InvalidTally();
}

Expand All @@ -263,6 +215,8 @@ contract FundingRound is
external
onlyCoordinator
{
if (isAddressZero(address(maci))) revert MaciNotSet();

_votingPeriodOver(poll);
if (isFinalized) {
revert RoundAlreadyFinalized();
Expand All @@ -276,28 +230,41 @@ contract FundingRound is
}

/**
* @dev Link Poll and Tally contracts to this funding round.
* @dev Link MACI related contracts to this funding round.
*/
function _setPollAndTally(MACI.PollContracts memory _pollContracts) private
function setMaci(
MACI _maci,
MACI.PollContracts memory _pollContracts,
Factories memory _factories
)
external
onlyOwner
{
if (_pollContracts.poll == address(0)) {
revert InvalidPoll();
}
if (!isAddressZero(address(maci))) revert MaciAlreadySet();

if (isAddressZero(address(_maci))) revert InvalidMaci();
if (isAddressZero(_pollContracts.poll)) revert InvalidPoll();
if (isAddressZero(_pollContracts.messageProcessor)) revert InvalidMessageProcessor();
if (isAddressZero(_factories.tallyFactory)) revert InvalidTallyFactory();
if (isAddressZero(_factories.messageProcessorFactory)) revert InvalidMessageProcessorFactory();

// we only create 1 poll per maci, make sure MACI use pollId = 0
// as the first poll index
pollId = 0;
address expectedPoll = maci.getPoll(pollId);

address expectedPoll = _maci.getPoll(pollId);
if( _pollContracts.poll != expectedPoll ) {
revert UnexpectedPollAddress(expectedPoll, _pollContracts.poll);
}

if (address(_pollContracts.tally) == address(0)) {
revert InvalidTally();
}

maci = _maci;
poll = Poll(_pollContracts.poll);
_setTally(_pollContracts.tally);

// save a copy of the factory in case we need to reset the tally result by recreating the
// the tally and message processor contracts
tallyFactory = ITallySubsidyFactory(_factories.tallyFactory);
messageProcessorFactory = IMessageProcessorFactory(_factories.messageProcessorFactory);
}

/**
Expand All @@ -311,6 +278,7 @@ contract FundingRound is
)
external
{
if (isAddressZero(address(maci))) revert MaciNotSet();
if (isFinalized) revert RoundAlreadyFinalized();
if (amount == 0) revert ContributionAmountIsZero();
if (amount > MAX_VOICE_CREDITS * voiceCreditFactor) revert ContributionAmountTooLarge();
Expand Down Expand Up @@ -400,6 +368,8 @@ contract FundingRound is
)
external
{
if (isAddressZero(address(poll))) revert PollNotSet();

uint256 batchSize = _messages.length;
for (uint8 i = 0; i < batchSize; i++) {
poll.publishMessage(_messages[i], _encPubKeys[i]);
Expand Down Expand Up @@ -523,6 +493,8 @@ contract FundingRound is
revert RoundAlreadyFinalized();
}

if (isAddressZero(address(maci))) revert MaciNotSet();

_votingPeriodOver(poll);

if (!isTallied()) {
Expand All @@ -536,7 +508,7 @@ contract FundingRound is
(,,, uint8 voteOptionTreeDepth) = poll.treeDepths();
uint256 totalResults = uint256(LEAVES_PER_NODE) ** uint256(voteOptionTreeDepth);
if ( totalTallyResults != totalResults ) {
revert IncompleteTallyResults();
revert IncompleteTallyResults(totalResults, totalTallyResults);
}

// If nobody voted, the round should be cancelled to avoid locking of matching funds
Expand Down Expand Up @@ -728,6 +700,8 @@ contract FundingRound is
external
onlyCoordinator
{
if (isAddressZero(address(maci))) revert MaciNotSet();

if (!isTallied()) {
revert VotesNotTallied();
}
Expand Down
30 changes: 28 additions & 2 deletions contracts/contracts/FundingRoundFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ pragma solidity ^0.8.10;

import {FundingRound} from './FundingRound.sol';
import {IClrFund} from './interfaces/IClrFund.sol';
import {IMACIFactory} from './interfaces/IMACIFactory.sol';
import {MACICommon} from './MACICommon.sol';
import {MACI} from 'maci-contracts/contracts/MACI.sol';
import {SignUpGatekeeper} from 'maci-contracts/contracts/gatekeepers/SignUpGatekeeper.sol';
import {InitialVoiceCreditProxy} from 'maci-contracts/contracts/initialVoiceCreditProxy/InitialVoiceCreditProxy.sol';

/**
* @dev A factory to deploy the funding round contract
*/
contract FundingRoundFactory {
contract FundingRoundFactory is MACICommon {
/**
* @dev Deploy the funding round contract
* @param _duration the funding round duration
Expand All @@ -23,8 +28,29 @@ contract FundingRoundFactory {
external
returns (address)
{
FundingRound newRound = new FundingRound(_duration, IClrFund(_clrfund));
IClrFund clrfund = IClrFund(_clrfund);
FundingRound newRound = new FundingRound(
clrfund.nativeToken(),
clrfund.userRegistry(),
clrfund.recipientRegistry(),
clrfund.coordinator()
);

IMACIFactory maciFactory = clrfund.maciFactory();
(MACI maci, MACI.PollContracts memory pollContracts) = maciFactory.deployMaci(
SignUpGatekeeper(newRound),
InitialVoiceCreditProxy(newRound),
address(newRound.topupToken()),
_duration,
newRound.coordinator(),
clrfund.coordinatorPubKey(),
address(this)
);

// link funding round with maci related contracts
newRound.setMaci(maci, pollContracts, maciFactory.factories());
newRound.transferOwnership(_clrfund);
maci.transferOwnership(address(newRound));
return address(newRound);
}
}
21 changes: 20 additions & 1 deletion contracts/contracts/MACIFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,13 @@ contract MACIFactory is Ownable, Params, SnarkCommon, DomainObjs, MACICommon {
SignUpGatekeeper signUpGatekeeper,
InitialVoiceCreditProxy initialVoiceCreditProxy,
address topupCredit,
uint256 duration,
address coordinator,
PubKey calldata coordinatorPubKey,
address maciOwner
)
external
returns (MACI _maci)
returns (MACI _maci, MACI.PollContracts memory _pollContracts)
{
if (!vkRegistry.hasProcessVk(
stateTreeDepth,
Expand Down Expand Up @@ -197,6 +200,22 @@ contract MACIFactory is Ownable, Params, SnarkCommon, DomainObjs, MACICommon {
stateTreeDepth
);

_pollContracts = _maci.deployPoll(
duration,
maxValues,
treeDepths,
coordinatorPubKey,
address(verifier),
address(vkRegistry),
// pass false to not deploy the subsidy contract
false
);

// transfer ownership to coordinator to run the tally scripts
Ownable(_pollContracts.poll).transferOwnership(coordinator);
Ownable(_pollContracts.messageProcessor).transferOwnership(coordinator);
Ownable(_pollContracts.tally).transferOwnership(coordinator);

_maci.transferOwnership(maciOwner);

emit MaciDeployed(address(_maci));
Expand Down
Loading

0 comments on commit 8f451fa

Please sign in to comment.