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

feat(x/protocolpool): Stream funds from community pool #18103

Merged
merged 90 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
abe5a02
add proto file
likhita-809 Oct 12, 2023
628c4ba
add proto-gen files
likhita-809 Oct 12, 2023
cbb0e8c
update proto file
likhita-809 Oct 12, 2023
7eb9444
run proto-gen
likhita-809 Oct 12, 2023
9fe659e
feat: Stream Funds from protocolpool
likhita-809 Oct 12, 2023
edfc4b8
wip: add more changes
likhita-809 Oct 12, 2023
40a8447
add pool module to EndBlocker order
likhita-809 Oct 12, 2023
26fabfa
fix simulation in protocolpool
likhita-809 Oct 12, 2023
f5aa92d
fix lint and run go mod tidy
likhita-809 Oct 12, 2023
302df33
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 12, 2023
cc2311b
wip: update module.go
likhita-809 Oct 12, 2023
2fa4e0b
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 13, 2023
ed6920d
fix tests
likhita-809 Oct 13, 2023
ceecddd
update proto files
likhita-809 Oct 13, 2023
9770289
address review comments: lazy code
likhita-809 Oct 13, 2023
4ef2446
wip: fix
likhita-809 Oct 13, 2023
8cd795c
fix tests
likhita-809 Oct 13, 2023
5880fdd
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 13, 2023
a9d6f72
wip: address review comments
likhita-809 Oct 13, 2023
c8b78da
run proto-gen & remove since comments
likhita-809 Oct 13, 2023
a02bde8
make authority as signer
likhita-809 Oct 13, 2023
abe1df7
add budget query
likhita-809 Oct 13, 2023
eb841ff
add proto-gen files
likhita-809 Oct 13, 2023
6b0675f
add grpc query implementation
likhita-809 Oct 13, 2023
d57cc00
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 13, 2023
d7235cd
fix nit
likhita-809 Oct 13, 2023
8782ff8
delete unused distrinfo struct
likhita-809 Oct 13, 2023
43b4778
simplify naming
likhita-809 Oct 13, 2023
924ada5
run proto-gen
likhita-809 Oct 13, 2023
d339520
code cleanup
likhita-809 Oct 13, 2023
4309b78
wip: cleanup
likhita-809 Oct 13, 2023
273be81
change proposal prompt name
likhita-809 Oct 13, 2023
d8c686b
fix lint
likhita-809 Oct 13, 2023
4b906dd
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 16, 2023
ed4c3f6
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 16, 2023
7c306d2
add MsgFundDispensationProposal proto msg
likhita-809 Oct 19, 2023
dfcb89c
update proto msg
likhita-809 Oct 19, 2023
81c83e8
Revert "update proto msg"
likhita-809 Oct 24, 2023
599303e
Revert "add MsgFundDispensationProposal proto msg"
likhita-809 Oct 24, 2023
0a8809e
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 24, 2023
0b9d201
address few comments
likhita-809 Oct 26, 2023
e3cc5d5
add proto changes
likhita-809 Oct 26, 2023
a015286
more updates
likhita-809 Oct 26, 2023
19d1cff
cleanup
likhita-809 Oct 26, 2023
1cfd817
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 26, 2023
0ede17a
more proto changes
likhita-809 Oct 26, 2023
7323da3
address few comments
likhita-809 Oct 26, 2023
8eeb1e7
fix claim funds logic
likhita-809 Oct 26, 2023
6faa47c
run proto-gen
likhita-809 Oct 26, 2023
f24bd99
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 26, 2023
df4f3ca
add tests
likhita-809 Oct 30, 2023
54b5b95
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 30, 2023
d5017bb
fix lint and tests
likhita-809 Oct 30, 2023
a74253d
run go mod tidy
likhita-809 Oct 30, 2023
9772449
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 30, 2023
0c75887
update docs
likhita-809 Oct 30, 2023
50bbe5d
more checks
likhita-809 Oct 30, 2023
8bacc42
wip: test
likhita-809 Oct 30, 2023
e67601a
wip
likhita-809 Oct 30, 2023
fc855d9
add proto-gen files
likhita-809 Oct 30, 2023
ed779bc
more changes
likhita-809 Oct 30, 2023
4cffd2b
fix tests
likhita-809 Oct 30, 2023
510848d
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 30, 2023
497a2b4
add double claim testcases
likhita-809 Oct 31, 2023
8ceda3c
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Oct 31, 2023
c0b4a2f
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 1, 2023
638b106
update proto file
likhita-809 Nov 1, 2023
c3702d0
wip: update keeper logic
likhita-809 Nov 1, 2023
01e8006
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 1, 2023
c6daf9e
update proto files
likhita-809 Nov 1, 2023
f3806dc
update keeper logic and tests
likhita-809 Nov 1, 2023
286cc87
update readme
likhita-809 Nov 1, 2023
5ac8237
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 1, 2023
3978f4c
improve errors
likhita-809 Nov 1, 2023
78c1d28
rename last claim time to next claim from
likhita-809 Nov 1, 2023
462fe14
change double claim tc to use 1 month period
likhita-809 Nov 1, 2023
57f4c1f
Merge branch 'likhita/sf-2' of https://github.com/cosmos/cosmos-sdk i…
likhita-809 Nov 1, 2023
1c84c46
refactor keeper code
likhita-809 Nov 1, 2023
d845f26
wip: address julien's comment
likhita-809 Nov 3, 2023
e818975
update proto files
likhita-809 Nov 3, 2023
0b4898c
use concrete time types
likhita-809 Nov 3, 2023
1bc47f7
update grpc query
likhita-809 Nov 3, 2023
12452ea
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 3, 2023
2baea4c
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 6, 2023
ae39a2d
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 6, 2023
bcd5221
address julien's comments
likhita-809 Nov 6, 2023
e90053e
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into likh…
likhita-809 Nov 6, 2023
3a27c0c
update Readme and godoc
likhita-809 Nov 6, 2023
3b11131
update readme
likhita-809 Nov 6, 2023
39a2191
remove pointer update on validateAndUpdateBudgetProposal
likhita-809 Nov 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,232 changes: 2,232 additions & 0 deletions api/cosmos/protocolpool/v1/budget.pulsar.go

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions proto/cosmos/protocolpool/v1/budget.proto
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Since: cosmos-sdk 0.50
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
syntax = "proto3";
package cosmos.protocolpool.v1;

option go_package = "cosmossdk.io/x/protocolpool/types";

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/msg/v1/msg.proto";

// Budget defines budget proposal type.
//
// Since: cosmos-sdk 0.50
message BudgetProposal {
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
option (cosmos.msg.v1.signer) = "recipient_address";
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
string recipient_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
cosmos.base.v1beta1.Coin total_budget = 2;
int64 start_time = 3;
int64 remaining_tranches = 4;
int64 period = 5;
}

// MsgBudgetProposalResponse defines the response to executing a
// MsgBudgetProposal message.
//
// Since: cosmos-sdk 0.50
message MsgBudgetProposalResponse {}

// MsgClaimBudget defines a message for claiming the distributed budget.
//
// Since: cosmos-sdk 0.50
message MsgClaimBudget {
option (cosmos.msg.v1.signer) = "recipient_address";
string recipient_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgClaimBudgetResponse defines the response to executing a
// MsgClaimBudget message.
//
// Since: cosmos-sdk 0.50
message MsgClaimBudgetResponse {
cosmos.base.v1beta1.Coin amount = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
;
}
1 change: 1 addition & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ func NewSimApp(
genutiltypes.ModuleName,
feegrant.ModuleName,
group.ModuleName,
pooltypes.ModuleName,
)

// NOTE: The genutils module must occur after staking so that pools are
Expand Down
1 change: 1 addition & 0 deletions simapp/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ var (
stakingtypes.ModuleName,
feegrant.ModuleName,
group.ModuleName,
pooltypes.ModuleName,
},
OverrideStoreKeys: []*runtimev1alpha1.StoreKeyConfig{
{
Expand Down
1 change: 1 addition & 0 deletions testutil/configurator/configurator.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func defaultConfig() *Config {
"upgrade",
"vesting",
"circuit",
"protocolpool",
},
InitGenesisOrder: []string{
"auth",
Expand Down
4 changes: 4 additions & 0 deletions x/gov/client/cli/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ var suggestedProposalTypes = []proposalType{
Name: "cancel-software-upgrade",
MsgType: "/cosmos.upgrade.v1beta1.MsgCancelUpgrade",
},
{
Name: "set-budget",
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
MsgType: "/cosmos.protocolpool.v1.BudgetProposal",
},
{
Name: proposalOther,
MsgType: "", // user will input the message type
Expand Down
73 changes: 73 additions & 0 deletions x/protocolpool/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package protocolpool

import (
"fmt"

"cosmossdk.io/x/protocolpool/keeper"
"cosmossdk.io/x/protocolpool/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func EndBlocker(ctx sdk.Context, k keeper.Keeper, authKeeper types.AccountKeeper) error {
err := k.BudgetProposal.Walk(ctx, nil, func(key sdk.AccAddress, budget types.BudgetProposal) (stop bool, err error) {
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
// check if the distribution is completed
if budget.RemainingTranches <= 0 {
// Log the end of the budget
k.Logger(ctx).Info(fmt.Sprintf("Budget ended for recipient: %s", key.String()))
return false, nil // Continue iterating
}

currentTime := ctx.BlockTime().Unix()

// Check if the start time is reached
if currentTime < budget.StartTime {
return false, fmt.Errorf("distribution has not started yet")
}

// Calculate the number of blocks elapsed since the start time
blocksElapsed := ctx.BlockHeight() - budget.Period

// Check if its time to distribute funds based on period intervals
if blocksElapsed > 0 && blocksElapsed%budget.Period == 0 {
// Calculate the amount to distribute in each tranche
amountPerTranche := budget.TotalBudget.Amount.QuoRaw(budget.RemainingTranches)
amount := sdk.NewCoin(budget.TotalBudget.Denom, amountPerTranche)

recipient, err := authKeeper.AddressCodec().StringToBytes(budget.RecipientAddress)
if err != nil {
return false, err
}

distributionInfo := types.DistributionInfo{
Address: recipient,
Amount: amount,
}

// store funds in the DistributionInfo until a claim tx
err = k.AppendDistributionInfo(ctx, distributionInfo)
if err != nil {
return false, err
}

// update the budget's remaining tranches
budget.RemainingTranches--

// update the TotalBudget amount
budget.TotalBudget.Amount.Sub(amountPerTranche)

k.Logger(ctx).Info(fmt.Sprintf("Processing budget for recipient: %s. Amount: %s", budget.RecipientAddress, amountPerTranche.String()))

// Save the updated budget in the state
err = k.BudgetProposal.Set(ctx, recipient, budget)
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Error while updating the budget for recipient %s", budget.RecipientAddress))
return false, err
}

}
return false, nil
})

return err
}
2 changes: 1 addition & 1 deletion x/protocolpool/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.21

require (
cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273
cosmossdk.io/collections v0.4.0
cosmossdk.io/core v0.12.0
cosmossdk.io/depinject v1.0.0-alpha.4
cosmossdk.io/errors v1.0.0
Expand All @@ -22,7 +23,6 @@ require (
)

require (
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/math v1.1.3-rc.1 // indirect
cosmossdk.io/store v1.0.0-rc.0 // indirect
cosmossdk.io/x/tx v0.10.0 // indirect
Expand Down
110 changes: 105 additions & 5 deletions x/protocolpool/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package keeper

import (
"context"
"errors"
"fmt"

"cosmossdk.io/collections"
storetypes "cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
Expand All @@ -19,7 +21,14 @@ type Keeper struct {
authKeeper types.AccountKeeper
bankKeeper types.BankKeeper

cdc codec.BinaryCodec

authority string

// State
Schema collections.Schema
BudgetProposal collections.Map[sdk.AccAddress, types.BudgetProposal]
DistrInfo collections.Map[sdk.AccAddress, sdk.Coin]
}
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved

func NewKeeper(cdc codec.BinaryCodec, storeService storetypes.KVStoreService,
Expand All @@ -29,12 +38,25 @@ func NewKeeper(cdc codec.BinaryCodec, storeService storetypes.KVStoreService,
if addr := ak.GetModuleAddress(types.ModuleName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
}
return Keeper{
storeService: storeService,
authKeeper: ak,
bankKeeper: bk,
authority: authority,
sb := collections.NewSchemaBuilder(storeService)

keeper := Keeper{
storeService: storeService,
authKeeper: ak,
bankKeeper: bk,
cdc: cdc,
authority: authority,
BudgetProposal: collections.NewMap(sb, types.BudgetKey, "budget", sdk.AccAddressKey, codec.CollValue[types.BudgetProposal](cdc)),
DistrInfo: collections.NewMap(sb, types.DistrInfoKey, "distribution_info", sdk.AccAddressKey, codec.CollValue[sdk.Coin](cdc)),
}

schema, err := sb.Build()
if err != nil {
panic(err)
}
keeper.Schema = schema

return keeper
}

// GetAuthority returns the x/protocolpool module's authority.
Expand Down Expand Up @@ -67,3 +89,81 @@ func (k Keeper) GetCommunityPool(ctx context.Context) (sdk.Coins, error) {
}
return k.bankKeeper.GetAllBalances(ctx, moduleAccount.GetAddress()), nil
}

func (k Keeper) AppendDistributionInfo(ctx sdk.Context, distributionInfo types.DistributionInfo) error {
amount, err := k.DistrInfo.Get(ctx, distributionInfo.Address)
if err != nil {
if errors.Is(err, collections.ErrNotFound) {
err := k.DistrInfo.Set(ctx, distributionInfo.Address, distributionInfo.Amount)
if err != nil {
return err
}
} else {
return err
}
}
updatedAmount := distributionInfo.Amount.Add(amount)
return k.DistrInfo.Set(ctx, distributionInfo.Address, updatedAmount)
}

func (k Keeper) ClaimFunds(ctx context.Context, recipient sdk.AccAddress) (amount sdk.Coin, err error) {
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
// get claimable funds from distribution info
amount, err = k.getClaimableFunds(ctx, recipient)
if err != nil {
return sdk.Coin{}, err
}

// distribute amount from feepool
err = k.DistributeFromFeePool(ctx, sdk.NewCoins(amount), recipient)
if err != nil {
return sdk.Coin{}, err
}

// remove the recipient from the DistributionInfo
err = k.DistrInfo.Remove(ctx, recipient)
if err != nil {
return sdk.Coin{}, err
}

return amount, nil
}

func (k Keeper) getClaimableFunds(ctx context.Context, recipient sdk.AccAddress) (amount sdk.Coin, err error) {
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
amount, err = k.DistrInfo.Get(ctx, recipient)
if err != nil {
if errors.Is(err, collections.ErrNotFound) {
return sdk.Coin{}, fmt.Errorf("no claimable funds are present for recipient: %s", recipient.String())
}
return sdk.Coin{}, err
}
return amount, nil
}

func (k Keeper) validateBudgetProposal(ctx context.Context, bp types.BudgetProposal) error {
account := k.authKeeper.GetAccount(ctx, sdk.AccAddress(bp.RecipientAddress))
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
if account == nil {
return fmt.Errorf("account not found: %s", bp.RecipientAddress)
}

if bp.TotalBudget.IsZero() {
return fmt.Errorf("total budget cannot be zero")
}

if err := validateAmount(sdk.NewCoins(*bp.TotalBudget)); err != nil {
return err
}

if bp.StartTime <= 0 {
return fmt.Errorf("start time must be a positive value")
}

if bp.RemainingTranches <= 0 {
return fmt.Errorf("remaining tranches must be a positive value")
}

if bp.Period <= 0 {
return fmt.Errorf("period should be a positive value")
}

return nil
}
32 changes: 32 additions & 0 deletions x/protocolpool/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,38 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &MsgServer{Keeper: keeper}
}

func (k MsgServer) MsgClaimBudget(ctx context.Context, msg *types.MsgClaimBudget) (*types.MsgClaimBudgetResponse, error) {
recipient, err := k.Keeper.authKeeper.AddressCodec().StringToBytes(msg.RecipientAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid recipient address: %s", err)
}

amount, err := k.ClaimFunds(ctx, recipient)
if err != nil {
return nil, err
}

return &types.MsgClaimBudgetResponse{Amount: amount}, nil
}

func (k MsgServer) SubmitBudgetProposal(ctx context.Context, msg *types.BudgetProposal) (*types.MsgBudgetProposalResponse, error) {
recipient, err := k.Keeper.authKeeper.AddressCodec().StringToBytes(msg.RecipientAddress)
if err != nil {
return nil, err
}

if err := k.validateBudgetProposal(ctx, *msg); err != nil {
return nil, err
}

// set budget proposal in state
err = k.BudgetProposal.Set(ctx, recipient, *msg)
if err != nil {
return nil, err
}
return &types.MsgBudgetProposalResponse{}, nil
}

func (k MsgServer) FundCommunityPool(ctx context.Context, msg *types.MsgFundCommunityPool) (*types.MsgFundCommunityPoolResponse, error) {
depositor, err := k.authKeeper.AddressCodec().StringToBytes(msg.Depositor)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions x/protocolpool/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
Expand All @@ -29,6 +30,7 @@ var (

_ module.AppModule = AppModule{}
_ module.AppModuleSimulation = AppModule{}
_ appmodule.HasEndBlocker = AppModule{}
)

// AppModuleBasic defines the basic application module used by the pool module.
Expand Down Expand Up @@ -92,6 +94,12 @@ func NewAppModule(cdc codec.Codec, keeper keeper.Keeper,
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }

// EndBlock implements the protocolpool module's EndBlock.
func (am AppModule) EndBlock(ctx context.Context) error {
c := sdk.UnwrapSDKContext(ctx)
return EndBlocker(c, am.keeper, am.accountKeeper)
}

//
// App Wiring Setup
//
Expand Down
Loading
Loading