Multi choice voting

Moonbeam has seen the need to use off-chain solutions to gauge community sentiment and let the stakeholders have a say in multiple important decisions, like grants and technical solutions.

Let’s take the unsustainable storage growth solution voting as an example on the Moonbeam Foundation’s current process. The Foundation created an off-chain proposal to snapshot.org in a weighted voting system with multiple options where stakeholders can vote with their free balance at the latest block at the time the proposal was created (there is transaction of any kind involved, the user only need to sign a message to vote). After the snapshot voting closed, the Foundation then created two separate on-chain remark proposals, and took the referenda with more aye votes as the “winner”, and went ahead to implement that solution.

As you can see, this is a bit convoluted, and puts additional friction to participate in governance. Ideally there should be an on-chain mechanism that allows this types of ecosystem affecting votes, without relaying on off chain services, also allowing locked funds to be available for voting.

And not only for “signal” voting, but also allow weighted decisions on subjects like choosing members for a collective, where a stakeholder can reflect different support levels for multiple members in a single vote (i.e. 100 tokens for member one, 30 tokens for member two, 0 for all other candidates).

@brenzi proposed a neat immediate solution to a similar problem for treasury proposals, that could be expanded to cover at least the case for signal voting, but it’s a bit obscure.

Is it possible to expand OpenGov to cover these cases? I understand that expanding beyond the aye/nay structure can be quite complicated.

Is it better to have a separate mechanism/pallet for this?

Giving it more thought, one way that this could be achieved is that a referendum can have multiple preimages (with a set limit), each of those being the posible outcomes the referendum could have. This can be seen as a “batch” of preimages in a single referendum, where tokenholders can vote aye/nay on each (some/all) of the options.

Simple aye/nay referendums would still be possible as a single preimage proposal.

When submitting a referendum proposal, some parameters could be defined to set additional conditions, like:

  • Max number of preimages to execute if successful: The top N preimages will be executed
  • Min support: Minimum amount of aye votes a preimage needs to be successful. Should be in line with the selected track

I think the modified base types would look something like:

ReferendumStatus

pub struct ReferendumStatus<...> {
    ...,
    pub proposal: BoundedVec<Call, MaxCalls>,
    ...,
}

Tally

pub struct CallVote<Votes> {
    pub ayes: Votes,
    pub nays: Votes,
    pub support: Votes,
}
pub struct Tally<Votes> {
    pub votes: BoundedVec<CallVote, MaxCalls>,
    dummy: PhantomData<Total>,
}

Casting

pub struct Casting<Balance, BlockNumber, PollIndex, MaxVotes> {
    pub votes: BoundedVec<(PollIndex, BoundedVec<AccountVote<Balance>, MaxCalls>), MaxVotes>,
    pub delegations: Delegations<Balance>,
    pub prior: PriorLock<BlockNumber, Balance>,
}