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(incentives)!: create gauge and add to gauge fee charge #2227

Merged
merged 29 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cdbc677
feat(incentives)!: create gauge and add to gauge fee charge
p0mvn Jul 24, 2022
2895645
initialize txfees keeper before incentives
p0mvn Jul 24, 2022
82ae999
finish TestChargeFee
p0mvn Jul 24, 2022
bec3023
refactor to charge fee in message server
p0mvn Jul 24, 2022
4fd5c71
more tests
p0mvn Jul 24, 2022
ccf9daa
clean up
p0mvn Jul 24, 2022
ec5fbea
test balances
p0mvn Jul 24, 2022
590349f
test create gauge fees (#2228)
czarcas7ic Jul 24, 2022
023fc86
add comments
p0mvn Jul 24, 2022
555d006
Merge branch 'roman/txfees-simplified' of github.com:osmosis-labs/osm…
p0mvn Jul 24, 2022
1b4eb6c
account keeper comment
p0mvn Jul 24, 2022
86e8b5e
fix TestCreateGaugeFee
p0mvn Jul 25, 2022
100b693
apply appparams.BaseCoinUnit
p0mvn Jul 25, 2022
915e9ff
remove txfees keeper from incentives and revert order
p0mvn Jul 25, 2022
70d9347
clean up
p0mvn Jul 25, 2022
b91c221
remove unused keepers fromm incentives keeper
p0mvn Jul 25, 2022
f9fd23c
Update x/incentives/keeper/gauge.go
p0mvn Jul 25, 2022
ff28eb4
Update x/incentives/keeper/gauge.go
p0mvn Jul 25, 2022
3da8d5a
clean up
p0mvn Jul 25, 2022
c14509a
Merge branch 'roman/txfees-simplified' of github.com:osmosis-labs/osm…
p0mvn Jul 25, 2022
f841b49
fixture names
p0mvn Jul 25, 2022
0503797
chargeFeeIfSufficientFeeDenomBalance test name
p0mvn Jul 25, 2022
0f4a821
changelog
p0mvn Jul 25, 2022
5c43126
comment
p0mvn Jul 25, 2022
a16ba32
finished tests (#2230)
czarcas7ic Jul 25, 2022
eba45d2
clean up
p0mvn Jul 25, 2022
87dd1fe
sim only allow accounts with enough to pay fee
czarcas7ic Jul 25, 2022
8698876
lint
czarcas7ic Jul 25, 2022
b2d6437
move fee to types and reuse in simulation (#2234)
p0mvn Jul 26, 2022
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 changes: 2 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,11 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
appCodec,
appKeepers.keys[incentivestypes.StoreKey],
appKeepers.GetSubspace(incentivestypes.ModuleName),
appKeepers.AccountKeeper,
appKeepers.BankKeeper,
appKeepers.LockupKeeper,
appKeepers.EpochsKeeper,
appKeepers.DistrKeeper,
)

appKeepers.SuperfluidKeeper = superfluidkeeper.NewKeeper(
Expand Down
16 changes: 14 additions & 2 deletions x/incentives/keeper/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ import (
"github.com/osmosis-labs/osmosis/v10/x/incentives/types"
)

const (
// CreateGaugeFee is the fee required to create a new gauge.
CreateGaugeFee = createGaugeFee
// AddToGagugeFee is the fee required to add to gauge.
AddToGaugeFee = addToGaugeFee
)

// AddGaugeRefByKey appends the provided gauge ID into an array associated with the provided key.
func (k Keeper) AddGaugeRefByKey(ctx sdk.Context, key []byte, guageID uint64) error {
return k.addGaugeRefByKey(ctx, key, guageID)
func (k Keeper) AddGaugeRefByKey(ctx sdk.Context, key []byte, gaugeID uint64) error {
return k.addGaugeRefByKey(ctx, key, gaugeID)
}

// DeleteGaugeRefByKey removes the provided gauge ID from an array associated with the provided key.
Expand All @@ -35,3 +42,8 @@ func (k Keeper) MoveUpcomingGaugeToActiveGauge(ctx sdk.Context, gauge types.Gaug
func (k Keeper) MoveActiveGaugeToFinishedGauge(ctx sdk.Context, gauge types.Gauge) error {
return k.moveActiveGaugeToFinishedGauge(ctx, gauge)
}

// ChargeFeeIfSufficientFeeDenomBalance see chargeFeeIfSufficientFeeDenomBalance spec.
func (k Keeper) ChargeFeeIfSufficientFeeDenomBalance(ctx sdk.Context, address sdk.AccAddress, fee int64, gaugeCoins sdk.Coins) error {
return k.chargeFeeIfSufficientFeeDenomBalance(ctx, address, fee, gaugeCoins)
}
27 changes: 27 additions & 0 deletions x/incentives/keeper/gauge.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@ import (
"strings"
"time"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/gogo/protobuf/proto"
db "github.com/tendermint/tm-db"

appparams "github.com/osmosis-labs/osmosis/v10/app/params"
epochtypes "github.com/osmosis-labs/osmosis/v10/x/epochs/types"
"github.com/osmosis-labs/osmosis/v10/x/incentives/types"
lockuptypes "github.com/osmosis-labs/osmosis/v10/x/lockup/types"

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

const (
// CreateGaugeFee is the fee required to create a new gauge.
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
createGaugeFee = 50 * 1_000_000
// AddToGagugeFee is the fee required to add to gauge.
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
addToGaugeFee = 25 * 1_000_000
)

// getGaugesFromIterator iterates over everything in a gauge's iterator, until it reaches the end. Return all gauges iterated over.
func (k Keeper) getGaugesFromIterator(ctx sdk.Context, iterator db.Iterator) []types.Gauge {
gauges := []types.Gauge{}
Expand Down Expand Up @@ -278,3 +287,21 @@ func (k Keeper) GetEpochInfo(ctx sdk.Context) epochtypes.EpochInfo {
params := k.GetParams(ctx)
return k.ek.GetEpochInfo(ctx, params.DistrEpochIdentifier)
}

// chargeFeeIfSufficientFeeDenomBalance charges fee in the base tx fee denom on the address if the address has
// balance that is less than fee + amount of the coin from gaugeCoins that is of base tx fee denom.
// gaugeCoins might not have a coin of tx base fee denom. In that case, only fee is compared to balance.
// The fee is sent to the community pool.
// Returns nil on success, error otherwise.
func (k Keeper) chargeFeeIfSufficientFeeDenomBalance(ctx sdk.Context, address sdk.AccAddress, fee int64, gaugeCoins sdk.Coins) (err error) {
feeInt := sdk.NewInt(fee)
totalCost := gaugeCoins.AmountOf(appparams.BaseCoinUnit).Add(feeInt)
accountBalance := k.bk.GetBalance(ctx, address, appparams.BaseCoinUnit).Amount
if accountBalance.LT(totalCost) {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "account's balance of %s (%s) is less than the total cost of the message (%s)", appparams.BaseCoinUnit, accountBalance, totalCost)
}
if err := k.dk.FundCommunityPool(ctx, sdk.NewCoins(sdk.NewCoin(appparams.BaseCoinUnit, feeInt)), address); err != nil {
return err
}
return nil
}
101 changes: 100 additions & 1 deletion x/incentives/keeper/gauge_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package keeper_test

import (
"testing"
"time"

"github.com/stretchr/testify/suite"

appparams "github.com/osmosis-labs/osmosis/v10/app/params"
"github.com/osmosis-labs/osmosis/v10/x/incentives/types"
lockuptypes "github.com/osmosis-labs/osmosis/v10/x/lockup/types"

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

var _ = suite.TestingSuite(nil)
func TestGaugeTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}

// TestInvalidDurationGaugeCreationValidation tests error handling for creating a gauge with an invalid duration.
func (suite *KeeperTestSuite) TestInvalidDurationGaugeCreationValidation() {
Expand Down Expand Up @@ -237,3 +241,98 @@ func (suite *KeeperTestSuite) TestGaugeOperations() {
}
}
}

func (suite *KeeperTestSuite) TestChargeFee() {
const baseFee = int64(100)

testcases := map[string]struct {
accountBalanceToFund sdk.Coin
feeToCharge int64
gaugeCoins sdk.Coins

expectError bool
}{
"fee + base denom gauge coin == acount balance, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee / 2,
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee/2))),
},
"fee + base denom gauge coin < acount balance, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee/2 - 1,
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee/2))),
},
"fee + base denom gauge coin > acount balance, error": {
accountBalanceToFund: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee/2 + 1,
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee/2))),

expectError: true,
},
"fee + base denom gauge coin < acount balance, custom values, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(11793193112)),
feeToCharge: 55,
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(328812))),
},
"account funded with coins other than base denom, error": {
accountBalanceToFund: sdk.NewCoin("usdc", sdk.NewInt(baseFee)),
feeToCharge: baseFee,
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee/2))),

expectError: true,
},
"fee == account balance, no gauge coins, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee,
},
"gauge coins == account balance, no fee, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
gaugeCoins: sdk.NewCoins(sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee))),
},
"fee == account balance, gauge coins in denom other than base, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee,
gaugeCoins: sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(baseFee*2))),
},
"fee + gauge coins == account balance, multiple gauge coins, one in denom other than base, success": {
accountBalanceToFund: sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee)),
feeToCharge: baseFee / 2,
gaugeCoins: sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(baseFee*2)), sdk.NewCoin(appparams.DefaultBondDenom, sdk.NewInt(baseFee/2))),
},
}

for name, tc := range testcases {
suite.Run(name, func() {
suite.SetupTest()

testAccount := suite.TestAccs[0]

ctx := suite.Ctx
incentivesKeepers := suite.App.IncentivesKeeper
bankKeeper := suite.App.BankKeeper

// Pre-fund account.
suite.FundAcc(testAccount, sdk.NewCoins(tc.accountBalanceToFund))

oldBalanceAmount := bankKeeper.GetBalance(ctx, testAccount, appparams.DefaultBondDenom).Amount

// System under test.
err := incentivesKeepers.ChargeFeeIfSufficientFeeDenomBalance(ctx, testAccount, tc.feeToCharge, tc.gaugeCoins)

// Assertions.
newBalanceAmount := bankKeeper.GetBalance(ctx, testAccount, appparams.DefaultBondDenom).Amount
if tc.expectError {
suite.Require().Error(err)

// check account balance unchanged
suite.Require().Equal(oldBalanceAmount, newBalanceAmount)
} else {
suite.Require().NoError(err)

// check account balance changed.
expectedNewBalanceAmount := oldBalanceAmount.Sub(sdk.NewInt(tc.feeToCharge))
suite.Require().Equal(expectedNewBalanceAmount.String(), newBalanceAmount.String())
}
})
}
}
6 changes: 5 additions & 1 deletion x/incentives/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ type Keeper struct {
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace
hooks types.IncentiveHooks
ak types.AccountKeeper
bk types.BankKeeper
lk types.LockupKeeper
ek types.EpochKeeper
dk types.DistrKeeper
}

// NewKeeper returns a new instance of the incentive module keeper struct.
func NewKeeper(cdc codec.Codec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, bk types.BankKeeper, lk types.LockupKeeper, ek types.EpochKeeper) *Keeper {
func NewKeeper(cdc codec.Codec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, ak types.AccountKeeper, bk types.BankKeeper, lk types.LockupKeeper, ek types.EpochKeeper, dk types.DistrKeeper) *Keeper {
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
}
Expand All @@ -34,9 +36,11 @@ func NewKeeper(cdc codec.Codec, storeKey sdk.StoreKey, paramSpace paramtypes.Sub
cdc: cdc,
storeKey: storeKey,
paramSpace: paramSpace,
ak: ak,
bk: bk,
lk: lk,
ek: ek,
dk: dk,
}
}

Expand Down
8 changes: 8 additions & 0 deletions x/incentives/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ func (server msgServer) CreateGauge(goCtx context.Context, msg *types.MsgCreateG
return nil, err
}

if err := server.keeper.chargeFeeIfSufficientFeeDenomBalance(ctx, owner, createGaugeFee, msg.Coins); err != nil {
return nil, err
}

gaugeID, err := server.keeper.CreateGauge(ctx, msg.IsPerpetual, owner, msg.Coins, msg.DistributeTo, msg.StartTime, msg.NumEpochsPaidOver)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
Expand All @@ -56,6 +60,10 @@ func (server msgServer) AddToGauge(goCtx context.Context, msg *types.MsgAddToGau
if err != nil {
return nil, err
}

if err := server.keeper.chargeFeeIfSufficientFeeDenomBalance(ctx, owner, addToGaugeFee, msg.Rewards); err != nil {
return nil, err
}
err = server.keeper.AddToGaugeRewards(ctx, owner, msg.Rewards, msg.GaugeId)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
Expand Down
Loading