Skip to content

Commit

Permalink
implementing gas consume on denom creation - osmosis-labs/osmosis#4983
Browse files Browse the repository at this point in the history
  • Loading branch information
spoo-bar committed May 23, 2023
1 parent 73086c0 commit b76911f
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 37 deletions.
5 changes: 4 additions & 1 deletion docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ Params defines the parameters for the tokenfactory module.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `denom_creation_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |
| `denom_creation_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | DenomCreationFee defines the fee to be charged on the creation of a new denom. The fee is drawn from the MsgCreateDenom's sender account, and transferred to the community pool. |
| `denom_creation_gas_consume` | [uint64](#uint64) | | DenomCreationGasConsume defines the gas cost for creating a new denom. This is intended as a spam deterrence mechanism.

See: https://github.com/CosmWasm/token-factory/issues/11 |



Expand Down
13 changes: 13 additions & 0 deletions proto/osmosis/tokenfactory/v1beta1/tokenfactory.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,22 @@ message DenomAuthorityMetadata {

// Params defines the parameters for the tokenfactory module.
message Params {
// DenomCreationFee defines the fee to be charged on the creation of a new
// denom. The fee is drawn from the MsgCreateDenom's sender account, and
// transferred to the community pool.
repeated cosmos.base.v1beta1.Coin denom_creation_fee = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"denom_creation_fee\"",
(gogoproto.nullable) = false
];


// DenomCreationGasConsume defines the gas cost for creating a new denom.
// This is intended as a spam deterrence mechanism.
//
// See: https://github.com/CosmWasm/token-factory/issues/11
uint64 denom_creation_gas_consume = 2 [
(gogoproto.moretags) = "yaml:\"denom_creation_gas_consume\"",
(gogoproto.nullable) = true
];
}
25 changes: 17 additions & 8 deletions x/tokenfactory/keeper/create_denom.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,25 @@ func (k Keeper) validateCreateDenom(ctx sdk.Context, creatorAddr string, subdeno
}

func (k Keeper) chargeForCreateDenom(ctx sdk.Context, creatorAddr string, _ string) (err error) {
// Send creation fee to community pool
creationFee := k.GetParams(ctx).DenomCreationFee
accAddr, err := sdk.AccAddressFromBech32(creatorAddr)
if err != nil {
return err
}
if creationFee != nil {
if err := k.communityPoolKeeper.FundCommunityPool(ctx, creationFee, accAddr); err != nil {
params := k.GetParams(ctx)

// if DenomCreationFee is non-zero, transfer the tokens from the creator
// account to community pool
if params.DenomCreationFee != nil {
accAddr, err := sdk.AccAddressFromBech32(creatorAddr)
if err != nil {
return err
}

if err := k.communityPoolKeeper.FundCommunityPool(ctx, params.DenomCreationFee, accAddr); err != nil {
return err
}
}

// if DenomCreationGasConsume is non-zero, consume the gas
if params.DenomCreationGasConsume != 0 {
ctx.GasMeter().ConsumeGas(params.DenomCreationGasConsume, "consume denom creation gas")
}

return nil
}
65 changes: 65 additions & 0 deletions x/tokenfactory/keeper/create_denom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,68 @@ func (suite *KeeperTestSuite) TestCreateDenom() {
})
}
}

func (suite *KeeperTestSuite) TestGasConsume() {
// It's hard to estimate exactly how much gas will be consumed when creating a
// denom, because besides consuming the gas specified by the params, the keeper
// also does a bunch of other things that consume gas.
//
// Rather, we test whether the gas consumed is within a range. Specifically,
// the range [gasConsume, gasConsume + offset]. If the actual gas consumption
// falls within the range for all test cases, we consider the test passed.
//
// In experience, the total amount of gas consumed should consume be ~30k more
// than the set amount.
const offset = 50000

for _, tc := range []struct {
desc string
gasConsume uint64
}{
{
desc: "gas consume zero",
gasConsume: 0,
},
{
desc: "gas consume 1,000,000",
gasConsume: 1_000_000,
},
{
desc: "gas consume 10,000,000",
gasConsume: 10_000_000,
},
{
desc: "gas consume 25,000,000",
gasConsume: 25_000_000,
},
{
desc: "gas consume 50,000,000",
gasConsume: 50_000_000,
},
{
desc: "gas consume 200,000,000",
gasConsume: 200_000_000,
},
} {
suite.SetupTest()
suite.Run(fmt.Sprintf("Case %s", tc.desc), func() {
// set params with the gas consume amount
suite.App.TokenFactoryKeeper.SetParams(suite.Ctx, types.NewParams(nil, tc.gasConsume))

// amount of gas consumed prior to the denom creation
gasConsumedBefore := suite.Ctx.GasMeter().GasConsumed()

// create a denom
_, err := suite.msgServer.CreateDenom(sdk.WrapSDKContext(suite.Ctx), types.NewMsgCreateDenom(suite.TestAccs[0].String(), "larry"))
suite.Require().NoError(err)

// amount of gas consumed after the denom creation
gasConsumedAfter := suite.Ctx.GasMeter().GasConsumed()

// the amount of gas consumed must be within the range
gasConsumed := gasConsumedAfter - gasConsumedBefore
suite.Require().Greater(gasConsumed, tc.gasConsume)
suite.Require().Less(gasConsumed, tc.gasConsume+offset)
})
}
}
21 changes: 17 additions & 4 deletions x/tokenfactory/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,27 @@ import (

// Parameter store keys.
var (
KeyDenomCreationFee = []byte("DenomCreationFee")
KeyDenomCreationFee = []byte("DenomCreationFee")
KeyDenomCreationGasConsume = []byte("DenomCreationGasConsume")
)

// ParamTable for gamm module.
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}

func NewParams(denomCreationFee sdk.Coins) Params {
func NewParams(denomCreationFee sdk.Coins, denomCreationGasConsume uint64) Params {
return Params{
DenomCreationFee: denomCreationFee,
DenomCreationFee: denomCreationFee,
DenomCreationGasConsume: denomCreationGasConsume,
}
}

// default gamm module parameters.
func DefaultParams() Params {
return Params{
DenomCreationFee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 10_000_000)), // 10 STAKE
DenomCreationFee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 10_000_000)), // 10 STAKE
DenomCreationGasConsume: 0,
}
}

Expand All @@ -39,6 +42,7 @@ func (p Params) Validate() error {
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(KeyDenomCreationFee, &p.DenomCreationFee, validateDenomCreationFee),
paramtypes.NewParamSetPair(KeyDenomCreationGasConsume, &p.DenomCreationGasConsume, validateDenomCreationGasConsume),
}
}

Expand All @@ -54,3 +58,12 @@ func validateDenomCreationFee(i interface{}) error {

return nil
}

func validateDenomCreationGasConsume(i interface{}) error {
_, ok := i.(uint64)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

return nil
}
92 changes: 68 additions & 24 deletions x/tokenfactory/types/tokenfactory.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b76911f

Please sign in to comment.