Skip to content

Commit

Permalink
feat: ADR-008: Fees module (#796)
Browse files Browse the repository at this point in the history
## Description

Closes: #XXXX.

This PR implements the `x/fees` module that allows governance to set minimum fees on messages.

Depends-On: #816
Depends-On: #817

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://docs.cosmos.network/v0.44/building-modules/intro.html)
- [ ] included the necessary unit and integration [tests](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [x] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [x] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [x] reviewed tests and test coverage
- [ ] manually tested (if applicable)
  • Loading branch information
leobragaz authored Apr 13, 2022
1 parent d2982d8 commit c684768
Show file tree
Hide file tree
Showing 50 changed files with 3,339 additions and 84 deletions.
2 changes: 2 additions & 0 deletions .changeset/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ types:
hide: true

modules:
- id: x/fees
description: Fees
- id: x/profiles
description: Profiles
- id: x/subspaces
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type: feat
module: x/fees
pull_request: 796
description: Added the new `x/fees` module
backward_compatible: true
date: 2022-04-08T10:16:28.516096837Z
6 changes: 4 additions & 2 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"x/fees":
- x/fees/**/*
"x/profiles":
- x/profiles/**/*
"x/posts":
- x/posts/**/*
"x/relationships":
- x/relationships/**/*
"x/subspaces":
- x/subspaces/**/*
"x/CLI":
Expand Down
10 changes: 6 additions & 4 deletions app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
channelkeeper "github.com/cosmos/ibc-go/v2/modules/core/04-channel/keeper"
ibcante "github.com/cosmos/ibc-go/v2/modules/core/ante"

feeskeeper "github.com/desmos-labs/desmos/v3/x/fees/keeper"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types"
)
Expand All @@ -17,6 +19,7 @@ type HandlerOptions struct {
ante.HandlerOptions

IBCChannelkeeper channelkeeper.Keeper
FeesKeeper feeskeeper.Keeper
TxCounterStoreKey sdk.StoreKey
WasmConfig wasmTypes.WasmConfig
}
Expand All @@ -37,12 +40,13 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
sigGasConsumer = ante.DefaultSigVerificationGasConsumer
}

anteDecorators := []sdk.AnteDecorator{
return sdk.ChainAnteDecorators(
ante.NewSetUpContextDecorator(),
wasmkeeper.NewLimitSimulationGasDecorator(options.WasmConfig.SimulationGasLimit),
wasmkeeper.NewCountTXDecorator(options.TxCounterStoreKey),
ante.NewRejectExtensionOptionsDecorator(),
ante.NewMempoolFeeDecorator(),
feeskeeper.NewMinFeeDecorator(options.FeesKeeper),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
Expand All @@ -55,7 +59,5 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCChannelkeeper),
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
), nil
}
42 changes: 35 additions & 7 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import (
"github.com/desmos-labs/desmos/v3/x/relationships"
relationshipstypes "github.com/desmos-labs/desmos/v3/x/relationships/types"

"github.com/desmos-labs/desmos/v3/x/subspaces"

"github.com/cosmos/cosmos-sdk/version"

"github.com/desmos-labs/desmos/v3/x/fees"
feeskeeper "github.com/desmos-labs/desmos/v3/x/fees/keeper"
feestypes "github.com/desmos-labs/desmos/v3/x/fees/types"

"github.com/cosmos/cosmos-sdk/x/auth/vesting"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/authz"
Expand Down Expand Up @@ -93,6 +95,8 @@ import (
profileskeeper "github.com/desmos-labs/desmos/v3/x/profiles/keeper"
profilestypes "github.com/desmos-labs/desmos/v3/x/profiles/types"
relationshipskeeper "github.com/desmos-labs/desmos/v3/x/relationships/keeper"

"github.com/desmos-labs/desmos/v3/x/subspaces"
subspaceskeeper "github.com/desmos-labs/desmos/v3/x/subspaces/keeper"
subspacestypes "github.com/desmos-labs/desmos/v3/x/subspaces/types"

Expand Down Expand Up @@ -226,6 +230,7 @@ var (
profiles.AppModuleBasic{},
relationships.AppModuleBasic{},
subspaces.AppModuleBasic{},
fees.AppModuleBasic{},
supply.AppModuleBasic{},
)

Expand Down Expand Up @@ -286,6 +291,7 @@ type DesmosApp struct {
ScopedWasmKeeper capabilitykeeper.ScopedKeeper

// Custom modules
FeesKeeper feeskeeper.Keeper
SubspacesKeeper subspaceskeeper.Keeper
ProfileKeeper profileskeeper.Keeper
RelationshipsKeeper relationshipskeeper.Keeper
Expand Down Expand Up @@ -336,7 +342,8 @@ func NewDesmosApp(
authzkeeper.StoreKey, wasm.StoreKey,

// Custom modules
profilestypes.StoreKey, relationshipstypes.StoreKey, subspacestypes.StoreKey, supplytypes.StoreKey,
profilestypes.StoreKey, relationshipstypes.StoreKey, subspacestypes.StoreKey,
feestypes.StoreKey, supplytypes.StoreKey,
)
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
Expand Down Expand Up @@ -426,6 +433,9 @@ func NewDesmosApp(
)
transferModule := ibctransfer.NewAppModule(app.TransferKeeper)

// Create fees keeper
app.FeesKeeper = feeskeeper.NewKeeper(app.appCodec, app.GetSubspace(feestypes.ModuleName))

// Create subspaces keeper and module
subspacesKeeper := subspaceskeeper.NewKeeper(app.appCodec, keys[subspacestypes.StoreKey])

Expand Down Expand Up @@ -454,6 +464,7 @@ func NewDesmosApp(
app.ProfileKeeper,
app.AccountKeeper,
app.BankKeeper,
app.FeesKeeper,
)

// Register the subspaces hooks
Expand Down Expand Up @@ -560,9 +571,14 @@ func NewDesmosApp(
wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper),

// Custom modules
subspaces.NewAppModule(appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper),
fees.NewAppModule(app.appCodec, app.FeesKeeper),
subspaces.NewAppModule(appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper, app.FeesKeeper),
profilesModule,
relationships.NewAppModule(appCodec, app.RelationshipsKeeper, app.SubspacesKeeper, profilesv4.NewKeeper(keys[profilestypes.StoreKey], appCodec), app.AccountKeeper, app.BankKeeper),
relationships.NewAppModule(
appCodec, app.RelationshipsKeeper, app.SubspacesKeeper,
profilesv4.NewKeeper(keys[profilestypes.StoreKey], appCodec), app.AccountKeeper,
app.BankKeeper, app.FeesKeeper,
),
supply.NewAppModule(appCodec, legacyAmino, app.SupplyKeeper),
)

Expand Down Expand Up @@ -592,6 +608,7 @@ func NewDesmosApp(
ibctransfertypes.ModuleName,
wasm.ModuleName,

feestypes.ModuleName,
subspacestypes.ModuleName,
relationshipstypes.ModuleName,
profilestypes.ModuleName,
Expand All @@ -618,6 +635,7 @@ func NewDesmosApp(
ibctransfertypes.ModuleName,
wasm.ModuleName,

feestypes.ModuleName,
subspacestypes.ModuleName,
relationshipstypes.ModuleName,
profilestypes.ModuleName,
Expand Down Expand Up @@ -651,6 +669,7 @@ func NewDesmosApp(
wasm.ModuleName,

// Custom modules
feestypes.ModuleName,
subspacestypes.ModuleName,
profilestypes.ModuleName,
relationshipstypes.ModuleName,
Expand Down Expand Up @@ -683,6 +702,7 @@ func NewDesmosApp(
wasm.ModuleName,

// Custom modules
feestypes.ModuleName,
subspacestypes.ModuleName,
relationshipstypes.ModuleName,
profilestypes.ModuleName,
Expand Down Expand Up @@ -721,10 +741,15 @@ func NewDesmosApp(
wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper),

// Custom modules
fees.NewAppModule(appCodec, app.FeesKeeper),
supply.NewAppModule(appCodec, legacyAmino, app.SupplyKeeper),
subspaces.NewAppModule(appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper),
subspaces.NewAppModule(appCodec, app.SubspacesKeeper, app.AccountKeeper, app.BankKeeper, app.FeesKeeper),
profilesModule,
relationships.NewAppModule(appCodec, app.RelationshipsKeeper, app.SubspacesKeeper, profilesv4.NewKeeper(keys[profilestypes.StoreKey], appCodec), app.AccountKeeper, app.BankKeeper),
relationships.NewAppModule(
appCodec, app.RelationshipsKeeper, app.SubspacesKeeper,
profilesv4.NewKeeper(keys[profilestypes.StoreKey], appCodec), app.AccountKeeper,
app.BankKeeper, app.FeesKeeper,
),
)

app.sm.RegisterStoreDecoders()
Expand All @@ -747,6 +772,7 @@ func NewDesmosApp(
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
IBCChannelkeeper: app.IBCKeeper.ChannelKeeper,
FeesKeeper: app.FeesKeeper,
TxCounterStoreKey: keys[wasm.StoreKey],
WasmConfig: wasmConfig,
},
Expand Down Expand Up @@ -986,6 +1012,8 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(ibchost.ModuleName)
paramsKeeper.Subspace(wasm.ModuleName)

paramsKeeper.Subspace(feestypes.ModuleName)
paramsKeeper.Subspace(subspacestypes.ModuleName)
paramsKeeper.Subspace(profilestypes.ModuleName)

return paramsKeeper
Expand Down
3 changes: 3 additions & 0 deletions app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"path/filepath"
"testing"

feestypes "github.com/desmos-labs/desmos/v3/x/fees/types"

relationshipstypes "github.com/desmos-labs/desmos/v3/x/relationships/types"

authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
Expand Down Expand Up @@ -229,6 +231,7 @@ func TestAppImportExport(t *testing.T) {
{app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}},
{app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}},

{app.keys[feestypes.StoreKey], newApp.keys[feestypes.StoreKey], [][]byte{}},
{app.keys[subspacestypes.StoreKey], newApp.keys[subspacestypes.StoreKey], [][]byte{}},
{app.keys[profilestypes.StoreKey], newApp.keys[profilestypes.StoreKey], [][]byte{}},
{app.keys[relationshipstypes.StoreKey], newApp.keys[relationshipstypes.StoreKey], [][]byte{}},
Expand Down
14 changes: 14 additions & 0 deletions proto/desmos/fees/v1/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
syntax = "proto3";
package desmos.fees.v1;

import "gogoproto/gogo.proto";
import "desmos/fees/v1/params.proto";

option go_package = "github.com/desmos-labs/desmos/v3/x/fees/types";

// GenesisState contains the data of the genesis state for the fees module
message GenesisState {
option (gogoproto.goproto_getters) = false;

desmos.fees.v1.Params params = 1 [ (gogoproto.nullable) = false ];
}
19 changes: 19 additions & 0 deletions proto/desmos/fees/v1/min_fee.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";
package desmos.fees.v1;

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

option go_package = "github.com/desmos-labs/desmos/v3/x/fees/types";

// MinFee contains the minimum amount of coins that should be paid as a fee for
// each message of the specific type sent
message MinFee {
string message_type = 1 [ (gogoproto.moretags) = "yaml:\"message_type\"" ];

repeated cosmos.base.v1beta1.Coin amount = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"amount\""
];
}
15 changes: 15 additions & 0 deletions proto/desmos/fees/v1/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";
package desmos.fees.v1;

import "gogoproto/gogo.proto";
import "desmos/fees/v1/min_fee.proto";

option go_package = "github.com/desmos-labs/desmos/v3/x/fees/types";

// Params contains the parameters for the fees module
message Params {
repeated desmos.fees.v1.MinFee min_fees = 1 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"min_fees\""
];
}
26 changes: 26 additions & 0 deletions proto/desmos/fees/v1/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";
package desmos.fees.v1;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "desmos/fees/v1/params.proto";

option go_package = "github.com/desmos-labs/desmos/v3/x/fees/types";

// Query defines the gRPC querier service.
service Query {
// Params queries the fees module params
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/desmos/fees/v1/fees/params";
}
}

// ___________________________________________________________________________________________________________________

// QueryParamsRequest is the request type for the Query/Params RPC method.
message QueryParamsRequest {}

// QueryParamsResponse is the response type for the Query/Params RPC
message QueryParamsResponse {
desmos.fees.v1.Params params = 1 [ (gogoproto.nullable) = false ];
}
28 changes: 26 additions & 2 deletions testutil/simtesting/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package simtesting
import (
"math/rand"

feeskeeper "github.com/desmos-labs/desmos/v3/x/fees/keeper"

"github.com/cosmos/cosmos-sdk/baseapp"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
Expand All @@ -16,18 +18,22 @@ import (

// SendMsg sends a transaction with the specified message.
func SendMsg(
r *rand.Rand, app *baseapp.BaseApp, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper,
r *rand.Rand, app *baseapp.BaseApp, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, fk feeskeeper.Keeper,
msg sdk.Msg, ctx sdk.Context, chainID string, gasValue uint64, privkeys []cryptotypes.PrivKey,
) error {
addr := msg.GetSigners()[0]
account := ak.GetAccount(ctx, addr)
coins := bk.SpendableCoins(ctx, account.GetAddress())

fees, err := simtypes.RandomFees(r, ctx, coins)
fees, sendTx, err := computeFees(r, ctx, fk, msg, coins)
if err != nil {
return err
}

if !sendTx {
return nil
}

txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
Expand All @@ -50,3 +56,21 @@ func SendMsg(

return nil
}

// computeFees computes the fees that should be used to send a transaction with the given message,
// considering the max spendable amount provided and the min fees set inside the fees module
func computeFees(
r *rand.Rand, ctx sdk.Context, fk feeskeeper.Keeper, msg sdk.Msg, max sdk.Coins,
) (fees sdk.Coins, sendTx bool, err error) {
minFees := fk.GetParams(ctx).MinFees
for _, minFee := range minFees {
if sdk.MsgTypeURL(msg) == minFee.MessageType {
fees = minFee.Amount
sendTx = fees.IsAllLT(max)
return
}
}

fees, err = simtypes.RandomFees(r, ctx, max)
return
}
Loading

0 comments on commit c684768

Please sign in to comment.