This ZIP outlines the design and implementation of zrml-futarchy.
Futarchy is a mode of governance defined by R. Hanson in [RH03]. An organization (nation, city, corporation, DAO, etc.) governed by futarchy selects its values (how is welfare measured?) using some form of a democratic vote, but uses prediction markets in which informants bet on their beliefs to aggregate information on which policies will improve the organization's welfare and which policies won't.
In futarchy, decisions about policy are delegated to prediction markets. In
these markets, the efficacy of the policies is estimated in terms of a
pre-defined welfare measure, a scalar measure of how well things are going for
the organization. Depending on the measurements made using the prediction
markets, the policy is either adopted or not. By proceeding in this fashion,
organizations governed by futarchy rely on the
Wisdom of the Crowd instead
of the "public relations teams, organized interest groups, news media,
conversation forums, think tanks, universities, journals, elite committees, and
state agencies" (see What is Futarchy? - Trading on The Future - Friederike Ernst #TOA18). Decisions are based purely on merit (improving the welfare
measure) and those who promote bad or corrupt policy are economically punished,
even if they succeed in the short term.
Futarchy also represents an alternative to the typical approaches to on-chain
governance. As on-chain identities do not necessarily correspond one-to-one to
off-chain identities, "One man, one vote" democracy is infeasible in the
blockchain context. Previous endeavours to finding a good replacement
(Polkadot democracy,
token holder votes,
token curated registries)
have mostly led down the same road: token-based voting.[^3] This essentially
puts the decisions into the hands of the powerful few. Futarchy walks a
different path. Once the welfare measure is set, policy decision become matter
of fact and are decided upon not by vote, but by bet.
It's easiest to illustrate this new concept through the use of an example.
Suppose that a group wants to make large-scale decisions using futarchy. This is
done by first selecting the welfare measure In case of a publicly traded
company, this could be the stock price of the company.
When a yay/nay decision needs to be made (for example: "Should we fire our CEO?"
for a public company), two scalar markets are created:
These markets will run for some time and provide a prediction for which decision
is better: The difference
approximates the effect of firing the CEO on the stock price. If the estimate of
increase. This means that the CEO actually gets fired and the trades of
are cancelled (this is done as we have no way of ever knowing what the stock
price would have been if the CEO had remained in place). If, on the other hand,
the estimate of
and the trades of
The traders in favor of firing the CEO can buy exposure to both markers by
acquiring LONG shares of
favor of keeping the CEO in place can buy SHORT of
Therefore, both parties have skin in the game regardless of what decision is
eventually made. If the decision turns out to be good (stock price is as
predicted or higher), then the traders will on average profit from participating
in the market. If the decision turns out to be bad (stock price is lower than
predicted), then most traders will suffer losses.
Other scenarios can be approached using this pattern. If a political party
wishes to select a candidate in order to maximize their change of winning, they
might select their share of the popular vote as the welfare measure and open a
scalar market for each candidate
Of course, these are only toy examples of applications of futarchy. The
processes above can be embellished in a multitude of ways. For example, maybe
the motion to fire the CEO should only be put into action if there is a clear
difference between the stock prices
encourage you to take a look at section IX. A Reference Proposal of
Shall We Vote on Values, But Bet on Beliefs?
for a deeper dive into the topic.
The futarchy governance flow we will implement is deliberately kept simple:
An oracle is an on-chain object which can, at any point in time, be evaluated and returns either true
or false
.
What we've described so far is just an oracle-based governance system. What makes this actual futarchy is the choice of oracle. In the first iteration of Zeitgeist's futarchy, the oracle is comprised of the following data:
The oracle evalulates positively on a block
Using this oracle, the standard futarchy design described in the section above can be implemented as follows:
The proposal will then only be enacted if the market predicts that
The futarchy service is implemented as a substrate pallet and will be used in the Zeitgeist and Battery Station runtimes. Here is a rough outline of the pallet's Config
:
ScheduleAnon
trait. In production, pallet-scheduler will be used to implement this trait.Oracle
type to allow testing its functionality against a mock oracle. The Oracle
type must implement the FutarchyOracle
trait provided by zeitgeist-primitives:pub trait FutarchyOracle {
/// Evaluates the query at the current block and returns the weight consumed and a `bool`
/// indicating whether the query evaluated positively.
fn evaluate(&self) -> (Weight, bool);
}
The oracle type used in production will be implemented using zrml-neo-swaps. Specifically, neo-swaps will provide the DecisionMarketOracle
type which implements FutarchyOracle
by looking up self.pool_id
, and then querying and comparing the prices of the specified outcomes. It will be implemented pessimistically in the sense that if the pool is not found or a calculation errors unexpectedly, then it will evaluate negatively.
The only extrinsic of zrml-futarchy is submit
:
/// Submits a `proposal` for evaluation in `duration` blocks.
///
/// If, after `duration` blocks, the oracle `proposal.oracle` is evaluated positively, the
/// proposal is scheduled for execution at `proposal.when`.
pub fn submit_proposal(
origin: OriginFor<T>,
duration: BlockNumberFor<T>,
proposal: Proposal<T>,
) -> DispatchResult;
The proposal type mentioned in the signature of submit_proposal
is:
pub struct Proposal<T>
where
T: Config,
{
/// The time at which the proposal will be enacted.
pub when: BlockNumberFor<T>,
/// The proposed call.
pub call: BoundedCallOf<T>,
/// The oracle that evaluates if the proposal should be enacted.
pub oracle: OracleOf<T>,
}
In production, calls will be bound using pallet-preimage.