Skip to content
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
12 changes: 12 additions & 0 deletions contracts/contracts/FundingRound.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ contract FundingRound is Ownable, MACISharedObjs, SignUpGatekeeper, InitialVoice
maci = _maci;
}

/**
* @dev Get voting deadline.
*/
function votingDeadline()
public
view
returns (uint256)
{
require(address(maci) != address(0), 'FundingRound: MACI not deployed');
return maci.calcVotingDeadline();
}

/**
* @dev Contribute tokens to this funding round.
* @param pubKey Contributor's public key.
Expand Down
11 changes: 6 additions & 5 deletions contracts/scripts/contribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ethers } from '@nomiclabs/buidler'
import { Keypair } from 'maci-domainobjs'

import MACIArtifact from '../build/contracts/MACI.json'
import { getEventArg } from '../tests/utils'
import { UNIT, getEventArg } from '../tests/utils'

async function main() {
const [,,,,, contributor1, contributor2] = await ethers.getSigners()
Expand All @@ -14,8 +14,9 @@ async function main() {
const maciAddress = await fundingRound.maci()
const maci = await ethers.getContractAt(MACIArtifact.abi, maciAddress)

const contributionAmount = 10000
const voiceCredits = Math.sqrt(contributionAmount)
// https://github.com/appliedzkp/maci/issues/155
// TODO: Use 16 UNIT
const contributionAmount = UNIT.mul(16).div(10 ** 10)
state.contributors = {}

for (const contributor of [contributor1, contributor2]) {
Expand All @@ -36,9 +37,9 @@ async function main() {
privKey: contributorKeypair.privKey.serialize(),
pubKey: contributorKeypair.pubKey.serialize(),
stateIndex: parseInt(stateIndex),
voiceCredits: voiceCredits,
voiceCredits: contributionAmount.toString(),
}
console.log(`Contributor ${contributorAddress} registered. State index: ${stateIndex}. Voice credits: ${voiceCredits}.`)
console.log(`Contributor ${contributorAddress} registered. State index: ${stateIndex}. Voice credits: ${contributionAmount.toString()}.`)
}

// Update state file
Expand Down
12 changes: 6 additions & 6 deletions contracts/scripts/deployTestRound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs'
import { ethers } from '@nomiclabs/buidler';
import { Keypair } from 'maci-domainobjs'

import { MaciParameters } from '../tests/utils'
import { UNIT, MaciParameters } from '../tests/utils'

async function main() {
// We're hardcoding factory address due to a buidler limitation:
Expand All @@ -23,12 +23,12 @@ async function main() {
'AnyOldERC20Token',
deployer,
);
const tokenInitialSupply = 1000000
const tokenInitialSupply = UNIT.mul(1000)
const token = await Token.deploy(tokenInitialSupply)
console.log(`Token deployed: ${token.address}`)
await token.transfer(poolContributor.getAddress(), 100000)
await token.transfer(contributor1.getAddress(), 100000)
await token.transfer(contributor2.getAddress(), 100000)
await token.transfer(poolContributor.getAddress(), UNIT.mul(100))
await token.transfer(contributor1.getAddress(), UNIT.mul(100))
await token.transfer(contributor2.getAddress(), UNIT.mul(100))

// Configure factory
const factory = await ethers.getContractAt(
Expand All @@ -48,7 +48,7 @@ async function main() {
await factory.setMaciParameters(...maciParameters.values())

// Add to matching pool
const poolContributionAmount = 10000
const poolContributionAmount = UNIT.mul(10)
const poolContributorToken = token.connect(poolContributor);
await poolContributorToken.approve(factory.address, poolContributionAmount);
const poolContributorFactory = factory.connect(poolContributor);
Expand Down
9 changes: 5 additions & 4 deletions contracts/scripts/vote.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import { ethers } from '@nomiclabs/buidler';
import { BigNumber } from 'ethers'
import { PrivKey, PubKey, Keypair } from 'maci-domainobjs'

import { createMessage } from '../tests/utils'
Expand All @@ -11,15 +12,15 @@ async function main() {

for (const contributor of [contributor1, contributor2]) {
const contributorAddress = await contributor.getAddress()
const { privKey, stateIndex } = state.contributors[contributorAddress]
const contributorKeyPair = new Keypair(PrivKey.unserialize(privKey))
const contributorData = state.contributors[contributorAddress]
const contributorKeyPair = new Keypair(PrivKey.unserialize(contributorData.privKey))
const messages = []
const encPubKeys = []
for (const recipientIndex of [1, 2]) {
const nonce = recipientIndex
const votes = 50
const votes = BigNumber.from(contributorData.voiceCredits).div(4)
const [message, encPubKey] = createMessage(
stateIndex,
contributorData.stateIndex,
contributorKeyPair,
coordinatorPubKey,
recipientIndex, votes, nonce,
Expand Down
10 changes: 5 additions & 5 deletions contracts/tests/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { genRandomSalt } from 'maci-crypto'
import { Keypair } from 'maci-domainobjs';

import { deployMaciFactory } from '../scripts/helpers';
import { ZERO_ADDRESS, getGasUsage, getEventArg, MaciParameters } from './utils';
import { ZERO_ADDRESS, UNIT, getGasUsage, getEventArg, MaciParameters } from './utils';

import FactoryArtifact from '../build/contracts/FundingRoundFactory.json';
import TokenArtifact from '../build/contracts/AnyOldERC20Token.json';
Expand Down Expand Up @@ -36,14 +36,14 @@ describe('Funding Round Factory', () => {
await maciFactory.transferOwnership(factory.address);

// Deploy token contract and transfer tokens to contributor
const tokenInitialSupply = 10000000000;
const tokenInitialSupply = UNIT.mul(1000)
token = await deployContract(deployer, TokenArtifact, [tokenInitialSupply]);
expect(token.address).to.properAddress;
await token.transfer(contributor.address, tokenInitialSupply);
});

describe('contributing to matching pool', () => {
const contributionAmount = 1000;
const contributionAmount = UNIT.mul(10)

it('allows user to contribute to matching pool', async () => {
await factory.setToken(token.address);
Expand Down Expand Up @@ -324,8 +324,8 @@ describe('Funding Round Factory', () => {
const signUpDuration = maciParameters.signUpDuration
const votingDuration = maciParameters.votingDuration
const roundDuration = signUpDuration + votingDuration + 10
const contributionAmount = 1000;
const totalSpent = 10000
const contributionAmount = UNIT.mul(10)
const totalSpent = UNIT.mul(100)
const totalSpentSalt = genRandomSalt().toString()

beforeEach(async () => {
Expand Down
40 changes: 20 additions & 20 deletions contracts/tests/round.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { genRandomSalt } from 'maci-crypto';
import { Keypair } from 'maci-domainobjs';

import { deployMaciFactory } from '../scripts/helpers';
import { ZERO_ADDRESS, getEventArg, getGasUsage, createMessage } from './utils';
import { ZERO_ADDRESS, UNIT, bnSqrt, getEventArg, getGasUsage, createMessage } from './utils'
import IVerifiedUserRegistryArtifact from '../build/contracts/IVerifiedUserRegistry.json';
import IRecipientRegistryArtifact from '../build/contracts/IRecipientRegistry.json';
import MACIArtifact from '../build/contracts/MACI.json';
Expand All @@ -23,7 +23,7 @@ describe('Funding Round', () => {
const signUpDuration = 86400 * 7; // Default duration in MACI factory
const votingDuration = 86400 * 7; // Default duration in MACI factory
const userKeypair = new Keypair()
const contributionAmount = 1000
const contributionAmount = UNIT.mul(10)

let token: Contract;
let verifiedUserRegistry: Contract;
Expand All @@ -44,11 +44,11 @@ describe('Funding Round', () => {
}

beforeEach(async () => {
const tokenInitialSupply = 10000000000;
const tokenInitialSupply = UNIT.mul(10000)
const Token = await ethers.getContractFactory('AnyOldERC20Token', deployer);
token = await Token.deploy(tokenInitialSupply);
await token.transfer(contributor.address, tokenInitialSupply / 4);
await token.transfer(coordinator.address, tokenInitialSupply / 4);
await token.transfer(contributor.address, tokenInitialSupply.div(4))
await token.transfer(coordinator.address, tokenInitialSupply.div(4))

verifiedUserRegistry = await deployMockContract(deployer, IVerifiedUserRegistryArtifact.abi);
await verifiedUserRegistry.mock.isVerifiedUser.returns(true);
Expand Down Expand Up @@ -102,7 +102,6 @@ describe('Funding Round', () => {

describe('accepting contributions', () => {
const userPubKey = userKeypair.pubKey.asContractParam()
const contributionAmount = 1000;
const encodedContributorAddress = defaultAbiCoder.encode(['address'], [contributor.address]);
let tokenAsContributor: Contract;
let fundingRoundAsContributor: Contract;
Expand Down Expand Up @@ -172,7 +171,7 @@ describe('Funding Round', () => {
await fundingRound.setMaci(maci.address);
await tokenAsContributor.approve(
fundingRound.address,
contributionAmount * 2,
contributionAmount.mul(2),
);
await fundingRoundAsContributor.contribute(userPubKey, contributionAmount)
await expect(fundingRoundAsContributor.contribute(userPubKey, contributionAmount))
Expand Down Expand Up @@ -230,7 +229,7 @@ describe('Funding Round', () => {
});

describe('voting', () => {
const singleVote = 100;
const singleVote = UNIT.mul(4)
let fundingRoundAsContributor: Contract;
let userStateIndex: number;

Expand Down Expand Up @@ -289,10 +288,11 @@ describe('Funding Round', () => {
});

describe('finalizing round', () => {
const matchingPoolSize = 100000
const totalSpent = 10000
const matchingPoolSize = UNIT.mul(1000)
const totalSpent = UNIT.mul(100)
const totalSpentSalt = genRandomSalt().toString()
const totalVotes = 100; // Math.sqrt(totalSpent)
const totalVotes = bnSqrt(totalSpent)
expect(totalVotes.toNumber()).to.equal(10 * 10 ** 9)

beforeEach(async () => {
maci = await deployMaciMock()
Expand Down Expand Up @@ -430,13 +430,13 @@ describe('Funding Round', () => {
});

it('reverts if round has been finalized already', async () => {
const totalSpent = 10000
const totalSpent = UNIT.mul(100)
const totalSpentSalt = genRandomSalt().toString()
maci = await deployMaciMock()
await fundingRound.setMaci(maci.address);
await provider.send('evm_increaseTime', [signUpDuration + votingDuration]);
await maci.mock.hasUntalliedStateLeaves.returns(false)
await maci.mock.totalVotes.returns(Math.sqrt(totalSpent))
await maci.mock.totalVotes.returns(bnSqrt(totalSpent))
await maci.mock.verifySpentVoiceCredits.returns(true)
await fundingRound.finalize(totalSpent, totalSpentSalt)

Expand All @@ -459,7 +459,7 @@ describe('Funding Round', () => {

describe('withdrawing funds', () => {
const userPubKey = userKeypair.pubKey.asContractParam()
const contributionAmount = 1000;
const contributionAmount = UNIT.mul(10)
let tokenAsContributor: Contract;
let fundingRoundAsContributor: Contract;

Expand Down Expand Up @@ -497,21 +497,21 @@ describe('Funding Round', () => {
});

describe('claiming funds', () => {
const matchingPoolSize = 100000;
const totalSpent = 10000;
const matchingPoolSize = UNIT.mul(1000)
const totalSpent = UNIT.mul(100)
const totalSpentSalt = genRandomSalt().toString();
const totalVotes = 100; // Math.sqrt(totalSpent)
const totalVotes = bnSqrt(totalSpent)
const recipientIndex = 3;
const recipientClaimData = [
recipient.address, // recipient
totalVotes / 2, // Tally result
totalVotes.div(2), // Tally result
[[0]], // Proof
genRandomSalt().toString(),
totalSpent / 2, // Total spent
totalSpent.div(2), // Total spent
[[0]],
genRandomSalt().toString(),
];
const expectedClaimableAmount = matchingPoolSize / 2 + totalSpent / 2;
const expectedClaimableAmount = matchingPoolSize.div(2).add(totalSpent.div(2))
let fundingRoundAsRecipient: Contract;
let fundingRoundAsContributor: Contract;

Expand Down
17 changes: 15 additions & 2 deletions contracts/tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ import { bigInt, genRandomSalt } from 'maci-crypto';
import { Keypair, PubKey, Command, Message } from 'maci-domainobjs';

export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export const UNIT = BigNumber.from(10).pow(BigNumber.from(18))

export function bnSqrt(a: BigNumber): BigNumber {
// Take square root from a big number
// https://stackoverflow.com/a/52468569/1868395
let x
let x1 = a.div(2)
do {
x = x1
x1 = (x.add(a.div(x))).div(2)
} while (!x.eq(x1))
return x
}

export async function getGasUsage(transaction: TransactionResponse): Promise<number | null> {
const receipt = await transaction.wait();
Expand Down Expand Up @@ -69,15 +82,15 @@ export function createMessage(
userKeypair: Keypair,
coordinatorPubKey: PubKey,
voteOptionIndex: number,
voiceCredits: number,
voiceCredits: BigNumber,
nonce: number,
salt?: number,
): [Message, PubKey] {
const encKeypair = new Keypair();
if (!salt) {
salt = genRandomSalt();
}
const quadraticVoteWeight = Math.floor(Math.sqrt(voiceCredits));
const quadraticVoteWeight = bnSqrt(voiceCredits)
const command = new Command(
bigInt(userStateIndex),
userKeypair.pubKey,
Expand Down
24 changes: 13 additions & 11 deletions vue-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"test": "vue-cli-service test:unit"
},
"dependencies": {
"@openfonts/inter_all": "^1.0.2",
"core-js": "^3.6.4",
"ethers": "^5.0.1",
"luxon": "^1.24.1",
"vue": "^2.6.11",
"vue-class-component": "^7.2.2",
"vue-property-decorator": "^8.3.0",
Expand All @@ -20,25 +21,26 @@
},
"devDependencies": {
"@types/chai": "^4.2.8",
"@types/luxon": "^1.24.3",
"@types/mocha": "^5.2.4",
"@typescript-eslint/eslint-plugin": "^2.18.0",
"@typescript-eslint/parser": "^2.18.0",
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-plugin-eslint": "~4.2.0",
"@vue/cli-plugin-pwa": "~4.2.0",
"@vue/cli-plugin-router": "~4.2.0",
"@vue/cli-plugin-typescript": "~4.2.0",
"@vue/cli-plugin-unit-mocha": "~4.2.0",
"@vue/cli-plugin-vuex": "~4.2.0",
"@vue/cli-service": "~4.2.0",
"@vue/cli-plugin-babel": "~4.4.6",
"@vue/cli-plugin-eslint": "~4.4.6",
"@vue/cli-plugin-pwa": "~4.4.6",
"@vue/cli-plugin-router": "~4.4.6",
"@vue/cli-plugin-typescript": "~4.4.6",
"@vue/cli-plugin-unit-mocha": "~4.4.6",
"@vue/cli-plugin-vuex": "~4.4.6",
"@vue/cli-service": "~4.4.6",
"@vue/eslint-config-typescript": "^5.0.1",
"@vue/test-utils": "1.0.0-beta.31",
"chai": "^4.1.2",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"sass": "^1.25.0",
"sass-loader": "^8.0.2",
"typescript": "~3.7.5",
"typescript": "~3.9.3",
"vue-template-compiler": "^2.6.11"
}
}
Loading