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 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 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 proposal is vetoed.

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

Structuring the proposal

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.

struct RPgfRecipients {
    recipients: HashSet<(Address, u64)>
}

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.

In this manner, any steward can propose a vector of deltas to the current CPgfEntrys in the CPgfSet. These deltas will be attached to the StewardFundingProposal as follows:

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

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.

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:=EntryCPgfSetEntry.amountT:= \sum_{\text{Entry} \in \text{CPgfSet}} {\text{Entry.amount}}

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

Applying funding

For blocks of which both RPGF and CPGF funding is to be applied, RPGF is applied first. If there is not enough funds to pay an RPGF proposal, it is rejected. For RPGF proposals that have the same graceEpoch, the proposal with the lowest proposalId is applied first.

Proposing funding as a non-PGF steward

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:

  • 23\frac{2}{3} of voting-power must vote on the FundingProposal
  • More than half of the votes must be in favor of the FundingProposal

Note that these are the same voting conditions as the StewardProposal