Skip to content

Commit

Permalink
merged with develop branch
Browse files Browse the repository at this point in the history
  • Loading branch information
yuetloo committed Aug 29, 2023
2 parents c2d9ced + d9ed7ce commit 0bf465f
Show file tree
Hide file tree
Showing 128 changed files with 10,266 additions and 4,235 deletions.
19 changes: 16 additions & 3 deletions .github/workflows/finalize-round.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
name: Finalize a test round

on: workflow_dispatch
on:
workflow_dispatch:
inputs:
branch_name:
description: 'Clrfund branch name'
required: true
default: 'develop'
subgraph_name:
description: 'Clrfund subgraph name'
required: true
default: 'yuetloo/clrfund-dev'

env:
NODE_VERSION: 16.x
SUBGRPAH_URL: "https://api.thegraph.com/subgraphs/name/clrfund/clrfund-arbitrum-goerli"
NETWORK: "arbitrum-goerli"
COORDINATOR_ETH_PK: ${{ secrets.ARBITRUM_GOERLI_COORDINATOR_WALLET_PRIVATE_KEY }}
COORDINATOR_PK: ${{ secrets.ARBITRUM_GOERLI_COORDINATOR_MACI_PRIVATE_KEY }}
Expand Down Expand Up @@ -33,6 +42,8 @@ jobs:
cargo install zkutil --version 0.3.2
- name: Checkout source code
uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.branch_name }}
- name: Download batch 64 params
run: |
ls -la $GITHUB_WORKSPACE
Expand All @@ -42,6 +53,8 @@ jobs:
yarn && yarn build
- name: Run finalize scripts
run: |
export SUBGRPAH_URL="https://api.thegraph.com/subgraphs/name/${{ github.event.inputs.subgraph_name }}"
echo $SUBGRAPH_URL
export NODE_CONFIG=$(node -e "const snarkParamsPath=process.env.GITHUB_WORKSPACE + '/params'; console.log(JSON.stringify({ snarkParamsPath }));")
export ROUND=$(curl -X POST -d '{"query":"{fundingRoundFactories {id currentRound {id maci}}}"}' $SUBGRPAH_URL)
export FACTORY_ADDRESS=$(node -e 'console.log(JSON.parse(process.env.ROUND).data.fundingRoundFactories[0].id)')
Expand All @@ -53,7 +66,7 @@ jobs:
echo "MACI_START_BLOCK:" $MACI_START_BLOCK
# tally and finalize
cd contracts
yarn hardhat run --network "${NETWORK}" scripts/tally.ts
yarn hardhat tally --round-address "${ROUND_ADDRESS}" --network "${NETWORK}"
curl --location --request POST 'https://api.pinata.cloud/pinning/pinFileToIPFS' \
--header "Authorization: Bearer ${{ secrets.PINATA_JWT }}" \
--form 'file=@"tally.json"'
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export VITE_IPFS_PINNING_JWT=x
export VITE_IPFS_PINNING_URL=x
export VITE_RECIPIENT_REGISTRY_TYPE=simple
export VITE_USER_REGISTRY_TYPE=simple
export VITE_WALLET_CONNECT_PROJECT_ID=1

yarn test:format && yarn test:web && yarn test:lint-i18n
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16.14.2
18.4.0
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The clr.fund smart contracts consist of a factory contract that deploys a new co
3. **Contributor:** Any address that contributes tokens to the funding round.
4. **Recipient:** Any address that is registered as funding recipient.

The clr.fund application can use any [EVM-compatible chain](https://ethereum.org/) as a backend. The application can be hosted on [IPFS](https://ipfs.io/) and can also run locally.
The clr.fund application can use any [EVM-compatible chain](https://ethereum.org/) as a backend. The application can be hosted on [IPFS](https://ipfs.tech/) and can also run locally.

For more details, see the [sequence diagram](docs/clrfund.svg) and [clr.fund constitution](https://github.com/clrfund/constitution).

Expand Down Expand Up @@ -55,6 +55,7 @@ In a future version, we plan to address this by routing ETH and token contributi
- [Deployment](docs/deployment.md)
- [Providing matching funds](docs/funding-source.md)
- [How to tally votes and verify results](docs/tally-verify.md)
- [How to donate to projects](docs/howto-use-app.md)
- [Running the subgraph](docs/subgraph.md)
- [Sitemap](docs/sitemap.md)
- [Website theme and customization](docs/theme.md)
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Common clr.fund utility functions used by contracts and vue-app
31 changes: 31 additions & 0 deletions common/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@clrfund/common",
"version": "0.0.1",
"description": "Common utility functions used by clrfund scripts and app",
"main": "src/index",
"scripts": {
"build": "tsc",
"lint": "eslint 'src/**/*.ts'",
"clean": "rm -rf build"
},
"license": "GPL-3.0",
"devDependencies": {
"eslint": "^8.31.0",
"typescript": "^4.9.3"
},
"dependencies": {
"@openzeppelin/merkle-tree": "^1.0.5",
"ethers": "^5.7.2",
"maci-crypto": "1.1.1",
"maci-domainobjs": "1.1.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/clrfund/monorepo.git"
},
"author": "",
"bugs": {
"url": "https://github.com/clrfund/monorepo/issues"
},
"homepage": "https://github.com/clrfund/monorepo#readme"
}
20 changes: 20 additions & 0 deletions common/src/block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { providers, utils } from 'ethers'

export interface Block {
blockNumber: number
hash: string
stateRoot: string
}

/*
* get the block stateRoot using eth_getBlockByHash
*/
export async function getBlock(
blockNumber: number,
provider: providers.JsonRpcProvider
): Promise<Block> {
const blockNumberHex = utils.hexValue(blockNumber)
const blockParams = [blockNumberHex, false]
const rawBlock = await provider.send('eth_getBlockByNumber', blockParams)
return { blockNumber, hash: rawBlock.hash, stateRoot: rawBlock.stateRoot }
}
7 changes: 7 additions & 0 deletions common/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './block'
export * from './proof'
export * from './merkle'
export * from './ipfs'
export * from './keypair'
export * from './tally'
export * from './utils'
18 changes: 18 additions & 0 deletions common/src/ipfs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { utils } from 'ethers'

const IPFS_BASE_URL = 'https://ipfs.io'

/**
* Get the IPFS content given the IPFS hash
* @param hash The IPFS hash
* @param gatewayUrl The IPFS gateway url
* @returns The IPFS content
*/
export async function getIpfsContent(
hash: string,
gatewayUrl = IPFS_BASE_URL
): Promise<any> {
const url = `${gatewayUrl}/ipfs/${hash}`
const result = utils.fetchJson(url)
return result
}
File renamed without changes.
37 changes: 37 additions & 0 deletions common/src/merkle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { StandardMerkleTree } from '@openzeppelin/merkle-tree'

/**
* Load users into a merkle tree
* @param users Users to load
* @returns user merkle tree
*/
export function loadUserMerkleTree(
users: string[]
): StandardMerkleTree<string[]> {
const tree = StandardMerkleTree.of(
users.map((user) => [user.toLowerCase()]),
['address']
)
return tree
}

/**
* Get the merkle proof for the user
* @param userAccount User wallet address to get the proof for
* @param userMerkleTree The merkle tree containing all approved users
* @returns
*/
export function getUserMerkleProof(
userAccount: string,
userMerkleTree: StandardMerkleTree<string[]>
): string[] | null {
try {
return userMerkleTree.getProof([userAccount.toLowerCase()])
} catch (err) {
console.log('userAccount', userAccount.toLowerCase())
console.log('getUserMerkleProof error', err)
return null
}
}

export { StandardMerkleTree }
85 changes: 85 additions & 0 deletions common/src/proof.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { utils, providers } from 'ethers'

/**
* RLP encode the proof returned from eth_getProof
* @param proof proof from the eth_getProof
* @returns
*/
export function rlpEncodeProof(proof: string[]) {
const decodedProof = proof.map((node: string) => utils.RLP.decode(node))

return utils.RLP.encode(decodedProof)
}

/**
* The storage key used in eth_getProof and eth_getStorageAt
* @param account Account address
* @param slotIndex Slot index of the balanceOf storage
* @returns storage key used in the eth_getProof params
*/
export function getStorageKey(account: string, slotIndex: number) {
return utils.keccak256(
utils.concat([
utils.hexZeroPad(account, 32),
utils.hexZeroPad(utils.hexValue(slotIndex), 32),
])
)
}

/**
* Get proof from eth_getProof
* @param params Parameter fro eth_getProof
* @returns proof returned from eth_getProof
*/
async function getProof(
params: Array<string | string[]>,
provider: providers.JsonRpcProvider
): Promise<any> {
try {
const proof = await provider.send('eth_getProof', params)
return proof
} catch (err) {
console.error(
'Unable to get proof. Your node may not support eth_getProof. Try a different provider such as Infura',
err
)
throw err
}
}
/**
* Get the storage proof
* @param token Token contract address
* @param blockHash The block hash to get the proof for
* @param provider provider to connect to the node
* @returns proof returned from eth_getProof
*/
export async function getAccountProof(
token: string,
blockHash: string,
provider: providers.JsonRpcProvider
): Promise<any> {
const params = [token, [], blockHash]
return getProof(params, provider)
}

/**
* Get the storage proof
* @param token Token contract address
* @param blockHash The block hash to get the storage proof for
* @param userAccount User account to get the proof for
* @param storageSlotIndex The storage index for the balanceOf storage
* @param provider provider to connect to the node
* @returns proof returned from eth_getProof
*/
export async function getStorageProof(
token: string,
blockHash: string,
userAccount: string,
storageSlotIndex: number,
provider: providers.JsonRpcProvider
): Promise<any> {
const storageKey = getStorageKey(userAccount, storageSlotIndex)

const params = [token, [storageKey], blockHash]
return getProof(params, provider)
}
File renamed without changes.
14 changes: 11 additions & 3 deletions maci-utils/src/utils.ts → common/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigNumber } from 'ethers'
import { genRandomSalt, IncrementalQuinTree, hash5 } from 'maci-crypto'
import { PubKey, Command, Message } from 'maci-domainobjs'
import { PubKey, PCommand, Message } from 'maci-domainobjs'
import { Keypair } from './keypair'
import { utils } from 'ethers'
import { Tally } from './tally'
Expand Down Expand Up @@ -43,6 +43,7 @@ export function createMessage(
voteOptionIndex: number | null,
voiceCredits: BigNumber | null,
nonce: number,
pollId: BigInt,
salt?: bigint
): [Message, PubKey] {
const encKeypair = newUserKeypair ? newUserKeypair : userKeypair
Expand All @@ -54,12 +55,13 @@ export function createMessage(
? bnSqrt(voiceCredits)
: BigNumber.from(0)

const command = new Command(
const command = new PCommand(
BigInt(userStateIndex),
encKeypair.pubKey,
BigInt(voteOptionIndex || 0),
BigInt(quadraticVoteWeight.toString()),
BigInt(nonce),
pollId,
salt
)
const signature = command.sign(userKeypair.privKey)
Expand Down Expand Up @@ -108,4 +110,10 @@ export function getPubKeyId(pubKey: PubKey): string {
return id
}

export { Message, Command, IncrementalQuinTree, hash5, LEAVES_PER_NODE }
export {
Message,
PCommand as Command,
IncrementalQuinTree,
hash5,
LEAVES_PER_NODE,
}
File renamed without changes.
6 changes: 5 additions & 1 deletion contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Recipient registry type for local deployment: simple, optimistic
RECIPIENT_REGISTRY_TYPE=optimistic

# Supported values: simple, brightid
# Supported values: simple, brightid, snapshot, merkle
USER_REGISTRY_TYPE=simple
# clr.fund (prod) or CLRFundTest (testing)
BRIGHTID_CONTEXT=clr.fund
Expand Down Expand Up @@ -45,3 +45,7 @@ ETHERSCAN_API_KEY=
# ZK proof circuit type, based on MACI v0.10.1 circuit type as defined in utils/deployment.ts
# e.g. test, small, medium, x32, prod
CIRCUIT_TYPE=prod


# The IPFS gateway url used by the prepare-results.ts script
IPFS_GATEWAY_URL=
Loading

0 comments on commit 0bf465f

Please sign in to comment.