Making contributions to a funding round

@auryn and I were discussing the contibutor’s UI in Figma, and this came up:

There are four possible states here:

  1. No funds contributed, no projects in cart
  2. No funds contributed, projects in cart
  3. Funds contributed, no projects in cart
  4. Funds contributed, projects in cart

In 1 and 3, there is no need to show sliders because funds haven’t been contributed and/or there are no projects to display a slider on.
In 2 and 4, we should display the sliders, whether or not the user has already deposited funds to the round or sent the message containing their vote.

If the user hasn’t contributed any funds to the round yet (2), then the “fund” button should trigger a transaction that sends funds to the round and submits their message.

If the user has contributed funds already(4), then the “fund” button should just send a new message to replace their old message.

If the user is in state (4) but allocates more funding than they have deposited, then the “fund” button should trigger a transaction to deposit the additional funds and send the updated message.

In this post I want to address some of these points in more detail.

If the user hasn’t contributed any funds to the round yet (2), then the “fund” button should trigger a transaction that sends funds to the round and submits their message.

There are three stages in MACI lifecycle:

  1. Sign-up period. It starts immediately after the deployment of MACI contract. During the sign-up period voters should call signUp() method, which will register their public key and calculate the amount of voice credits they have (the amount of voice credits can not be changed later). Users can’t submit messages during this period.
  2. Voting period. It starts immediately after the sign-up period. During that period users (or someone on their behalf) can submit messages to MACI by calling the publishMessage() method. Sign-ups are not allowed anymore during this period.
  3. Processing period. It starts immediately after the voting period and lasts until the coordinator completes all the necessary operations.

As we can see, the sign-up and voting periods don’t overlap, so it’s not possible to sign up and submit message at the same time, unless we store the message somewhere and submit it later on behalf of a user (but we should avoid it, as it could require a lot of gas). This means that users will be probably required to interact with our system at least twice: when they contribute money (during the sign-up period) and when they vote (during the voting period).

Deploying the MACI at the end of the round doesn’t help, but adds even more friction, as users will need to interact with our system three times (again, unless we sign up and publish messages on behalf of a user):

  1. During the funding period, when they just contribute the amount they want.
  2. During the signup period, after the instantiation of MACI.
  3. During the voting period.

If the user is in state (4) but allocates more funding than they have deposited, then the “fund” button should trigger a transaction to deposit the additional funds and send the updated message.

It’s not possible to add voice credits once the user has been signed up. We can introduce the “funding period”, during which users will be able to deposit additional funds (we don’t actually need to instantiate MACI at the end of the round to do that), but that would require an additional interaction with our system, as I showed in a previous paragraph.

1 Like

Now we’re talking :slight_smile: This is very useful to know, now we have several scenarios and user flows to consider which I wasn’t aware earlier (hence my questions in Figma).
I’ll review all above and your feedback in Figma and make revisions accordingly.

2 Likes

Following up our discussion from Figma here’s a quick diagram on the user flow. Feel free to comment in file directly https://www.figma.com/file/HotZCx3zNptdm0wCzXtZKf/clr.fund?node-id=223%3A137

1 Like

This is exactly what we had planned in the original build. Grant it is gas intensive on whoever signs up, contributes, and submits votes on behalf of the user (we had envisioned this as part of the coordinator’s responsibilities), but it allows for a much better user experience; users only have to interact once and can make additional contributions throughout the round if they like.

If the signup period is and voting period cannot overlap, it will nerf some the virility of the Quadratic Funding mechanism, because contributors can’t complete the viral loop in one sitting.

In my opinion, the UX improvement is worth the additional gas cost on the coordinator.

@weijiekoh I know we talked about this in the past. If I recall correctly, we had discussed the ability to have the signup and voting periods overlap, allowing users to:

  1. signup at any point before the round closes
  2. contribute and top up at any point between signing up and the round closing
  3. submit vote messages at any point between signing up and the round closing

Was there ever any progress made on this?

If 500 users each contribute to 5 projects, coordinator will have to make 2500 publishMessage() calls. If we take into account current gas prices, that would roughly translate into $2500 in fees. The system will become less autonomous and more dependent on the coordinator and their funding. It also allows coordinator to censor votes, because the MACI contract can not know whether all messages have been submitted or not.

I think you’re baking in an assumption on that these are all separate transactions. I’m sure we could amortize the transaction costs by batching function calls into larger transactions (constrained by the block gas limit, of course).

Also, a message can contain multiple votes, no? So 500 users contributing to 5 projects each would only require 500 messages, so far as I’m aware.

I think the dependence on the coordinator is kind of a moot point because the system is already quite dependent on them.

Yes, we can batch them. I think we need to do that even in case when contributors submit votes by themselves, to avoid asking them to confirm each publishMessage() call separately. I created a new issue for that: https://github.com/clrfund/monorepo/issues/59. I’m going to implement it and measure the gas costs.

No, according to MACI docs a message can contain only a single command.

I am against the idea of giving them even more power. But for the PoC we can make this tradeoff, in hope that future versions of MACI would allow signups and voting at the same time:

The sign-up period ends after a predefined deadline. A later version of MACI will allow ongoing sign-ups where state trees will be merged once per week.

(source)

1 Like

Hi all! Following up from the User Flow diagram and discussion in Figma comments here’s a demo prototype covering main scenarios we identified. https://share.getcloudapp.com/NQugYog0

You can try it yourself here https://www.figma.com/proto/HotZCx3zNptdm0wCzXtZKf/clr.fund?node-id=273%3A2&viewport=342%2C185%2C0.14486059546470642&scaling=scale-down-width

Let me know (in Figma) if you have any comments. Thanks!

1 Like

@markop, this is looking really great!

I implemented the submitMessageBatch() method and did the measurements.

Direct call to publishMessage(): ~756000 gas

Batch submission:

  • 1: 688190 gas (no idea why it costs less than direct call :smile: )
  • 2: 1307320 gas
  • 3: 1921400 gas
  • 10: 6220909 gas (~18% cheaper than doing 10 direct calls).

Submitting 100 messages (100 users 1 vote each) today would cost us: 6220909 gas * 10 * 40 Gwei = 2.4883636 ETH = 573.4 USD.
Submitting 2500 messages (500 users 5 votes each) today would cost us 14335 USD.

What I’m hearing is that we should be building this whole thing on Optimistic Rollup, lol.

Seriously though that’s super expensive.

2 Likes