Skip to content

Commit

Permalink
feat: finish incentive module (#1952)
Browse files Browse the repository at this point in the history
* exponent fix

* store reward accumulator exponent

* spec abstract

* rename field

* initial app wiring

* comment out incomplete invariant

* implement govtypes.Content

* bug todo

* package umee.incentive.v1

* add message name option to tx.proto

* fix bug

* ++

* make proto-all

* proto: remove unbonding tiers

* remove unbonding tiers from code

* --

* allow unbonding duration zero

* skip unbonding creation when duration is zero

* update queries; unbonding time decrease affects ongoing unbondings

* commit everything, everywhere, all at once

* fix tests without changing module init order

* userMaxWithdraw now respects bonded collateral

* mock leverage keeper tokens

* remove circular keeper reference and refactor hooks

* msg bond tests

* lint

* md lint

* tests

* test max unbondings

* unbonding completion test

* ++

* implement emergency unbond logic

* remove ErrNotImplemented

* proto field renames

* todon't

* extra incentiveprogram validate

* more validation

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* do not override heeper when setting hooks

* implement proto change suggestions

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggested whitespace (app)

* implement all util/keys changes

* fix merge

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* validate functions for genesis subtypes

* genesis test stub

* add gov create programs test

* emergency unbond test

* msg sponsor tests

* early return in updateRewards

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* cosmetic update in updateRewards

* suggestion++

Co-authored-by: Robert Zaremba <[email protected]>

* partial scenario test

* refactor all incentive tests to unit tests

* cleanup

* lint

* cleanup incentive program add/modify/delete functions

* fixed bug

* finishUnbondings -> cleanupUnbondings

* break loop early

* remove unnecessary gov.Content

* comment--

* remove proto getters-all

* remove proto messagename-all

* rename to ForceUnbondTo

* initialize exponent on program create (gov)

* add v4.4 migrator

* allow setting max unbondings to unlimited

* replace panic with err in iterators

* remove communtiy fund param - use distribution module account

* proto doc max unbondings

* emergency unbond CLI was missing

* typo

* comment

* max unbondings default to 10

* comment--

* remove redundant empty string check

* refactor functions surrounding reduceBondTo

* add current rates query for frontend

---------

Co-authored-by: Robert Zaremba <[email protected]>
  • Loading branch information
toteki and robert-zaremba authored Apr 25, 2023
1 parent 87a8725 commit 81b86b1
Show file tree
Hide file tree
Showing 64 changed files with 5,228 additions and 2,920 deletions.
34 changes: 25 additions & 9 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ import (
appparams "github.com/umee-network/umee/v4/app/params"
"github.com/umee-network/umee/v4/swagger"
"github.com/umee-network/umee/v4/util/genmap"
"github.com/umee-network/umee/v4/x/incentive"
incentivekeeper "github.com/umee-network/umee/v4/x/incentive/keeper"
incentivemodule "github.com/umee-network/umee/v4/x/incentive/module"
"github.com/umee-network/umee/v4/x/leverage"
leveragekeeper "github.com/umee-network/umee/v4/x/leverage/keeper"
leveragetypes "github.com/umee-network/umee/v4/x/leverage/types"
Expand Down Expand Up @@ -186,6 +189,7 @@ func init() {
// ibcfee.AppModuleBasic{},
gravity.AppModuleBasic{},
leverage.AppModuleBasic{},
incentivemodule.AppModuleBasic{},
oracle.AppModuleBasic{},
bech32ibc.AppModuleBasic{},
uibcmodule.AppModuleBasic{},
Expand All @@ -210,6 +214,7 @@ func init() {
icatypes.ModuleName: nil,
gravitytypes.ModuleName: {authtypes.Minter, authtypes.Burner},
leveragetypes.ModuleName: {authtypes.Minter, authtypes.Burner},
incentive.ModuleName: nil,
oracletypes.ModuleName: nil,
uibc.ModuleName: nil,
}
Expand Down Expand Up @@ -260,6 +265,7 @@ type UmeeApp struct {
ICAHostKeeper icahostkeeper.Keeper
GravityKeeper gravitykeeper.Keeper
LeverageKeeper leveragekeeper.Keeper
IncentiveKeeper incentivekeeper.Keeper
OracleKeeper oraclekeeper.Keeper
bech32IbcKeeper bech32ibckeeper.Keeper
UIbcQuotaKeeper uibcquotakeeper.Keeper
Expand Down Expand Up @@ -324,8 +330,8 @@ func New(
authzkeeper.StoreKey, nftkeeper.StoreKey, group.StoreKey,
ibchost.StoreKey, ibctransfertypes.StoreKey, icahosttypes.StoreKey,
gravitytypes.StoreKey,
leveragetypes.StoreKey, oracletypes.StoreKey, bech32ibctypes.StoreKey,
uibc.StoreKey,
leveragetypes.StoreKey, incentive.StoreKey, oracletypes.StoreKey,
bech32ibctypes.StoreKey, uibc.StoreKey,
}
if Experimental {
storeKeys = append(storeKeys, wasm.StoreKey)
Expand Down Expand Up @@ -466,11 +472,14 @@ func New(
app.OracleKeeper,
cast.ToBool(appOpts.Get(leveragetypes.FlagEnableLiquidatorQuery)),
)
app.LeverageKeeper = *app.LeverageKeeper.SetHooks(
leveragetypes.NewMultiHooks(
app.OracleKeeper.Hooks(),
),
app.IncentiveKeeper = incentivekeeper.NewKeeper(
appCodec,
keys[incentive.StoreKey],
app.BankKeeper,
app.LeverageKeeper,
)
app.LeverageKeeper.SetTokenHooks(app.OracleKeeper.Hooks())
app.LeverageKeeper.SetBondHooks(app.IncentiveKeeper.BondHooks())

app.GravityKeeper = gravitykeeper.NewKeeper(
keys[gravitytypes.StoreKey],
Expand Down Expand Up @@ -674,6 +683,7 @@ func New(
ica.NewAppModule(nil, &app.ICAHostKeeper),
gravity.NewAppModule(app.GravityKeeper, app.BankKeeper),
leverage.NewAppModule(appCodec, app.LeverageKeeper, app.AccountKeeper, app.BankKeeper),
incentivemodule.NewAppModule(appCodec, app.IncentiveKeeper, app.BankKeeper, app.LeverageKeeper),
oracle.NewAppModule(appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper),
bech32ibc.NewAppModule(appCodec, app.bech32IbcKeeper),
uibcmodule.NewAppModule(appCodec, app.UIbcQuotaKeeper),
Expand Down Expand Up @@ -703,6 +713,7 @@ func New(
paramstypes.ModuleName, vestingtypes.ModuleName,
icatypes.ModuleName, // ibcfeetypes.ModuleName,
leveragetypes.ModuleName,
incentive.ModuleName,
oracletypes.ModuleName,
gravitytypes.ModuleName,
bech32ibctypes.ModuleName,
Expand All @@ -721,6 +732,7 @@ func New(
paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
icatypes.ModuleName, // ibcfeetypes.ModuleName,
leveragetypes.ModuleName,
incentive.ModuleName,
gravitytypes.ModuleName,
bech32ibctypes.ModuleName,
uibc.ModuleName,
Expand All @@ -743,6 +755,7 @@ func New(

oracletypes.ModuleName,
leveragetypes.ModuleName,
incentive.ModuleName,
gravitytypes.ModuleName,
bech32ibctypes.ModuleName,
uibc.ModuleName,
Expand All @@ -758,6 +771,7 @@ func New(

oracletypes.ModuleName,
leveragetypes.ModuleName,
incentive.ModuleName,
gravitytypes.ModuleName,
bech32ibctypes.ModuleName,
uibc.ModuleName,
Expand Down Expand Up @@ -794,10 +808,12 @@ func New(

simStateModules := genmap.Pick(
app.mm.Modules,
[]string{stakingtypes.ModuleName, authtypes.ModuleName, oracletypes.ModuleName,
ibchost.ModuleName},
[]string{
stakingtypes.ModuleName, authtypes.ModuleName, oracletypes.ModuleName,
ibchost.ModuleName,
},
)
// TODO: Ensure x/leverage implements simulator and add it here:
// TODO: Ensure x/leverage, x/incentive implement simulator and add it here:
simTestModules := genmap.Pick(simStateModules,
[]string{oracletypes.ModuleName, ibchost.ModuleName})

Expand Down
14 changes: 13 additions & 1 deletion app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/umee-network/umee/v4/app/upgradev3"
"github.com/umee-network/umee/v4/app/upgradev3x3"
"github.com/umee-network/umee/v4/x/incentive"
leveragekeeper "github.com/umee-network/umee/v4/x/leverage/keeper"
leveragetypes "github.com/umee-network/umee/v4/x/leverage/types"
oraclekeeper "github.com/umee-network/umee/v4/x/oracle/keeper"
Expand All @@ -47,6 +48,18 @@ func (app UmeeApp) RegisterUpgradeHandlers(bool) {
app.registerUpgrade4_1(upgradeInfo)
app.registerUpgrade4_2(upgradeInfo)
app.registerUpgrade4_3(upgradeInfo)
app.registerUpgrade4_4(upgradeInfo)
}

// performs upgrade from v4.3 to v4.4
func (app *UmeeApp) registerUpgrade4_4(upgradeInfo upgradetypes.Plan) {
const planName = "v4.4"
app.UpgradeKeeper.SetUpgradeHandler(planName, onlyModuleMigrations(app, planName))
app.storeUpgrade(planName, upgradeInfo, storetypes.StoreUpgrades{
Added: []string{
incentive.ModuleName,
},
})
}

// performs upgrade from v4.2 to v4.3
Expand Down Expand Up @@ -97,7 +110,6 @@ func (app *UmeeApp) registerUpgrade4_3(upgradeInfo upgradetypes.Plan) {
icahosttypes.StoreKey,
},
})

}

// performs upgrade from v4.1 to v4.2
Expand Down
60 changes: 28 additions & 32 deletions proto/umee/incentive/v1/genesis.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package umeenetwork.umee.incentive.v1;
package umee.incentive.v1;

option go_package = "github.com/umee-network/umee/v4/x/incentive";

Expand All @@ -11,7 +11,7 @@ import "umee/incentive/v1/incentive.proto";
message GenesisState {
Params params = 1 [(gogoproto.nullable) = false];
uint32 next_program_id = 2;
uint64 last_rewards_time = 3;
int64 last_rewards_time = 3;
repeated RewardTracker reward_trackers = 4 [(gogoproto.nullable) = false];
repeated RewardAccumulator reward_accumulators = 5 [(gogoproto.nullable) = false];
repeated IncentiveProgram upcoming_programs = 6 [(gogoproto.nullable) = false];
Expand All @@ -21,59 +21,55 @@ message GenesisState {
repeated AccountUnbondings account_unbondings = 10 [(gogoproto.nullable) = false];
}

// TotalBond tracks the amount of coins of one uToken denomination bonded to a
// given reward tier by all accounts. Used by queries TotalBonded and TotalUnbonding.
message TotalBond {
uint32 tier = 1;
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
}

// Bond tracks the amount of coins of one uToken denomination bonded to a
// given reward tier by a single account.
// Bond tracks the amount of coins of one uToken denomination bonded
// by a single account.
message Bond {
string account = 1;
uint32 tier = 2;
cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false];
cosmos.base.v1beta1.Coin uToken = 2 [(gogoproto.nullable) = false];
}

// RewardTracker tracks the value of a given tier and lock denom's RewardAccumulator
// at the last time a specific account calculated pending rewards for it. When calculating
// RewardTracker tracks the value of a given lock denom's RewardAccumulator at the
// last time a specific account calculated pending rewards for it. When calculating
// available rewards, this value is used to determine the difference between the current
// RewardAccumulator for a tier and the last value at which the user updated bonds or claimed
// RewardAccumulator for a uToken and the last value at which the user updated bonds or claimed
// tokens. Their pending rewards increase by only the rewards accrued in that time period.
message RewardTracker {
string account = 1;
uint32 tier = 2;
string denom = 3;
repeated cosmos.base.v1beta1.DecCoin reward_tracker = 4 [
string account = 1;
string uToken = 2;
repeated cosmos.base.v1beta1.DecCoin rewards = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"
];
}

// RewardAccumulator is a global reward tracking struct that indicates the amount
// of rewards that a single unit of denom would have accumulated if it was bonded
// at a given tier since genesis.
// of rewards that a reference amount of a bonded uToken denom would have accumulated
// if it was bonded since genesis. To prevent rounding issues, the reference amount is
// 10^exponent of the uToken's smallest possible amount, generally matching the exponent
// of the associated base token registered with the leverage module.
message RewardAccumulator {
uint32 tier = 1;
string denom = 2;
repeated cosmos.base.v1beta1.DecCoin reward_tracker = 3 [
string uToken = 1;
repeated cosmos.base.v1beta1.DecCoin rewards = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"
];
uint32 exponent = 3;
}

// Unbonding is a structure that tracks an in-progress token unbonding.
// It tracks both its start time and end time, so that if the module's
// unbonding time changes, the unbonding can complete at the earlier of
// its original end time or its new one based on the new parameter.
message Unbonding {
uint64 end = 1;
cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false];
int64 start = 1;
int64 end = 2;
cosmos.base.v1beta1.Coin uToken = 3 [(gogoproto.nullable) = false];
}

// AccountUnbondings is a structure that is used to store all of an account's unbondings
// for a single bonded uToken denom and and unbonding tier in both KVStore and genesis state.
// for a single bonded uToken denom in both KVStore and genesis state.
message AccountUnbondings {
string account = 1;
string denom = 2;
uint32 tier = 3;
repeated Unbonding unbondings = 4 [(gogoproto.nullable) = false];
}
string uToken = 2;
repeated Unbonding unbondings = 3 [(gogoproto.nullable) = false];
}
46 changes: 11 additions & 35 deletions proto/umee/incentive/v1/incentive.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package umeenetwork.umee.incentive.v1;
package umee.incentive.v1;

import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";
Expand All @@ -10,43 +10,19 @@ option go_package = "github.com/umee-network/umee/v4/x/incentive";
message Params {
option (gogoproto.equal) = true;

// max_unbondings defines the maximum amount of concurrent unbondings an address can have
// on each unbonding tier of each bonded uToken denom.
// max_unbondings is the maximum amount of concurrent unbondings an address can have
// of each bonded uToken denom. Zero is interpreted as no limit.
uint32 max_unbondings = 1;

// unbonding_duration_long defines the unbonding duration (in seconds) of the long tier.
uint64 unbonding_duration_long = 2;
// unbonding_duration is the unbonding duration (in seconds).
int64 unbonding_duration = 2;

// unbonding_duration_middle defines the unbonding duration (in seconds) of the middle tier.
uint64 unbonding_duration_middle = 3;

// unbonding_duration_short defines the unbonding duration (in seconds) of the short tier.
uint64 unbonding_duration_short = 4;

// tier_weight_short defines the proportion of rewards which assets bonded
// in the short unbonding duration receive compared to what the same amount
// would receive bonded to the long tier.
// valid values: [0;1]
string tier_weight_short = 5 [
// emergency_unbond_fee is the portion of a bond that is paid when it is instantly
// released using MsgEmergencyUnbond. For example, 0.01 is a 1% fee. Ranges 0-1.
string emergency_unbond_fee = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

// tier_weight_middle defines the proportion of rewards which assets bonded
// in the middle unbonding duration receive compared to what the same amount
// would receive bonded to the long tier.
// valid values: [0;1]
string tier_weight_middle = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

// community_fund_address is the address from which all incentive programs
// proposed with "from_community_fund = true" will receive their funding.
// Since funds are withdrawn automatically when an incentive program passes
// governance, this account should always contain sufficient balance to
// cover incentive programs which are being voted upon.
string community_fund_address = 7;
}

// IncentiveProgram defines a liquidity mining incentive program on a single
Expand All @@ -62,13 +38,13 @@ message IncentiveProgram {
// start_time is the unix time (in seconds) at which the incentives begin.
// If a program is passed after its intended start time, its start time
// will be increased to the current time, with program duration unchanged.
uint64 start_time = 2;
int64 start_time = 2;

// duration is the length of the incentive program from start time to
// completion in seconds.
uint64 duration = 3;
int64 duration = 3;

// uToken is the incentivized uToken collateral. Suppliers who collateralize
// uToken is the incentivized uToken collateral denom. Suppliers who collateralize
// this asset then bond it to the incentive module are eligible for this program's
// rewards.
string uToken = 4;
Expand Down
Loading

0 comments on commit 81b86b1

Please sign in to comment.