Let's talk about recipient curation mechanisms

This has been one of the most discussed topics in our Telegram, so it’s only fitting that it be the first topic on the forum.

The issue, in brief, is that there is a finite number of recipient slots available for each MACI round (as limited by the coordinator’s computing power). That limit is currently 5^5 = 3,125.

To help prevent the system being gamed, and to ensure that legitimate projects are able to register as recipients, we will need a curation mechanism.

In our initial PoC rounds, we will simply whitelist a group of recipient projects that we manually select. But we will need something more robust and permissionless once we hit MVP rounds and beyond.

Some ideas that have been suggested:

  • Forked version of everest.link:
    The current version does not provide onchain access to categories or receiving addresses, so it is not suitable. But we could create a fork of it that includes this data on chain.
    Everest has the nice property of the metadata being readily available in their subgraph.
    However, there are also concerns with having existing projects curate as they have a strong financial incentive to deny any new entries to the list, even if they are valid.
  • Append-only registry with registration fee:
    Recipients pay a fee to register each round. After paying the fee, they are added to the recipient list. The target registration price should be such that buying all of the slots costs more than the total matching pool, thus there is no financial incentive to buy all of the slots in the round. The registration price could be set manually by the contract owner to start with, potentially being replaced with something that adjusts automatically in future.
  • Curation by external jury: as described by Kirill on GitHub
    Recipients could add themselves to the recipient list each round. They must deposit a stake to do so, and so long as no one raises a challenge, they get it back at the end of the round. If someone challenges the project during the challenge period, an external jury (Kleros or Aragon court) is used to determine if the recipient is valid.
    Recipients on the registry are also ranked by age and past value received, to determine priority into subsequent rounds.

Let’s carry on the discussion here.


In my proposal there are actually two registries: one is curated registry of projects with a challenge mechanism, and another one is a list of registered recipients for clr.fund. First registry is loosely coupled to our contracts and can be swapped to another registry (like Everest) using the mechanism described here. Second one is tightly coupled as it needs to be aware of the MACI’s vote option limit and the data on previous contributions. I updated my original post on GitHub to clarify this.

Any registration fee needs to balance spam and attack-reduction benefits with potential downsides.

For example, the higher the fee, the higher the cost to legitimate recipients.

This is especially the case for newer projects that have yet to receive much funding. Such projects by definition have less budget to spend on acquiring new funds, AND face significant uncertainty about the amount of support they are likely to receive from a given clr.fund. As a result, such projects may be quite sensitive to the size of the registration fee.

This would not necessarily be a problem if the important projects already exist and are well-known, but one of the key value propositions of a large QF protocol is discovering new projects that are nonetheless valuable to a meaningful contingent of the Ethereum network.

Potential mitigation
Somebody (perhaps the clr.fund dev team) could run a recipient project each round with the express purpose of refunding the registration fee for new or lower-funded recipients who that team judges to be legitimate (not spam or part of an attack). This judgement could begin as a centralized decision (e.g. recipients can apply to the operator to get their fee refunded) and potentially evolve into a more distributed mechanism.

As with any spam prevention, the fee should aim for the sweet spot that is both high enough to make spamming cost prohibitive and low enough that it doesn’t hinder real users.

Given the current limit of 3125, a price of $10 should be sufficient to make spamming the registry cost prohibitive, since it would cost 3x what we’ve talked about having in the matching pool to start with ($10k), while also being a relatively trivial sum for honest participants; if you’re not confident you can earn back your $10, you probably shouldn’t be submitting your project to the round anyway.

Obviously, the price and/or capacity will have to increase in future for this to be effective with much larger matching pools.

Just wanted to point out https://curate.kleros.io/, it seems to have the features we need in a curation mechanism.

I also just came across this. I haven’t read it yet but it could be relevant for a future version if privacy turns out to be important in a curation context.


Token-curated registries (TCRs) are a mechanism by which a set of users are able to jointly curate a reputable list about real-world information. Entries in the registry may have any form, so this primitive has been proposed for use— and deployed— in a variety of decentralized applications, ranging from the simple joint creation of lists to helping to prevent the spread of misinformation online. Despite this interest, the security of this primitive is not well understood, and indeed existing constructions do not achieve strong or provable notions of security or privacy. In this paper, we provide a formal cryptographic treatment of TCRs as well as a construction that provably hides the votes cast by individual curators. Along the way, we provide a model and proof of security for an underlying voting scheme, which may be of independent interest.

1 Like

The prediction market plaform Omen now uses Kleros Curate to manage the list of valid markets: https://curate.kleros.io/tcr/0xb72103eE8819F2480c25d306eEAb7c3382fBA612. This is very similar to our use case.

Yeah, I’ve been following this pretty closely. I almost spun up a list back in june, but the gas prices were too high. Regretting it now because they are even higher. lol.
But this looks like the best current option to me.

1 Like

Started an acceptance criteria doc here: https://docs.google.com/document/d/1BKyCVY2gkCiDOESu0HjQG14l2-1uELvz-ksByqZ_tNI/edit?usp=sharing

1 Like

Let’s try to tighten this up. Gas is cheap(er than it has been since DeFi went nuts), so we should capitalize on it and spin up the Kleros curate list ASAP.

1 Like

Here is our Kleros Curate TCR

1 Like

We’ve got a new entry in our registry: https://curate.kleros.io/tcr/0x2E3B10aBf091cdc53cC892A50daBDb432e220398/0x9fcfe7ef7ba3cae1163c0036a8ac15a3b98d3e82098c96f33335d3fea9b7ac15

But their logo image is not a square, so this entry can be challenged in court :laughing:

1 Like

This is actually the second time that this has happened. The commons stack did the same thing and was challenged. I’m actually interested to see if anyone challenges this one.

An better scaling solution for clrfund has not yet arrived, so we’ll continue to run funding rounds on xDai for some time.
Unfortunately Kleros TCR is not available on xDai chain. So we have two options (other than just waiting):

  • Read data from mainnet TCR. This would require some kind of oracle, but it seems that there is no such thing on xDai at the moment. Celeste subjective oracle is probably closer to launch than other solutions.
  • Create our own TCR, either by forking Kleros TCR (which seems like a lot of work) or by implementing a simplified version of it.

A simplified version of TCR could have API similar to Kleros Generalized TCR but actually be a simple registry managed by a trusted party. For that simplified version of TCR we can create an adapter which we can later reuse with real TCR on mainnet.

The xDai and Kleros team are both interested in creating a solution to allow contracts on xDai to query contracts on mainnet. We kicked off a discussion about it yesterday. But I have no idea if or when this will actually materialize into a solution that we can use.

I’m not sure I see a huge benefit to this. Other than the fact that it would have the same interface as Kleros so that we can swap them out later, it is no practical benefit over the current solution where our Safe is the gatekeeper.

I beleive 1Hive might deploy an instance of Aragon court, so perhaps that could be an alternate option to Kleros on xDai.

The benefit is that we can start working on it immediately, because for mainnet clrfund instance we’ll need this Kleros TCR adapter anyway. I don’t know if it is worth spending our resources on xDai-specific solutions if our goal is mainnet.

That’s fair. I’m on board with going for this route then.

I imagine that we could probably plug this into whatever solution xDai and Kleros come up with also, since they’ll probably want to keep the interface the same as well.

More analysis and discussion in this GitHub issue: https://github.com/clrfund/monorepo/issues/36


  • If we use Kleros TCR as is, clrfund will be susceptible to DoS attack. Currently the vote option limit is 125, so if required submission deposit is 0.05 ETH it would cost less than 6.25 ETH to fill a recipient list. Of couse, the limit can also be reached naturally if there’s enough interest from the community.
  • If we want to protect clrfund against this, the ranking mechanism is needed. We can implement our own or use something like Conviction Voting. Unfortunately it will make it a bit harder to become a valid recipient.

Another important question is how to identify recipients. Currently we use recipient’s eth address: http://clrfund.eth.link/#/project/0x4E2f7c052376727ff6F6DE2715850419ecacC302. But there are projects in TCR that share the same recipient address, so we need to either add a requirement for addresses to be unique to our recipient acceptance criteria or use something else as an identifier. Kleros TCR uses keccak256 hash of entry data as an identifier, we can use it as well (instead of eth address). For example, here’s the URL of clrfund entry: https://curate.kleros.io/tcr/0x2E3B10aBf091cdc53cC892A50daBDb432e220398/0xc9cc75acbd333a72719da5446fc1752406ae0922a3c8818f769d6156af04adeb, it contains the ID 0xc9cc75acbd333a72719da5446fc1752406ae0922a3c8818f769d6156af04adeb.

I’ve actually been wondering if we should use ENS names to identify recipients.

My rational being that:

  1. it’s perfectly reasonable to expect each recipient to have a different ENS name.
  2. because metadata can be linked to on the ENS name, it would mean that list items in Kleros could be much simpler (they would probably only require one field).
  3. because the metadata lives on the ENS name, it could be easily updated by whoever controls the ENS name.
  4. recipients could specify receiving addresses for different networks on their ENS name, so we don’t have to add/remove list items if/when we deploy to a new network.