Skip to content

Commit

Permalink
feat: add global_inflation_per_claim param to tokenomics module (#951)
Browse files Browse the repository at this point in the history
## Summary

Add `global_inflation_per_claim` param to the tokenomics module.

## Issue

- `TODO_BETA`

## Type of change

Select one or more from the following:

- [x] New feature, functionality or library
- [ ] Consensus breaking; add the `consensus-breaking` label if so. See
#791 for details
- [ ] Bug fix
- [ ] Code health or cleanup
- [ ] Documentation
- [ ] Other (specify)

## Testing

- [ ] **Documentation**: `make docusaurus_start`; only needed if you
make doc changes
- [x] **Unit Tests**: `make go_develop_and_test`
- [ ] **LocalNet E2E Tests**: `make test_e2e`
- [x] **DevNet E2E Tests**: Add the `devnet-test-e2e` label to the PR.

## Sanity Checklist

- [x] I have tested my changes using the available tooling
- [ ] I have commented my code
- [x] I have performed a self-review of my own code; both comments &
source code
- [ ] I create and reference any new tickets, if applicable
- [ ] I have left TODOs throughout the codebase, if applicable

---------

Co-authored-by: red-0ne <[email protected]>
  • Loading branch information
bryanchriswhite and red-0ne authored Dec 2, 2024
1 parent 2211d41 commit 88c5321
Show file tree
Hide file tree
Showing 19 changed files with 581 additions and 166 deletions.
136 changes: 97 additions & 39 deletions api/poktroll/tokenomics/params.pulsar.go

Large diffs are not rendered by default.

142 changes: 109 additions & 33 deletions api/poktroll/tokenomics/tx.pulsar.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ genesis:
# This is the address that will receive the dao/foundation rewards during claim settlement (global mint TLM).
# TODO_MAINNET(@olshansk): Consolidate the usage of DAO/PNF throughout the configs & codebase.
dao_reward_address: "pokt1eeeksh2tvkh7wzmfrljnhw4wrhs55lcuvmekkw"
global_inflation_per_claim: 0.1
shared:
params:
num_blocks_per_session: 10
Expand Down
8 changes: 8 additions & 0 deletions makefiles/params.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ params_update_tokenomics_all: ## Update the tokenomics module params
params_update_tokenomics_mint_allocation_percentages: ## Update the tokenomics module mint_allocation_percentages param
poktrolld tx authz exec ./tools/scripts/params/tokenomics_mint_allocation_percentages.json $(PARAM_FLAGS)

.PHONY: params_update_tokenomics_dao_reward_address
params_update_tokenomics_dao_reward_address: ## Update the tokenomics module dao_reward_address param
poktrolld tx authz exec ./tools/scripts/params/tokenomics_dao_reward_address.json $(PARAM_FLAGS)

.PHONY: params_update_tokenomics_global_inflation_per_claim
params_update_tokenomics_global_inflation_per_claim: ## Update the tokenomics module global_inflation_per_claim param
poktrolld tx authz exec ./tools/scripts/params/tokenomics_global_inflation_per_claim.json $(PARAM_FLAGS)

### Service Module Params ###
.PHONY: params_get_service
params_get_service: ## Get the service module params
Expand Down
3 changes: 3 additions & 0 deletions proto/poktroll/tokenomics/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ message Params {
// minted tokens are at the end of claim settlement.
string dao_reward_address = 6 [(cosmos_proto.scalar) = "cosmos.AddressString", (gogoproto.jsontag) = "dao_reward_address", (gogoproto.moretags) = "yaml:\"dao_reward_address\""]; // Bech32 cosmos address

// global_inflation_per_claim is the percentage of a claim's claimable uPOKT amount which will be minted on settlement.
double global_inflation_per_claim = 7 [(gogoproto.jsontag) = "global_inflation_per_claim", (gogoproto.moretags) = "yaml:\"global_inflation_per_claim\""];

// IMPORTANT: Make sure to update all related files if you're modifying or adding a new parameter.
// Try the following grep to find all related places: `grep -r compute_units_to_tokens_multiplier`
// TODO_IMPROVE: Look into an opportunity to use an enum to avoid using strings throughout the codebase.
Expand Down
1 change: 1 addition & 0 deletions proto/poktroll/tokenomics/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ message MsgUpdateParam {
oneof as_type {
MintAllocationPercentages as_mint_allocation_percentages = 3 [(gogoproto.jsontag) = "as_mint_allocation_percentages", (gogoproto.moretags) = "yaml:\"as_mint_allocation_percentages\""];
string as_string = 4 [(gogoproto.jsontag) = "as_string"];
double as_float = 5 [(gogoproto.jsontag) = "as_float"];
}
}

Expand Down
2 changes: 2 additions & 0 deletions testutil/integration/suites/param_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,12 @@ var (
ValidParams: tokenomicstypes.Params{
MintAllocationPercentages: tokenomicstypes.DefaultMintAllocationPercentages,
DaoRewardAddress: sample.AccAddress(),
GlobalInflationPerClaim: 0.666,
},
ParamTypes: map[ParamType]any{
ParamTypeMintAllocationPercentages: tokenomicstypes.MsgUpdateParam_AsMintAllocationPercentages{},
ParamTypeString: tokenomicstypes.MsgUpdateParam_AsString{},
ParamTypeFloat64: tokenomicstypes.MsgUpdateParam_AsFloat{},
},
DefaultParams: tokenomicstypes.DefaultParams(),
NewParamClientFn: tokenomicstypes.NewQueryClient,
Expand Down
4 changes: 3 additions & 1 deletion tools/scripts/params/tokenomics_all.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"supplier": 0.7,
"source_owner": 0.15,
"application": 0.0
}
},
"dao_reward_address": "pokt1eeeksh2tvkh7wzmfrljnhw4wrhs55lcuvmekkw",
"global_inflation_per_claim": 0.1
}
}
]
Expand Down
12 changes: 12 additions & 0 deletions tools/scripts/params/tokenomics_dao_reward_address.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"body": {
"messages": [
{
"@type": "/poktroll.tokenomics.MsgUpdateParam",
"authority": "pokt10d07y265gmmuvt4z0w9aw880jnsr700j8yv32t",
"name": "dao_reward_address",
"as_string": "pokt1eeeksh2tvkh7wzmfrljnhw4wrhs55lcuvmekkw"
}
]
}
}
12 changes: 12 additions & 0 deletions tools/scripts/params/tokenomics_global_inflation_per_claim.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"body": {
"messages": [
{
"@type": "/poktroll.tokenomics.MsgUpdateParam",
"authority": "pokt10d07y265gmmuvt4z0w9aw880jnsr700j8yv32t",
"name": "global_inflation_per_claim",
"as_float": 0.1
}
]
}
}
4 changes: 4 additions & 0 deletions x/tokenomics/keeper/msg_server_update_param.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package keeper

//
import (
"context"
"fmt"
Expand Down Expand Up @@ -44,6 +45,9 @@ func (k msgServer) UpdateParam(
case tokenomicstypes.ParamDaoRewardAddress:
logger = logger.With("param_value", msg.GetAsString())
params.DaoRewardAddress = msg.GetAsString()
case tokenomicstypes.ParamGlobalInflationPerClaim:
logger = logger.With("param_value", msg.GetAsFloat())
params.GlobalInflationPerClaim = msg.GetAsFloat()
default:
return nil, status.Error(
codes.InvalidArgument,
Expand Down
78 changes: 64 additions & 14 deletions x/tokenomics/keeper/msg_server_update_param_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,42 @@ import (
tokenomicstypes "github.com/pokt-network/poktroll/x/tokenomics/types"
)

func TestMsgUpdateParam_UpdateMintAllocationDaoOnly(t *testing.T) {
t.Skip("since the mint allocation percentages must sum to 1, it is not possible to modify only one of them")
}
func TestMsgUpdateParam_UpdateMintAllocationPercentagesOnly(t *testing.T) {
expectedMintAllocationPercentages := tokenomicstypes.MintAllocationPercentages{
Dao: 0.1,
Proposer: 0.2,
Supplier: 0.3,
SourceOwner: 0.4,
Application: 0.0,
}

func TestMsgUpdateParam_UpdateMintAllocationProposerOnly(t *testing.T) {
t.Skip("since the mint allocation percentages must sum to 1, it is not possible to modify only one of them")
}
// Set the parameters to their default values
k, msgSrv, ctx := setupMsgServer(t)
defaultParams := tokenomicstypes.DefaultParams()
require.NoError(t, k.SetParams(ctx, defaultParams))

func TestMsgUpdateParam_UpdateMintAllocationSupplierOnly(t *testing.T) {
t.Skip("since the mint allocation percentages must sum to 1, it is not possible to modify only one of them")
}
// Ensure the default values are different from the new values we want to set
require.NotEqual(t, expectedMintAllocationPercentages, defaultParams.MintAllocationPercentages)

func TestMsgUpdateParam_UpdateMintAllocationSourceOwnerOnly(t *testing.T) {
t.Skip("since the mint allocation percentages must sum to 1, it is not possible to modify only one of them")
}
// Update the mint allocation percentages.
updateParamMsg := &tokenomicstypes.MsgUpdateParam{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Name: tokenomicstypes.ParamMintAllocationPercentages,
AsType: &tokenomicstypes.MsgUpdateParam_AsMintAllocationPercentages{AsMintAllocationPercentages: &expectedMintAllocationPercentages},
}
res, err := msgSrv.UpdateParam(ctx, updateParamMsg)
require.NoError(t, err)

// Assert that the response contains the expected mint allocation percentages.
require.NotEqual(t, defaultParams.MintAllocationPercentages, res.Params.MintAllocationPercentages)
require.Equal(t, expectedMintAllocationPercentages, res.Params.MintAllocationPercentages)

func TestMsgUpdateParam_UpdateMintAllocationApplicationOnly(t *testing.T) {
t.Skip("since the mint allocation percentages must sum to 1, it is not possible to modify only one of them")
// Assert that the on-chain mint allocation percentages is updated.
params := k.GetParams(ctx)
require.Equal(t, expectedMintAllocationPercentages, params.MintAllocationPercentages)

// Ensure the other parameters are unchanged
testkeeper.AssertDefaultParamsEqualExceptFields(t, &defaultParams, res.Params, string(tokenomicstypes.KeyMintAllocationPercentages))
}

func TestMsgUpdateParam_UpdateDaoRewardAddressOnly(t *testing.T) {
Expand Down Expand Up @@ -63,3 +81,35 @@ func TestMsgUpdateParam_UpdateDaoRewardAddressOnly(t *testing.T) {
// Ensure the other parameters are unchanged
testkeeper.AssertDefaultParamsEqualExceptFields(t, &defaultParams, res.Params, string(tokenomicstypes.KeyDaoRewardAddress))
}

func TestMsgUpdateParam_UpdateGlobalInflationPerClaimOnly(t *testing.T) {
expectedGlobalInflationPerClaim := 0.666

// Set the parameters to their default values
k, msgSrv, ctx := setupMsgServer(t)
defaultParams := tokenomicstypes.DefaultParams()
require.NoError(t, k.SetParams(ctx, defaultParams))

// Ensure the default values are different from the new values we want to set
require.NotEqual(t, expectedGlobalInflationPerClaim, defaultParams.GlobalInflationPerClaim)

// Update the dao reward address.
updateParamMsg := &tokenomicstypes.MsgUpdateParam{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Name: tokenomicstypes.ParamGlobalInflationPerClaim,
AsType: &tokenomicstypes.MsgUpdateParam_AsFloat{AsFloat: expectedGlobalInflationPerClaim},
}
res, err := msgSrv.UpdateParam(ctx, updateParamMsg)
require.NoError(t, err)

// Assert that the response contains the expected dao reward address.
require.NotEqual(t, defaultParams.GlobalInflationPerClaim, res.Params.GlobalInflationPerClaim)
require.Equal(t, expectedGlobalInflationPerClaim, res.Params.GlobalInflationPerClaim)

// Assert that the on-chain dao reward address is updated.
params := k.GetParams(ctx)
require.Equal(t, expectedGlobalInflationPerClaim, params.GlobalInflationPerClaim)

// Ensure the other parameters are unchanged
testkeeper.AssertDefaultParamsEqualExceptFields(t, &defaultParams, res.Params, string(tokenomicstypes.KeyGlobalInflationPerClaim))
}
27 changes: 27 additions & 0 deletions x/tokenomics/keeper/msg_update_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ func TestMsgUpdateParams(t *testing.T) {
shouldError: true,
expectedErrMsg: "empty address string is not allowed",
},
{
desc: "invalid: negative global inflation per claim",

req: &tokenomicstypes.MsgUpdateParams{
Authority: tokenomicsKeeper.GetAuthority(),
Params: tokenomicstypes.Params{
// GlobalInflationPerClaim MUST be positive.
GlobalInflationPerClaim: -0.1,

// DaoRewardAddress MUST NOT be empty string
// when MintAllocationDao is greater than 0.
DaoRewardAddress: sample.AccAddress(),

// MintAllocationXXX params MUST sum to 1.
MintAllocationPercentages: tokenomicstypes.MintAllocationPercentages{
Dao: 0,
Proposer: 0.1,
Supplier: 0.1,
SourceOwner: 0.1,
Application: 0.7,
},
},
},

shouldError: true,
expectedErrMsg: "GlobalInflationPerClaim must be greater than or equal to 0:",
},
{
desc: "valid: successful param update",

Expand Down
36 changes: 36 additions & 0 deletions x/tokenomics/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,39 @@ func TestParams_ValidateDaoRewardAddress(t *testing.T) {
})
}
}

func TestParams_ValidateGlobalInflationPerClaim(t *testing.T) {
tests := []struct {
desc string
globalInflationPerClaim any
expectedErr error
}{
{
desc: "invalid type",
globalInflationPerClaim: float32(0.111),
expectedErr: tokenomicstypes.ErrTokenomicsParamInvalid.Wrap("invalid parameter type: float32"),
},
{
desc: "less than zero",
globalInflationPerClaim: float64(-0.1),
expectedErr: tokenomicstypes.ErrTokenomicsParamInvalid.Wrapf(
"GlobalInflationPerClaim must be greater than or equal to 0: %f", float64(-0.1),
),
},
{
desc: "valid GlobalInflationPerClaim",
globalInflationPerClaim: tokenomicstypes.DefaultGlobalInflationPerClaim,
},
}

for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
err := tokenomicstypes.ValidateGlobalInflationPerClaim(test.globalInflationPerClaim)
if test.expectedErr != nil {
require.ErrorContains(t, err, test.expectedErr.Error())
} else {
require.NoError(t, err)
}
})
}
}
19 changes: 9 additions & 10 deletions x/tokenomics/types/message_update_param.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func NewMsgUpdateParam(authority string, name string, asTypeAny any) (*MsgUpdate
asTypeIface = &MsgUpdateParam_AsMintAllocationPercentages{AsMintAllocationPercentages: &asType}
case string:
asTypeIface = &MsgUpdateParam_AsString{AsString: asType}
case float64:
asTypeIface = &MsgUpdateParam_AsFloat{AsFloat: asType}
default:
return nil, fmt.Errorf("unexpected param value type: %T", asTypeAny)
}
Expand Down Expand Up @@ -44,28 +46,25 @@ func (msg *MsgUpdateParam) ValidateBasic() error {
// Parameter name must be supported by this module.
switch msg.Name {
case ParamMintAllocationPercentages:
if err := msg.paramTypeIsMintAllocationPercentages(); err != nil {
if err := genericParamTypeIs[*MsgUpdateParam_AsMintAllocationPercentages](msg); err != nil {
return err
}
return ValidateMintAllocationPercentages(*msg.GetAsMintAllocationPercentages())
case ParamDaoRewardAddress:
if err := msg.paramTypeIsString(); err != nil {
if err := genericParamTypeIs[*MsgUpdateParam_AsString](msg); err != nil {
return err
}
return ValidateDaoRewardAddress(msg.GetAsString())
case ParamGlobalInflationPerClaim:
if err := genericParamTypeIs[*MsgUpdateParam_AsFloat](msg); err != nil {
return err
}
return ValidateGlobalInflationPerClaim(msg.GetAsFloat())
default:
return ErrTokenomicsParamNameInvalid.Wrapf("unsupported param %q", msg.Name)
}
}

func (msg *MsgUpdateParam) paramTypeIsMintAllocationPercentages() error {
return genericParamTypeIs[*MsgUpdateParam_AsMintAllocationPercentages](msg)
}

func (msg *MsgUpdateParam) paramTypeIsString() error {
return genericParamTypeIs[*MsgUpdateParam_AsString](msg)
}

// genericParamTypeIs checks if the parameter type is T, returning an error if not.
func genericParamTypeIs[T any](msg *MsgUpdateParam) error {
if _, ok := msg.AsType.(T); !ok {
Expand Down
11 changes: 11 additions & 0 deletions x/tokenomics/types/message_update_param_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ func TestMsgUpdateParam_ValidateBasic(t *testing.T) {
},
expectedErr: ErrTokenomicsParamInvalid,
},
{
name: "invalid: global inflation per claim less than 0",
msg: MsgUpdateParam{
Authority: sample.AccAddress(),
Name: ParamGlobalInflationPerClaim,
AsType: &MsgUpdateParam_AsFloat{
AsFloat: -0.1,
},
},
expectedErr: ErrTokenomicsParamInvalid,
},
{
name: "valid: correct address, param name, and type",
msg: MsgUpdateParam{
Expand Down
Loading

0 comments on commit 88c5321

Please sign in to comment.