Coder Social home page Coder Social logo

clrfund / monorepo Goto Github PK

View Code? Open in Web Editor NEW
186.0 15.0 90.0 271.51 MB

clr.fund dapp

Home Page: https://clr.fund/

License: GNU General Public License v3.0

JavaScript 0.16% TypeScript 69.64% Vue 23.33% HTML 0.02% Solidity 6.17% Shell 0.16% SCSS 0.50%
quadratic-funding maci

monorepo's Introduction

clr.fund

clr.fund is a permissionless and trust-minimized Quadratic Funding protocol. It uses Minimal Anti-Collusion Infrastructure (MACI) to protect against various forms of bribery and collusion with the use of zk-SNARKs. To protect from Sybil attacks it can use BrightID or a similar identity system.

clr.fund runs a continuous sequence of Quadratic Funding rounds, where anyone is able to add public goods projects as funding "recipients", contribute funds to the matching pool ("matching funds"), and contribute funds to individual recipients. To ensure that only public goods are added as recipients clr.fund can use curation mechanism such as Kleros Curate.

While clr.fund aims to be agnostic to the source of matching funds, it specifically aims to enable contributions from the following sources:

  1. Ethereum protocol rewards (Block rewards, transaction taxes, etc)
  2. Known and anonymous benefactors
  3. Benevolent protocols (MakerDAO, Burn Signal, etc)

In order for their contributions to count towards matching, contributors must verify their uniqueness.

The clr.fund smart contracts consist of a factory contract that deploys a new contract for each round. All matching funds are sent to the factory contract, while contribution funds are sent to the current round's contract. There are four roles in factory contract:

  1. Owner: This address (initially set to deployer) can set the address of coordinator, finalize a round by transferring matching funds to the current round contract, and set the token and round duration.
  2. Coordinator: This address is responsible for running the zk-SNARK computation on contributions to produce the relative percentages of matching funds that each recipient should receive. The coordinator can quit at any time, which invalidates the current round forcing the owner to start a new round and users to submit new MACI messages for their contributions. Without some advancement in oblivious computation, this Coordinator is necessarily a trusted party in this system (this is discussed more in the Limitations section).
  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 as a backend. The application can be hosted on IPFS and can also run locally.

For more details, see the sequence diagram and clr.fund constitution.

Some helpful blogposts to explain the clr.fund project:

Limitations

There are various limitations in our current design; we discuss some of them here.

Trusted Participants

The need for several trusted parties is the biggest limitation in the current design. The owner could, and likely will, be replaced with a DAO or some other decision-making mechanism which could alleviate the trust concern for this role.

However, without some breakthrough in oblivious computation, the zk-SNARK computations must necessarily be done by some trusted party who becomes a prime target for bribery as they are the only participant who can know the details of each contributor’s contributions.

Several solutions have been suggested, such as having the operator’s private keys and computations happen inside of some trusted computing environment or wallfacer-esque isolation of the operator. But most just kick the trust-can down the road a little further.

Single Token

For simplicity's sake in the contract, the zk-SNARK, and the user interface, clr.fund selects an ERC20 token as its native token (set by the contract owner), which is the only token that the funding round contract interacts with. This is an issue given our goal of being agnostic to the funding source.

For example, block reward funding would be in ETH, while many users may want to contribute DAI or other ERC20 tokens.

In a future version, we plan to address this by routing ETH and token contributions in anything other than the current native token through a DEX such as UniSwap.

Documentation

Development

Install Node v20 with nvm

nvm install 20
nvm use 20

Install the dependencies and build

yarn && yarn build

# Along with the dependencies, git hooks are also installed. At the end of the installation, you will see the following line after a successful setup.
husky - Git hooks installed

Copy configuration for contract deployment

# adjust the configuration for localhost if necessary
cp contracts/deploy-config-example.json contracts/deploy-config.json

Generate coordinator MACI key

yarn hardhat new-maci-key

Copy env for contracts

# update COORDINATOR_MACISK with the MACI key from previous step
# adjust other configuration if necessary
cp contracts/.env.example contracts/.env

Copy env for the webapp

cp vue-app/.env.example vue-app/.env    # adjust if necessary

Start the frontend app in development mode (hot-code reloading, error reporting, etc.)

In one terminal, init the hardhat node

yarn start:node

In a 2nd terminal you will need to run your graph node (more on this here)

cd subgraph/graph-node
docker compose up -d

And finally, in a 3rd terminal

# this will compile and deploy the contracts + deploy the subgraph + build and run the vue app
yarn start:dev

Other useful scripts

Compile the contracts

yarn build:contracts

Run unit tests

yarn test

Start the frontend sans a local blockchain

yarn start:web

Lint the files

yarn lint

Git hooks

Pre-commit

Prettier is executed on the staged files to keep a consistent format style across the codebase.

Pre-push

yarn test:format and yarn test:web is going to be triggered to ensure that the code is in good shape.

As you can see, we are only checking the web (/vue-app) tests and not the contracts ones. This is because there are not changes very often in the /contracts folder. However, if you do make a change in /contracts don't forget to run yarn test or yarn test:contracts.

Tech stack resources

Visual Studio Code

As a recommendation, use the Vetur extension. It gives you some useful features for Vue like syntax highlights, autocomplete, etc.

Create a vetur.config.js file at the project root with the following content:

/** @type {import('vls').VeturConfig} */
module.exports = {
  settings: {
    'vetur.useWorkspaceDependencies': true,
  },
  projects: [
    {
      root: './vue-app',
      package: './package.json',
      tsconfig: './tsconfig.json',
      globalComponents: ['./src/components/**/*.vue'],
    },
  ],
}

monorepo's People

Contributors

adamstallard avatar auryn-macmillan avatar corwintines avatar crisgarner avatar daodesigner avatar dependabot[bot] avatar johnson86tw avatar maxgrok avatar minimalsm avatar omahs avatar patil2099 avatar pettinarip avatar proofoftom avatar pumpkingwok avatar ryancreatescopy avatar samajammin avatar siftal avatar wackerow avatar xuhcc avatar yuetloo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

monorepo's Issues

Funding Round contract: Additional testing

Unit tests:

  • Publish key-changing message.
  • Vote with invalid key.
  • Vote for invalid vote option.
  • Claim zero amount.
  • Empty matching pool.

We may also want to turn buidler scripts (#81) into integration test suite.

Initial Voice Credit Proxy: Verify the amount

FundingRoundVoiceCreditProxy contract must verify the amount by calling the FundingRound contract. If possible, calling contribute() must be the only way to sign up for MACI voting.

Script for test round deployment

Create a buidler script that will do the following:

  • Deploy ERC20 token contract.
  • Set native token for funding round factory.
  • Set coordinator.
  • Contribute tokens to the matching pool.
  • Register dummy recipients.
  • Deploy funding round.
  • Deploy MACI.

Need an array of recipients corresponding the the vote options in MACI

mapping(address => string) public recipients;

Votes in MACI are cast for an index, rather than a specific address. So we need an array of addresses that corresponds to the vote options in MACI.

Here is an example of how we might build such an array, along with a mapping for convenient two-way lookup.
https://github.com/clrfund/registry/blob/master/contracts/Registry.sol

View previous rounds

Visitors and contributors can view funding results from previous rounds

Related: funding analytics

View previous contributions

Contributor can see their previous contributions within a round

View can see recipient contribution totals from previous rounds

Factory Contract: Enable switching between different recipient curation mechanisms

Add method for setting recipient registry proxy:

function setRecipientRegistryProxy(address _registryProxy)

A registry proxy must implement the following interface (to be discussed):

contract RecipientRegistryProxy {
    function isValidRecipient(address _recipient)
}

Then in our contracts we can use it like that:

function addRecipient(address _recipient) {
    require(recipientRegistryProxy.isValidRecipient(_recipient));
}

Coordinator Interface

Some kind of interface allowing the coordinator to...

  • Generate MACI constructor parameters
  • deploy MACI
  • run zk-snark
  • submit results on-chain

Per-round matching fund smoothing

Smooth out the matching fund amounts per round.

This is important for (at least) the following reasons:

  1. There may be an attack vector relating to intentionally spiking the matching funds of a given round
  2. If recipients have reason to expect a future round could have significantly higher matching funds, they may delay participation to conserve their social & marketing capital in case that happens. This would have the effect of diluting the quality of recipients in current rounds.
  3. The existence of funding for future rounds will imbue users/participants/stakeholders with a level of incremental confidence in the system as a whole.

Potential implementations:

  • Matching funds are contributed to an "endowment" pool. Each round draws its matching funds from X% (e.g. half) of the existing funds in the endowment pool.
  • We set (gradually increasing?) per-round matching fund caps. All matching funds contributed beyond the cap of the upcoming round are automatically allocated to the following round, and so on.

Run the funding round on testnet

Testnet round checklist:

  • Choose testnet -> Goerli
  • Appoint owner (could be a DAO or multisig)
  • Deploy token contract to testnet or choose the existing one -> https://github.com/bokkypoobah/WeenusTokenFaucet
  • Deploy funding round factory to testnet -> 0x7f75FAE7FeDF7B3958BE27C2CF5E048D2fDdC238
  • Deploy frontend to IPFS
  • Appoint coordinator
  • Choose MACI parameters
  • Register recipients
  • Register contributors
  • Start funding round

Nested clr.fund instances?

Recipient projects may belong to categories with distinct characteristics that would be best funded by distinct clr.fund instances. For example:

  1. Project teams of certain categories may have a more (or less) direct relationship with the individuals their project benefits, creating distinct dynamics relating to projects ability to attract contributions. See the media section of Gitcoin Grants.
  2. Groups of projects may have such different purposes as to dilute the schelling point of a shared funding pool, which could hurt the pool's ability to attract marginal contributors or matching funds.

So we should just have separate funds, right?
We probably should. But doing so comes with some decentralization and credible neutrality challenges. Once categories are defined, filtering recipients into categories isn't a problem: recipients can self-select into categories, and contributors can police that self-selection with their contribution choices (e.g. "don't fund a media project in the tech category"). The bigger issue is with deciding what the categories should be.

Who gets to make that decision? And who decides how matching funds get allocated to each category? Gitcoin Grants, for example, decided a few rounds ago to separate Media and Tech projects into their own categories. This was probably the right decision given how much of a fundraising / shilling advantage the top media projects have over everything else (see example 1 above), but should we be ok with one or two people unilaterally making that decision? If we're trying to build a credibly neutral fundraising platform, the answer is No.

So what can we do?
Instead of a few people making the decision, we can let the community decide what the categories should be and how much funding they get. We already have a great mechanism to do this: clr.fund itself!

The idea is to nest instances of clr.fund within other instances, creating a multi-level hierarchy of instances:

  • The highest level (L0) has one instance of clr.fund and is responsible for selecting and allocating funds to each category of projects. Example categories -- "Ethereum Protocol-Level Development," "Ethereum Application-Layer Development," "Ethereum Media"
  • The lowest level (Ln) has many instances of clr.fund: one for each category identified in higher levels. Each instance is responsible for selecting and allocating funds to individual recipient projects within the given category. Example recipients w/in "Ethereum Protocol-Level Development" -- "Prysmatic," "Optimism," "OpenEthereum"
  • Each category receiving funds from a given instance triggers a new instance for the next round at the next level down. The total funds allocated to that category in the initial round become the matching funds in the next round.
  • There can be any number of intermediate levels (e.g. L1, L2, where sub-categories and sub-sub-categories can be selected and funded. For example, "Ethereum Protocol-Level Development" could be further split into layer 1, layer 2, ETH2, ETH1.x or any number of variations.
  • All of these levels are established organically. There's no requirement that a given instance be for categories or for projects. Categories and instances can be proposed and compete for funds within the same instance / level!
  • Contributors of both matching funds and matched funds can contribute at any level. For example, if I care about advancements in layer 2 scaling in general but am not sure which projects are most deserving, I can contribute to the layer 2 category within the "Ethereum Protocol-Level Development" instance. My funds then become part of the matching funds for layer 2 projects.

Create a subgraph for clr.fund

Build a subgraph for clr.fund

Prize Bounty

500 DAI

Challenge Description

Clr.fund is building a permissionless and credibly neutral quadratic funding protocol and application that is built with zk-snark magic, courtesy of the Minimal Anti-collusion Infrastructure MACI.

The clr.fund contracts are at a point where the interface should remain relatively stable, so we would like to make it easier on developers wanting to build tools and extensions to our protocol by providing a subgraph.

To earn this bounty, you should build a subgraph that indexes all of the events in the clr.fund contracts.

Submission Requirements

A valid submission should include a demonstration and source code of a working subgraph that indexes the following entities and fields for the clr.fund contracts:

Clr.fund

  • Total funding allocated in USD over all time
  • Total matching funds allocated in USD over all time
  • Total direct contributions in USD over all time
  • Total direct contributors over all time
  • Total matching pool contributors over all time
  • Total recipients over all time
  • Current token
  • Current round number

Round

  • Round number
  • Round address
  • MACI address
  • Coordinator public key
  • token for this matching round
  • Total matching funds allocated in token for this round
  • Total direct contributions in token for this round
  • Total matching pool contributors for this round
  • recipientTreeDepth: number;
  • startBlock: number;
  • nativeTokenAddress: string;
  • nativeTokenSymbol: string;
  • nativeTokenDecimals: number;
  • voiceCreditFactor: BigNumber;
  • status: string;
  • contributionDeadline: DateTime;
  • votingDeadline: DateTime;

Contribution

  • Type: matching pool or direct
  • Token:
  • Amount:
  • Contributor:
  • Round number

Claim

  • Recipient
  • Round number
  • Amount claimed in token
  • Total direct contributions
  • Total matching funds claimed

Contributor

  • Address
  • Contributions
  • Rounds where they made direct contributions
  • Rounds where they made matching pool contributions
  • Total direct contributions in USD
  • Total matching pool contributions in USD

Recipient

  • Address
  • Rounds where they were eligible
  • Rounds where they have claimed
  • Claims
  • Total amount claimed, in USD
  • Total direct contributions claimed, in USD
  • Total matching funds claimed, in USD

Judging Criteria

This bounty will be awarded to the participant who submits the best subgraph as decided by the clr.fund contributors.

Winner Announcement Date

Shortly after the event.

Build a BrightID Verified User Registry contract

Build a BrightID Verified User Registry contract

Prize Bounty

500 DAI

Challenge Description

Clr.fund is building a permissionless and credibly neutral quadratic funding protocol and application that is built with zk-snark magic, courtesy of the Minimal Anticollusion Infrastructure MACI.

A critical property of quadratic funding is the assurance that each contributor is in fact a unique individual. We would like to use BrightID to ensure this.

To earn this bounty, you should implement a VerifiedUserRegistry contract that ensures only BrightID verified users can sign as contributors to each round of clr.fund.

Submission Requirements

A valid submission should include a demonstration and source code of working contract that Verified User Registry contract that allows only BrightID verified users to sign up as contributors to each clr.fund round.

To add BrightID support we need to create a contract which will conform to the VerifiedUserRegistry interface:

pragma solidity ^0.5.8; 
 pragma experimental ABIEncoderV2; 
  
 /** 
  * @dev Interface of the registry of verified users. 
  */ 
 interface IVerifiedUserRegistry { 
  
   function isVerifiedUser(address _user) external view returns (bool); 
  
 }

Judging Criteria

This bounty will be awarded to the participant who submits the best version of this contract as judged by the clr.fund contributors.

Winner Announcement Date

Shortly after the event.

MACI factory: setting MACI parameters

  • Only owner can change MACI parameters.
  • Parameters are expected to change rarely, so I think there's no reason to pass them to deployMaci() every time. A separate setter is preferred.
  • We probably don't want individual setters for each parameter, but a single method to set them all at once.

Factory contract: Remove recipients

Add removeRecipient() method to remove invalid entries or duplicates. It should emit an event to allow filtering on the frontend.

What to do with reserved indexes: still undecided, but I think we can simply invalidate MACI slots (see #19 (comment)).

Funding Round contract: Verify totals before finalizing the round

If owner finalizes the round and the coordinator doesn't publish the vote tally, or publishes incorrect data, the funds will be locked in the funding round contract because the recipients will not be able to provide necessary data to claimFunds() (though they can probably brute-force the results if there are only few voters).

This means that owner should wait until coordinator publishes the data and finalize the round only when there's enough evidence that the tally data is correct. To prevent owner from accidentally finalizing the round, we need to require that verifyTotals() is called before finalizing the round.

Funding Round contract: Add method for batch submission of messages

To improve contributor's experience, we need a method for batch submission of messages. I think it should be implemented in FundingRound contract because the size of MACI contract is already approaching limits.

function submitMessageBatch(Message[] memory _messages, PubKey[] memory _encPubKeys)

It seems that we also need to ensure that the first message is a key-change command.

https://github.com/appliedzkp/maci/blob/master/specs/01_introduction.md#high-level-process

A later version of MACI will have to mitigate a vote-buying attack where a user may be bribed immediately when the voting period starts, such that their very first message is influenced by a briber. One solution to this is to have the contract to mandate that the first message that each participant sends is to change their key (see below).

Recipient curation

Curation and discovery tools for recipients

The need for this is mitigated by the current MACI-imposed limit of 16 recipients, but if/as that constraint is relaxed and the recipient list proliferates, credibly neutral ways of surfacing recipients that a given contributor may be interested in will be come increasingly important. Otherwise, curation may instead occur on social media and devolve to a popularity contest.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.