Skip to content

Commit

Permalink
Merge pull request #58 from anoma/bengt/pgf-specs-update
Browse files Browse the repository at this point in the history
Update specs for pgf
  • Loading branch information
bengtlofgren committed Jun 29, 2023
2 parents 38da3ea + 5674e06 commit 6e0b9d1
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 73 deletions.
32 changes: 21 additions & 11 deletions packages/specs/pages/base-ledger/governance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,15 @@ The governance subkey, `/\$GovernanceAddress/proposal/\$id/funds` will be used a

### Supported proposal types

At the moment, Namada supports 4 types of governance proposals:
At the moment, Namada supports 5 types of governance proposals:

```rust
pub enum ProposalType {
/// Carries the optional proposal code path
Default(Option<String>),
StewardProposal,
PGFProposal,
StewardFundingProposal,
FundingProposal,
ETHBridge,
}
```
Expand All @@ -128,28 +129,37 @@ pub enum ProposalType {

- Can carry a wasm code to be executed in case the proposal passes
- Allows both validators and delegators to vote
- Requires 2/3 of the total voting power to succeed
- Requires $\frac{2}{3}$ of the total voting power to succeed
- Doesn't expect any memo attached to the votes

`StewardProposal` is a proposal to elect a steward for _Public Goods Funding_:
`StewardProposal` is a proposal to change the StewardSet for _Public Goods Funding_:

- Doesn't carry any wasm code
- Allows both validators and delegators to vote
- Requires 1/3 of the total voting power to vote `Yay`
- Requires $\frac{1}{3}$ of the total voting power to vote
- Requires $\frac{1}{2}$ of the total votes to be `Yay`

`StewardFundingProposal` is a proposal to *conduct* _Public Goods Funding_ **by a steward**:
- Can only be submitted by PGF stewards
- Allows both validators and delegators to vote
- Passes by default unless $\frac{1}{3}$ of the total voting power votes on the proposal, AND out of the votes, at least $\frac{1}{2}$ are `Nay`

`FundingProposal` is a proposal to *conduct* _Public Goods Funding_ **by anyone**:
- Allows both validators and delegators to vote
- Requires $\frac{1}{3}$ of the total voting power to vote
- Requires $\frac{1}{2}$ of the total votes to be `Yay`


`ETHBridge` is aimed at regulating actions on the bridge like the update of the Ethereum smart contracts or the withdrawing of all the funds from the `Vault` :

- Doesn't carry any wasm code
- Allows only validators to vote
- Requires 2/3 of the total voting power to succeed
- Requires $\frac{2}{3}$ of the total voting power to succeed
- Expect every vote to carry a memo in the form of a `Signature` over some bytes provided in the proposal

`PGFProposal` is a specific proposal to propose transfers for _Public Goods Funding_:

- Can only be submitted by PGF stewards
- Allows both validators and delegators to vote
- Passes by default unless $\frac{1}{3}$ of the total voting power votes on the proposal, AND out of the votes, at least $\frac{1}{2}$ are `Nay`
- Expect every vote to carry a memo in the form of `Set<(Address, BudgetCap)>`


### GovernanceAddress VP

Expand Down Expand Up @@ -318,6 +328,6 @@ The proposalHash is produced over the concatenation of: `content`, `author`, `vo
Same mechanism as [on chain](#tally) tally but instead of reading the data from storage it will require a list of serialized json votes.

## Interfaces

You should be able to interact with governance through the following interfaces:
- Ledger CLI
- Wallet
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"becoming-a-steward" : "Becoming a steward",
"electing" : "Electing the stewards",
"funding" : "Mechanism for funding",
"incentives" : "Steward incentives",
"storage" : "Storage"
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,40 @@ would inherently introduce a new category into social consensus, should the prop
Nominating oneself as a PGF steward may be done at any time.


## Initiating the StewardProposal

Before a new PGF steward can either be elected or removed, a governance proposal that specifies this objective must pass. The voting on this proposal is handled by the governance proposal type `StewardProposal`, which is a custom proposal type.


The struct of `StewardProposal` is constructed as follows, and is explained in more detail in the [governance specs](../base-ledger/governance.md)

```rust
struct StewardProposal{
id: u64
content: Vec<u8>,
author: Address,
r#type: PGFSteward,
votingStartEpoch: Epoch,
votingEndEpoch: Epoch,
graceEpoch: Epoch,
}
```

The proposal may specify:
- Up to 1 account that will be added as a steward
- Up to any number of accounts that will be removed as stewards

Before the proposal is submitted, the protocol will verify that ***if*** the proposal proposes a new steward, ***then*** the author of the proposal is the same
as the account that is being proposed as a steward. This is to prevent a malicious actor from proposing a steward that is not themselves.

If the proposal specificies any set of stewards to be removed, the protocol will verify that the author of the proposal is a current steward, only AFTER the proposal has passed.
If a proposal is passed that removes an account, and that account is not in the set of current stewards, the proposal will still execute, but no action will be taken with respect to that account.

In order for a new PGF steward to be elected (or removed), $\frac{2}{3}$ of validating power must vote on the `StewardProposal` and more than half of the votes must be in favor.
If more than half of the votes are against the proposal, the steward set is kept the same, and the proposer of the proposal loses their escrowed funds.

See the example under [electing a steward](./electing.mdx#example) for more detail, as it may serve as the best medium for explaining the mechanism.

## Losing stewardship status

There are 3 ways that a Steward may be removed from the steward set:
Expand All @@ -37,28 +71,4 @@ used to elect the steward in the first place!
In the same way that a steward can be voted in by Namada governance through a custom proposal, the equal and opposite force exists.
Hence, any governance member (validator or delegate), is able to initiate a vote (for the relevant cost) in order to remove an arbitrary
number of current PGF stewards. If this proposal passes, it signals that the Steward(s) has/have not fulfilled their duty to the public,
which the stewards are meant to serve (hence the name).

## Initiating the vote

Before a new PGF steward can either be elected or removed, a governance proposal that specifies this objective must pass. The voting on this proposal is handled by the governance proposal type `StewardProposal`, which is a custom proposal type.


The struct of `StewardProposal` is constructed as follows, and is explained in more detail in the [governance specs](../base-ledger/governance.md)

```rust
struct StewardProposal{
id: u64
content: Vec<u8>,
author: Address,
r#type: PGFSteward,
votingStartEpoch: Epoch,
votingEndEpoch: Epoch,
graceEpoch: Epoch,
}
```

In order for a new PGF steward to be elected (or removed), $\frac{2}{3}$ of validating power must vote on the `StewardProposal` and more than half of the votes must be in favor. If more than half of the votes are against the proposal, the steward set is kept the same, and the proposer of the proposal loses their escrowed funds.


See the example below for more detail, as it may serve as the best medium for explaining the mechanism.
which the stewards are meant to serve (hence the name).
11 changes: 6 additions & 5 deletions packages/specs/pages/economics/public-goods-funding/electing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Callout } from 'nextra-theme-docs'

## Voting for the stewards

After the `StewardProposal` has been submitted, and once the steward's address has been constructed and broadcasted, the steward address can be voted on by governance participants. All voting must occur between `votingStartEpoch` and `votingEndEpoch`.
After the `StewardProposal` has been submitted, the steward address can be voted on by governance participants. All voting must occur between `votingStartEpoch` and `votingEndEpoch`.


The vote for a new steward nomination will be constructed as follows:
The vote for a steward-set change will be constructed as follows:


Each participant submits a vote through governance:
Expand All @@ -20,15 +20,16 @@ struct OnChainVote {
```

Where the proposalVote is simply an enum dictating whether the voter voted `Yay` or `Nay` to the proposed candidate change.
The `id` will correspond to the `id` of the `StewardProposal` that is being voted on.


#### Dealing with ties
In the rare occurance of a tie, the steward retains membership by default.
In the rare occurance of a tie, the `StewardProposal` is rejected, i.e the current steward-set remains the same.


## Electing stewards

Once the decision has been made on whether to elect (or remove) the intended steward, the established address corresponding to the multisig is added to (removed from) the `PGF` internal address.
Once the decision has been made on whether to elect (or remove) the intended steward/s, the established address/es corresponding to the multisig/s is/are added to (removed from) the `PGF` internal address.

### Example

Expand All @@ -46,7 +47,7 @@ The current PGF stewards are Dave and Elsa.
struct StewardProposal{
id: 2
content: Vec<32,54,01,24,13,37>, // (Just the byte representation of the content (description) of the proposal)
author: 0xCharlie,
author: 0xBobCharlieMultisig,
r#type: StewardProposal,
votingStartEpoch: Epoch(45),
votingEndEpoch: Epoch(54),
Expand Down
89 changes: 59 additions & 30 deletions packages/specs/pages/economics/public-goods-funding/funding.mdx
Original file line number Diff line number Diff line change
@@ -1,53 +1,82 @@
import { Callout } from 'nextra-theme-docs'

# Mechanism
# Mechanism of funding

Once elected and instantiated, PGF stewards will then unilaterally be able to sign transactions that propose either RPGF or CPGF funding. The PGF stewards as a whole will have an "allowance" to spend up to the `PGF` internal address's balance.
Once elected and instantiated, PGF stewards will then unilaterally be able to sign transactions that propose either RPGF or CPGF funding. The PGF funding proposals in joint may spend up to the `PGF` internal address's balance.
There is also the ability for non-stewards to propose funding, but the voting conditions are different.

## Proposing Funding
In order to propose funding, any steward will be able to propose a PGFProposal through governance. Only stewards will be valid authors of these proposals. There will be a minimum voting period set specifically for these types of proposals and can be changed by Governance.
## Proposing funding as a PGF steward
In order to propose funding, any steward will be able to propose a `StewardFundingProposal` through governance, which is a custom proposal.
Only stewards will be valid authors of these proposals. There will be a minimum voting period set specifically for these types of proposals and can be changed by Governance.

This governance proposal will be such that it **passes** by default **unless** the following conditions are met:
This governance proposal will be such that it **passes** by default **unless** the proposal is ***vetoed***.

Conditions to veto a PGF proposal:
##### Conditions to veto a `StewardFundingProposal`:
1. Out of the votes that voted for the proposal, more than $50\%$ voted `Nay` on the proposal
2. At least $\frac{1}{3}$ of voting power voted on the proposal.
- Further, if at least $\frac{2}{3}$ of voting power voted `Nay` on the proposal, and the proposal was rejected, the Steward is removed from the set of stewards.

### Structuring the proposal

The PGF stewards should be able to propose both retroactive and continuous public funding transactions. Retroactive public funding transactions are straightforward and implement no additional logic to a normal transfer.

However, for continuous PGF (cPGF), the stewards should be able to submit a one time transaction which indicates the recipient addresses that should be eligble for receiveing cPGF.

The following data is attached to the PGF transaction and will allow the stewards to represent the projects they wish to be continously funded. Each tuple represent the address of the recipient and the respective amount of NAM that the recipient will receive every epoch.
#### Retroactive PGF (RPGF)
The PGF stewards should be able to propose both retroactive and continuous public funding transactions.
Retroactive public goods funding (RPGF) transactions are straightforward and implement no additional logic to a normal transfer.
The following data is attached to the PGF transaction and will allow the stewards to represent the projects they wish to be funded retroactively.
Each tuple represent the address of the recipient and the respective amount of NAM that the recipient will receive.

```rust
struct cPgfRecipients {
struct RPgfRecipients {
recipients: HashSet<(Address, u64)>
}
```
The mechanism for these transfers will be implemented in `finalize-block.rs`, which will send the addresses their respective amounts each end-of-epoch.
Further, the following transactions:
- add (recipient, amount) to cPgfRecipients (inserts the pair into the hashset above)
- remove recipient from cPgfRecipients (removes the address and corresponding amount pair from the hashset above)
should be added in order to ease the management of cPGF recipients.

```rust
impl addRecipient for cPgfRecipients
#### Continuous PGF (CPGF)
However, for continuous public goods funding (CPGF), the stewards will need to propose ***changes*** to the current set of CPGF recipients and amounts they receive.
We define the **set** of tuples representing the (address of the CPGF recipient, amount of NAM received per epoch) as the `CPgfSet`.
We refer to the individual tuple as a `CPgfEntry`.

impl remRecipient for cPgfRecipients
In this manner, any steward can propose a vector of ***deltas*** to the current `CPgfEntry`s in the `CPgfSet`.
These deltas will be attached to the `StewardFundingProposal` as follows:

```rust
struct CPgfDeltas {
deltas: Vec<(Address, i64)>
}
```

## PGF stewards incentives
<Callout type="info">
Note that the amount of NAM received per epoch is represented as an `i64`. This means all deltas must be integers.
However, the amount of NAM received per epoch is represented as a `u64` in the `CPgfEntry`, which means that large negative deltas act as a removal of the recipient from the set.
</Callout>

##### Applying deltas to the `CPgfSet`
The `CPgfDeltas` will be used to update the `CPgfSet` as follows:

- If the address is not in the `CPgfSet`, then the address is added to the `CPgfSet` with the corresponding amount.
- If the address is in the `CPgfSet`, then the amount is updated by adding the delta to the current amount.
- If the delta is negative and the current amount is less than (or equal to) the absolute value of the delta, then the address is removed from the `CPgfSet`.

##### Mechanism of CPGF
The mechanism for these transfers will be implemented in `finalize-block.rs`, which will send the addresses their respective amounts each end-of-epoch.

###### Edgecase: Total amount of NAM sent to `CPgfSet` is greater than the total amount of NAM in the PGF internal address
Because the amount in each `CPgfEntry` is not verified, and the absolute value of the PGF internal addresses is unpredictable, it may occur that the total amount of NAM sent to the `CPgfSet` in one epoch is greater than the total amount of NAM in the PGF internal address.
In this case, the PGF internal address will be set to zero, and the `CPgfSet` will be receive funding accordingly:

The total sum of amounts in the `CPgfSet` will be calculated, and the the amount of NAM transferred to a single `CPgfEntry` will be proportional to the amount of NAM in the `CPgfEntry` relative to the total sum of amounts in the `CPgfSet`.
More accurately, it will be calculated as follows:

$$T:= \sum_{\text{Entry} \in \text{CPgfSet}} {\text{Entry.amount}}$$

$$\textit{Transfer to entry} \leftarrow \text{Entry.amount} \cdot \frac{\text{PGFInternalAddress.balance}}{T}$$


Being a PGF steward is (should be) hard work. Stewards must invest their time in crafting proposals, being in touch with the opinions of the Namada community, and taking the risks associated with being voted out.
In order to incentivise this effort, Namada allocates a set amount of NAM inflation that is directed towards the stewards.
## Proposing funding as a non-PGF steward

This inflation is allocated towards the PGF internal address, in which each steward account has control over their respective share of the funds.
The inflation is "streamed" to the PGF internal address, in an identical manner to how the cPGF is streamed to the recipients (i.e end of each epoch).
The Steward account can then unilaterally (within the rules of a multisig transaction) either:
- Set up a "stream of income" to another account (e.g a personal account)
- Transfer collected funds in a lump sum transaction
There is also the possibility to propose funding as a non-PGF steward. This is done by submitting the custom governance proposal `FundingProposal` through governance.
The structure of the proposal is identical to the `StewardFundingProposal` except that the author of the proposal is not required to be a PGF steward, and the voting conditions differ.
The proposal will be such that it **is rejected** by default **unless** the following conditions are met:
- $\frac{2}{3}$ of validating power must vote on the `FundingProposal`
- More than half of the votes must be in favor of the `FundingProposal`

The parameter of inflation income is set by governance and is included in genesis by default.
That allocation is then allocated to each steward (more stewards = more total funding).
Note that these are the same voting conditions as the `StewardProposal`
11 changes: 11 additions & 0 deletions packages/specs/pages/economics/public-goods-funding/incentives.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# PGF stewards incentives

Being a PGF steward is (should be) hard work. Stewards must invest their time in crafting proposals, being in touch with the opinions of the Namada community, and taking the risks associated with being voted out.
In order to incentivise this effort, Namada allocates a set amount of NAM inflation that is directed towards the stewards.

By default, this inflation is directed (directly) to each PGF steward account. The steward can then decide what to do with any collected funds.
The Steward account can also unilaterally (within the rules of a multisig transaction) set up a stream of income to a separate set of accounts (e.g a set of personal accounts between the signers behind the steward account).
The inflation is then credited directly to these set of accounts.

The parameter of inflation income is set by governance and is included in genesis by default.
That allocation is allocated to each steward (more stewards = more total funding).
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Stewards in storage

{/* TODO: This needs to be updated */}

## Addresses
Governance adds 1 internal address:

Expand All @@ -11,9 +13,9 @@ The stewards should be able to propose the burning of funds, but this hopefully

### VP checks

The VP must check that the steward's spending does not exceed the balance of the VP (in aggregate).
The VP must check that any spending in the form of `FundingProposals` or `StewardFundingProposal`s does not exceed the balance of the VP (in aggregate).

The VP must also check that any spending is only done by the active PGF stewards.
The VP must also check that any `StewardFundingProposal` spending is only done by the active PGF stewards.

## Storage

Expand All @@ -22,6 +24,7 @@ The VP must also check that any spending is only done by the active PGF stewards
Each recipient will be listed under this storage space (for cPGF)
- `/PGFAddress/cPGF_recipients/Address = Amount`
- `/PGFAddress/active_stewards/address = Address`

### Struct

```rust
Expand Down

0 comments on commit 6e0b9d1

Please sign in to comment.