Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Stream funds from community pool #17267

Closed
hxrts opened this issue Aug 2, 2023 · 10 comments · Fixed by #18103
Closed

[Feature]: Stream funds from community pool #17267

hxrts opened this issue Aug 2, 2023 · 10 comments · Fixed by #18103
Assignees

Comments

@hxrts
Copy link
Contributor

hxrts commented Aug 2, 2023

Summary

Allow governance to set a parameter that will periodically move funds from the community pool into one or more specified accounts.

Problem Definition

Chains may want to use community pool funds to pay for ongoing commercial services or public goods. Examples include relayer service contracts or core software development. As an alternative to one-off community spend proposals chains should be able to create a continuous funding stream (which may be changed or terminated at any time).

Proposal

Params

store a budget map with the following structure:

budget := map[sdk.AccAddress]Dec{
    cosmos1234..., 0.5, // community pool
    cosmos1235..., 0.25 // grants dao
    cosmos1236..., 0.25 // dev fund
}

This map can be modified with a custom message voted on by gov. Upon proposal submission the following checks are performed to ensure the message is well-formed:
1. All account addresses exist
2. The sum of all stream amounts equals exactly 1

The budget is also stored as an epoch_balance tracking object, the use of which is described below

epoch_balance := map[Denom]Amount{
    ATOM, 10000,
    NTRN, 10,
    USDC, 100
}

EndBlocker

At epoch n a function is called that performs the following:

  • Reads the current balance of all coins in the community pool
  • Subtracts each epoch_balance from epoch n-1 from the corresponding values in epoch n
  • If the balance dividend is positive (coins were added), then this result is multiplied by each value in the budget map and the amount is transferred from the community pool to the corresponding address
  • epoch_balance from epoch n replaces the previous object, persisting for the next epoch

note: this is a simple unobtrusive implementation, however I'm open to various alternatives

@keefertaylor said he'd be happy to take this

@tac0turtle
Copy link
Member

I think there are two parts to this work, first community pool being pulled out of distribution, then either allowing native streaming from that module or allowing streaming plugins to allow people to plugin custom streaming logic from vms or native go code.

@hxrts
Copy link
Contributor Author

hxrts commented Sep 5, 2023

The thing is I'd really like this natively in the SDK so all chains have the ability to do things like make a stream to pay for IBC relaying for instance.

@alexanderbez
Copy link
Contributor

alexanderbez commented Sep 5, 2023

My initial stab at this -- ref: #12831

@likhita-809
Copy link
Contributor

ref: #10811

@hxrts
Copy link
Contributor Author

hxrts commented Oct 5, 2023

With the new module design, where distribution is distinct from the community pool, the above architecture should be modified slightly.

I suggest creating a middleware which has the same functionality. It should take a map of addresses and corresponding percentage weights that sum to 100%.

The middleware can be placed between the distribution module and the community pool module. This allows us to direct the flow of funds coming from distribution, either to the community pool or some number of other addresses. The community pool address is just one of the addresses in the map. The middleware must validate that the community pool address is present in the map.

A second instance of the middleware can be placed after the community pool. Similar to the previous instantiation, it can redirect funds away from the community pool into any number other addresses. The percentage weights correspond to a percentage of the total funds available in the CP at that height. Note that community pool address should still be present in the map and the corresponding percentage represents the percentage of funds that will remain in the CP at that height.

To updating the middleware parameter a user must submit a governance proposal with the following:

  • Reference to the middleware they'd like to configure (i.e., before or after the community pool)
  • Map of addresses and percentages

@tac0turtle
Copy link
Member

this defeats the need for a community pool module imo. Id rather we keep it in the community pool module and simplify the distribution module not make it more complex.

@julienrbrt
Copy link
Member

+1, why can't it be done in a Begin/EndBlocker in the community pool module?
I do not think chains want to stream funds to 10k different addresses per block, so there won't be any performance hit.

@likhita-809
Copy link
Contributor

+1, why can't it be done in a Begin/EndBlocker in the community pool module? I do not think chains want to stream funds to 10k different addresses per block, so there won't be any performance hit.

definitely, that's the track I've been in. But still wandering with some other thoughts. This conversation would really help me sort out my thoughts.

@anilcse
Copy link
Collaborator

anilcse commented Oct 10, 2023

This is a great idea and much needed feature. I have couple of inputs to simplify/extend this further.

Lets have budget type with following details

[
{
    recipient_address: cosmos1....dfkg,
    total_budget: {
         denom: uatom,
         amount: 10000000000
    },
    start_time: 16000000, // in epoch seconds
    remaining_tranches: [
    {
        period: 10000,
        amount: 1000000000
    },
    {
        period: 20000,
        amount: 1000000000
    },
    ...
    ]
},
...
]

This allows users/proposers to put these details in the governance community-spending proposal. We can even use this for distributing USD value instead of just ATOMs by applying price calculation logic when the DENOM is USD.
This follows general vesting periods implementation but endblocker will transfer and clear the tranche when the period is reached.

We can also just have something like:

[
{
    recipient_address: cosmos1....dfkg,
    total_budget: {
         denom: uatom,
         amount: 10000000000
    },
    start_time: 16000000, // in epoch seconds
    remaining_tranches: 10,
    period: 1000, // for every 1000 blocks, or it can be epoch number as well.
},
...
]

I think we can still improve this a bit. Open for feedback/comments

@hxrts
Copy link
Contributor Author

hxrts commented Oct 13, 2023

I like the tranches feature a lot! USD denominations creates a dependency on an external price oracle, which seems out of scope for now. Also think 3rd party services will be better suited for more complex functionality that requires exchange rates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants