From 9eafd1a30c5becd2dcab30c5b92c9b2e9200408f Mon Sep 17 00:00:00 2001 From: alpo <62043214+AlpinYukseloglu@users.noreply.github.com> Date: Thu, 17 Feb 2022 22:19:22 -0800 Subject: [PATCH] Ensure gauges can only be created for assets that exist on-chain (#855) * ensure gauges can only be created for onchain denoms + comments * added and fixed tests + cleaned up comments * added support for superfluid synthetic denoms * fixed tests to accommodate new checks --- x/incentives/abci_test.go | 12 ++++++++++++ x/incentives/genesis_test.go | 6 ++++++ x/incentives/keeper/gauge.go | 8 ++++++++ x/incentives/keeper/gauge_test.go | 17 +++++++++++++++++ x/incentives/keeper/suite_test.go | 6 ++++++ x/incentives/types/expected_keepers.go | 2 ++ x/mint/keeper/hooks_test.go | 6 ++++++ x/mint/keeper/keeper_test.go | 6 ++++++ 8 files changed, 63 insertions(+) diff --git a/x/incentives/abci_test.go b/x/incentives/abci_test.go index 445aa39a679..e203cf5c215 100644 --- a/x/incentives/abci_test.go +++ b/x/incentives/abci_test.go @@ -30,6 +30,12 @@ func TestPerpetualGaugeNotExpireAfterDistribution(t *testing.T) { Denom: "lptoken", Duration: time.Second, } + + // mints coins so supply exists on chain + mintLPtokens := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err = simapp.FundAccount(app.BankKeeper, ctx, addr, mintLPtokens) + require.NoError(t, err) + _, err = app.IncentivesKeeper.CreateGauge(ctx, true, addr, coins, distrTo, time.Now(), 1) require.NoError(t, err) @@ -62,6 +68,12 @@ func TestNonPerpetualGaugeExpireAfterDistribution(t *testing.T) { Denom: "lptoken", Duration: time.Second, } + + // mints coins so supply exists on chain + mintLPtokens := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err = simapp.FundAccount(app.BankKeeper, ctx, addr, mintLPtokens) + require.NoError(t, err) + _, err = app.IncentivesKeeper.CreateGauge(ctx, false, addr, coins, distrTo, time.Now(), 1) require.NoError(t, err) diff --git a/x/incentives/genesis_test.go b/x/incentives/genesis_test.go index 08a432aa29d..8c2c09a96c5 100644 --- a/x/incentives/genesis_test.go +++ b/x/incentives/genesis_test.go @@ -32,6 +32,12 @@ func TestIncentivesExportGenesis(t *testing.T) { startTime := time.Now() err := simapp.FundAccount(app.BankKeeper, ctx, addr, coins) require.NoError(t, err) + + // mints coins so supply exists on chain + mintLPtokens := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err = simapp.FundAccount(app.BankKeeper, ctx, addr, mintLPtokens) + require.NoError(t, err) + gaugeID, err := app.IncentivesKeeper.CreateGauge(ctx, true, addr, coins, distrTo, startTime, 1) require.NoError(t, err) diff --git a/x/incentives/keeper/gauge.go b/x/incentives/keeper/gauge.go index d487b3dfac3..82e1bdba122 100644 --- a/x/incentives/keeper/gauge.go +++ b/x/incentives/keeper/gauge.go @@ -3,6 +3,7 @@ package keeper import ( "encoding/json" "fmt" + "strings" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -100,6 +101,8 @@ func (k Keeper) SetGaugeWithRefKey(ctx sdk.Context, gauge *types.Gauge) error { // CreateGauge create a gauge and send coins to the gauge func (k Keeper) CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64) (uint64, error) { + + // Ensure that this gauge's duration is one of the allowed durations on chain durations := k.GetLockableDurations(ctx) if distrTo.LockQueryType == lockuptypes.ByDuration { durationOk := false @@ -114,6 +117,11 @@ func (k Keeper) CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddr } } + // Ensure that the denom this gauge pays out to exists on-chain + if !k.bk.HasSupply(ctx, distrTo.Denom) && !strings.Contains(distrTo.Denom, "osmovaloper") { + return 0, fmt.Errorf("denom does not exist: %s", distrTo.Denom) + } + gauge := types.Gauge{ Id: k.GetLastGaugeID(ctx) + 1, IsPerpetual: isPerpetual, diff --git a/x/incentives/keeper/gauge_test.go b/x/incentives/keeper/gauge_test.go index c5f7a10b6e6..f33e52624f4 100644 --- a/x/incentives/keeper/gauge_test.go +++ b/x/incentives/keeper/gauge_test.go @@ -25,6 +25,23 @@ func (suite *KeeperTestSuite) TestInvalidDurationGaugeCreationValidation() { suite.Require().NoError(err) } +func (suite *KeeperTestSuite) TestNonExistentDenomGaugeCreation() { + suite.SetupTest() + + addrNoSupply := sdk.AccAddress([]byte("Gauge_Creation_Addr_")) + addrs := suite.SetupManyLocks(1, defaultLiquidTokens, defaultLPTokens, defaultLockDuration) + distrTo := lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.ByDuration, + Denom: defaultLPDenom, + Duration: defaultLockDuration, + } + _, err := suite.app.IncentivesKeeper.CreateGauge(suite.ctx, false, addrNoSupply, defaultLiquidTokens, distrTo, time.Time{}, 1) + suite.Require().Error(err) + + _, err = suite.app.IncentivesKeeper.CreateGauge(suite.ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1) + suite.Require().NoError(err) +} + // TODO: Make this test table driven // OR if it needs to be script based, // remove lots of boilerplate so this can actually be followed diff --git a/x/incentives/keeper/suite_test.go b/x/incentives/keeper/suite_test.go index fba65f318b0..9b9fcd66186 100644 --- a/x/incentives/keeper/suite_test.go +++ b/x/incentives/keeper/suite_test.go @@ -114,6 +114,12 @@ func (suite *KeeperTestSuite) setupNewGaugeWithDuration(isPerpetual bool, coins Denom: "lptoken", Duration: duration, } + + // mints coins so supply exists on chain + mintCoins := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr, mintCoins) + suite.Require().NoError(err) + numEpochsPaidOver := uint64(2) if isPerpetual { numEpochsPaidOver = uint64(1) diff --git a/x/incentives/types/expected_keepers.go b/x/incentives/types/expected_keepers.go index 0a4267ddeb8..ab863c52c61 100644 --- a/x/incentives/types/expected_keepers.go +++ b/x/incentives/types/expected_keepers.go @@ -12,6 +12,8 @@ import ( type BankKeeper interface { GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + HasSupply(ctx sdk.Context, denom string) bool + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromModuleToManyAccounts( ctx sdk.Context, senderModule string, recipientAddrs []sdk.AccAddress, amts []sdk.Coins, diff --git a/x/mint/keeper/hooks_test.go b/x/mint/keeper/hooks_test.go index 1f029ef0d5c..4d7ecd4e433 100644 --- a/x/mint/keeper/hooks_test.go +++ b/x/mint/keeper/hooks_test.go @@ -216,6 +216,12 @@ func setupGaugeForLPIncentives(t *testing.T, app *osmoapp.OsmosisApp, ctx sdk.Co Denom: "lptoken", Duration: time.Second, } + + // mints coins so supply exists on chain + mintLPtokens := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err = simapp.FundAccount(app.BankKeeper, ctx, addr, mintLPtokens) + require.NoError(t, err) + _, err = app.IncentivesKeeper.CreateGauge(ctx, true, addr, coins, distrTo, time.Now(), 1) require.NoError(t, err) } diff --git a/x/mint/keeper/keeper_test.go b/x/mint/keeper/keeper_test.go index f7b4dc6285c..f40183d37d4 100644 --- a/x/mint/keeper/keeper_test.go +++ b/x/mint/keeper/keeper_test.go @@ -82,6 +82,12 @@ func (suite *KeeperTestSuite) TestDistrAssetToDeveloperRewardsAddrWhenNotEmpty() Denom: "lptoken", Duration: time.Second, } + + // mints coins so supply exists on chain + mintLPtokens := sdk.Coins{sdk.NewInt64Coin(distrTo.Denom, 200)} + err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, gaugeCreator, mintLPtokens) + suite.Require().NoError(err) + gaugeId, err := suite.app.IncentivesKeeper.CreateGauge(suite.ctx, true, gaugeCreator, coins, distrTo, time.Now(), 1) suite.NoError(err) err = suite.app.PoolIncentivesKeeper.UpdateDistrRecords(suite.ctx, poolincentivestypes.DistrRecord{