Let's talk about governance

How the clr.fund should be governed?

I suggest that we use the principle of separation of powers and keep the the matching funds out of funding round factory contract.

The matching pool contract should serve as a wallet with a permanent address, so dapps and protocols can direct fees into it. The govenance of this contract would mean choosing which clr.fund instance receives funding and at what rate. The exact model of governance should depend on the nature of funding sources.

The clr.fund instance will not hold anything and the matching funds will be transferred directly from matching pool contract to funding round contract at the end of voting period, allowing the governors of the matching pool to cut the funding at any time. The governance of clr.fund instance would be limited to selecting recipient curation and user verification mechanisms, setting MACI parameters and appointing the coordinator. To cover the costs of managing the clr.fund instance its owners may register as a QF recipient or they can take a small fee from each transfer of matching funds.

1 Like

We actually talked a lot about governance early on and came to the conclusion that introducing any governance on matching funds (beyond QF) would introduce more problems than it would solve.
For example, many funding sources (protocols, block rewards, etc) would be unable to participate in governance, and thus those that could would have disproportionate control over funding.

Ultimately, we decided that once funds are contributed to the matching pool, the former owner loses all claim over them and the only way they should leave the matching pool is via the QF mechanism.

The governance power that matching fund contributors do have is to vote with their feet. If the instance of clr.fund is not distributing funds in a way they like, contributors can simply cut off future funding.

Obviously, this puts a lot more power in the owner role, so we should be cautious to make sure it is not captured / perverted.

The route that I imagine for that is to start with owner being the clr.fund multi-sig. The owner role should then be transferred to a DAO of some description, some options that I like are:

  • the clr.fund colony, assuming that it 1. has the capability to call arbitrary functions on other contracts and 2. has a wide enough reputation distribution to be better than the multi-sig (this is my primary reason for pushing us to use the colony from early on).
  • a futarchy DAO. While none exist yet, I actually think that this would be the best option, as we could base decisions on predictions of how they will impact key metrics (like funds contributed, number of contributors, funds distributed, etc). It would also be much less prone to capture, since there is such a strong profit motive for prediction market participants to be accurate, rather than self-motivated.

One thing this does bring up is our contract’s upgradability method. One thing we could look at doing is using EIP-2535 diamond standard contracts to separate concerns and limit which functions can be upgraded.

Transferring control over funds to the same people who run QF is not a solution either. This just makes the whole thing centralized. The funds should be kept separately and governed by the entity that provides funding:

“Governance” could mean anything here, because there’s always some governance. In most extreme case there’s a governance by hard fork.

I agree, and this is what I’m talking about in my post: we need archictecture that would allow matching pool contributors to implement their own exit mechanism. Because in cases of funding by protocol fees or block rewards there will be no simple off-switch. Basically, we need to replace “push” transfers with “pull”.

I think there is a distinct difference between transfering the funds to something like the clr.fund multi-sig and transferring funds to the matching pool (fundingRoundFactory), because no code exists at the fundingRoundFactory for the owner to exit with the funds directly.

This is the part that I disagree with, because:

  1. having additional code that allows people to withdraw from the matching pool increases the attack surface.
  2. many of the matching pool contributors will have no ability to exit with the funds they contributed.

Right, I agree. But there also would be no simple governance mechanism for those fees either.
And even if the only governance is that contributors can remove whatever they’ve deposited, it hasn’t really solved the problem for protocol fees and block rewards because, as you mentioned, there is no simple off-switch for those funding sources.

In reality though, all this is doing is kicking the can down the road. There is always going to be a “push” transfer, either to fundingRoundFactory or to the governed wallet that you’re suggesting.
Given that some funding sources will be unable to participate in this governance, it seems like inappropriate (and may introduce perverse incentives) to hand over governance to those contributors who can participate.

So what are you actually suggesting for governance of these pools then?
I think it’s really difficult to make a call on this without an idea of what the governance mechanism will be.

I’m not suggesting anything, there’s no governance mechanism that fits everyone. The governance is to be decided by those who provide funding, that’s the whole point.

Run me through how you imagine this pull mechanic working.

Say we’ve got one instance of clr.fund and three different pools, each with a different governance mechanism. How do funds get from these pools to the recipients?

Each pool contract should implement a standard interface that enables interaction with clr.fund contracts.

Then clr.fund instance admins register these three pools as funding sources in FundingRoundFactory contract. When the funding round ends, someone calls transferMatchingFunds(), which iterates over the list of funding sources, calls each pool contract and transfers the allowed amount to funding round contract.


Let’s consider the simplest case, when there’s no governance mechanism at all. This means that the matching pool contract is immutable and transferMatchingFunds() simply transfers all available funds. This is equivalent to our current design where matching funds are locked in FundingRoundFactory. But the architecture is more flexible and enables customization.

The matching pool contract could be used for various purposes, not necessarily for governance. For example, rate limiting: someone puts 100K DAI into matching pool contract but allows clr.fund instance to spend only 10K DAI per month.

1 Like

Ok, I’m onboard with this architecture change. It’s a solid improvement.

How do you think this should be prioritized?

Important for R1 or something we should implement as an improvement post R1?

I’d lean towards after R1, just so we don’t slow ourselves down with scope creep. But I could be convinced otherwise.

I think it’s definitely not a top priority and could be implemented post R1 (once we collect enough feedback from the potential funding partners).

1 Like