update incentive spec (#982)

This commit is contained in:
Denali Marsh 2021-08-06 16:12:08 +02:00 committed by GitHub
parent b86cfc9f14
commit 2167b13430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 89 deletions

View File

@ -4,7 +4,7 @@ order: 1
# Concepts
This module presents an implementation of user incentives that are controlled by governance. When users take a certain action, for example opening a CDP, they become eligible for rewards. Rewards are __opt in__ meaning that users must submit a message before the claim deadline to claim their rewards. The goals and background of this module were subject of a previous Kava governance proposal, which can be found [here](https://ipfs.io/ipfs/QmSYedssC3nyQacDJmNcREtgmTPyaMx2JX7RNkMdAVkdkr/user-growth-fund-proposal.pdf)
This module presents an implementation of user incentives that are controlled by governance. When users take a certain action, for example opening a CDP, they become eligible for rewards. Rewards are **opt in** meaning that users must submit a message before the claim deadline to claim their rewards. The goals and background of this module were subject of a previous Kava governance proposal, which can be found [here](https://ipfs.io/ipfs/QmSYedssC3nyQacDJmNcREtgmTPyaMx2JX7RNkMdAVkdkr/user-growth-fund-proposal.pdf)
## General Reward Distribution
@ -42,4 +42,7 @@ The incentive module is responsible for distribution of KAVA tokens to users who
## SWP Token Distribution
TODO
The incentive module distributes the SWP token on the Kava blockchain. SWP tokens are distributed to two types of ecosystem participants:
1. Kava stakers - any address that stakes (delegates) KAVA tokens will be eligible to claim SWP tokens. For each delegator, SWP tokens are accumulated ratably based on the total number of kava tokens staked. For example, if a user stakes 1 million KAVA tokens and there are 100 million staked KAVA, that user will accumulate 1% of SWP tokens earmarked for stakers during the distribution period. Distribution periods are defined by a start date, an end date, and a number of SWP tokens that are distributed per second.
2. Liquidity providers - any address that provides liquidity to eligible Swap protocol pools will be eligible to claim SWP tokens. For each liquidity provider, SWP tokens are accumulated ratably based on the total amount of pool shares. For example, if a liquidity provider deposits "xyz" and "abc" tokens into the "abc:xyz" pool to receive 10 shares and the pool has 50 total shares, then that user will accumulate 20% of SWP tokens earmarked for liquidity providers of that pool during the distribution period. Distribution periods are defined by a start date, an end date, and a number of SWP tokens that are distributed per second.

View File

@ -11,12 +11,13 @@ order: 2
```go
// Params governance parameters for the incentive module
type Params struct {
USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"` // rewards for minting USDX
HardSupplyRewardPeriods MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"` // rewards for hard supply
HardBorrowRewardPeriods MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"` // rewards for hard borrow
HardDelegatorRewardPeriods RewardPeriods `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"` // rewards for kava delegators
ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"` // the available claim multipliers that determine who much rewards are paid out and how long rewards are locked for
ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"` // the time at which claims expire
USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"`
HardSupplyRewardPeriods MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"`
HardBorrowRewardPeriods MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"`
DelegatorRewardPeriods MultiRewardPeriods `json:"delegator_reward_periods" yaml:"delegator_reward_periods"`
SwapRewardPeriods MultiRewardPeriods `json:"swap_reward_periods" yaml:"swap_reward_periods"`
ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"`
ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"`
}
```
@ -24,7 +25,6 @@ type Params struct {
Each `RewardPeriod` defines a particular collateral for which rewards are eligible and the amount of rewards available.
```go
// RewardPeriod stores the state of an ongoing reward
type RewardPeriod struct {
Active bool `json:"active" yaml:"active"` // if the reward is active
@ -53,13 +53,18 @@ type MultiRewardPeriod struct {
```go
// GenesisState is the state that must be provided at genesis.
type GenesisState struct {
Params Params `json:"params" yaml:"params"` // governance parameters
USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"` // when USDX rewards were last accumulated
HardSupplyAccumulationTimes GenesisAccumulationTimes `json:"hard_supply_accumulation_times" yaml:"hard_supply_accumulation_times"` // when hard supply rewards were last accumulated
HardBorrowAccumulationTimes GenesisAccumulationTimes `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"` // when hard borrow rewards were last accumulated
HardDelegatorAccumulationTimes GenesisAccumulationTimes `json:"hard_delegator_accumulation_times" yaml:"hard_delegator_accumulation_times"` // when hard delegator rewards were last accumulated
USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` // USDX minting claims at genesis, if any
HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"` // Hard liquidity provider claims at genesis, if any
Params Params `json:"params" yaml:"params"`
USDXRewardState GenesisRewardState `json:"usdx_reward_state" yaml:"usdx_reward_state"`
HardSupplyRewardState GenesisRewardState `json:"hard_supply_reward_state" yaml:"hard_supply_reward_state"`
HardBorrowRewardState GenesisRewardState `json:"hard_borrow_reward_state" yaml:"hard_borrow_reward_state"`
DelegatorRewardState GenesisRewardState `json:"delegator_reward_state" yaml:"delegator_reward_state"`
SwapRewardState GenesisRewardState `json:"swap_reward_state" yaml:"swap_reward_state"`
USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"`
DelegatorClaims DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
SwapClaims SwapClaims `json:"swap_claims" yaml:"swap_claims"`
}
```
@ -69,33 +74,68 @@ For complete details for how items are stored, see [keys.go](../types/keys.go).
### Claim Creation
When users take incentivized actions, the `incentive` module will create or update a `Claim` object in the store, which represents the amount of rewards that the user is eligible to claim. The two defined claim objects are `USDXMintingClaims` and `HardLiquidityProviderClaims`:
When users take incentivized actions, the `incentive` module will create or update a `Claim` object in the store, which represents the amount of rewards that the user is eligible to claim. Each `Claim` object contains one or several RewardIndexes, which are used to calculate the amount of rewards a user can claim. There are four defined claim objects:
- `USDXMintingClaim`
- `HardLiquidityProviderClaim`
- `DelegatorClaim`
- `SwapClaim`
```go
// Claim is an interface for handling common claim actions
type Claim interface {
GetOwner() sdk.AccAddress
GetReward() sdk.Coin
GetType() string
}
// BaseClaim is a common type shared by all Claims
type BaseClaim struct {
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Reward sdk.Coin `json:"reward" yaml:"reward"`
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Reward sdk.Coin `json:"reward" yaml:"reward"`
}
// BaseMultiClaim is a common type shared by all Claims with multiple reward denoms
type BaseMultiClaim struct {
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Reward sdk.Coins `json:"reward" yaml:"reward"`
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Reward sdk.Coins `json:"reward" yaml:"reward"`
}
// RewardIndex stores reward accumulation information
type RewardIndex struct {
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
RewardFactor sdk.Dec `json:"reward_factor" yaml:"reward_factor"`
}
// MultiRewardIndex stores reward accumulation information on multiple reward types
type MultiRewardIndex struct {
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
RewardIndexes RewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
}
// USDXMintingClaim is for USDX minting rewards
type USDXMintingClaim struct {
BaseClaim `json:"base_claim" yaml:"base_claim"` // Base claim object
RewardIndexes RewardIndexes `json:"reward_indexes" yaml:"reward_indexes"` // indexes which are used to calculate the amount of rewards a user can claim
BaseClaim `json:"base_claim" yaml:"base_claim"`
RewardIndexes RewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
}
// HardLiquidityProviderClaim stores the hard liquidity provider rewards that can be claimed by owner
type HardLiquidityProviderClaim struct {
BaseMultiClaim `json:"base_claim" yaml:"base_claim"` // base claim object
SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"` // indexes which are used to calculate the amount of hard supply rewards a user can claim
BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"` // indexes which are used to calculate the amount of hard borrow rewards a user can claim
DelegatorRewardIndexes RewardIndexes `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"` // indexes which are used to calculate the amount of hard delegator rewards a user can claim
BaseMultiClaim `json:"base_claim" yaml:"base_claim"`
SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"`
BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"`
}
// DelegatorClaim stores delegation rewards that can be claimed by owner
type DelegatorClaim struct {
BaseMultiClaim `json:"base_claim" yaml:"base_claim"`
RewardIndexes MultiRewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
}
// SwapClaim stores the swap rewards that can be claimed by owner
type SwapClaim struct {
BaseMultiClaim `json:"base_claim" yaml:"base_claim"`
RewardIndexes MultiRewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
}
```

View File

@ -4,19 +4,34 @@ order: 3
# Messages
Users claim rewards using `MsgClaimUSDXMintingReward` and `MsgClaimHardReward` messages.
Users claim rewards using messages that correspond to each claim type.
```go
// MsgClaimUSDXMintingReward message type used to claim USDX minting rewards
type MsgClaimUSDXMintingReward struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
}
// MsgClaimHardReward message type used to claim Hard liquidity provider rewards
type MsgClaimHardReward struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
DenomsToClaim []string `json:"denoms_to_claim" yaml:"denoms_to_claim"`
}
// MsgClaimDelegatorReward message type used to claim delegator rewards
type MsgClaimDelegatorReward struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
DenomsToClaim []string `json:"denoms_to_claim" yaml:"denoms_to_claim"`
}
// MsgClaimSwapReward message type used to claim delegator rewards
type MsgClaimSwapReward struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"`
DenomsToClaim []string `json:"denoms_to_claim" yaml:"denoms_to_claim"`
}
```

View File

@ -6,40 +6,40 @@ order: 5
The incentive module contains the following parameters:
| Key | Type | Example | Description |
|----------------------------|--------------------|------------------------|--------------------------------------------------|
| USDXMintingRewardPeriods | RewardPeriods | [{see below}] | USDX minting reward periods |
| HardSupplyRewardPeriods | MultiRewardPeriods | [{see below}] | Hard supply reward periods |
| HardBorrowRewardPeriods | MultiRewardPeriods | [{see below}] | Hard borrow reward periods |
| HardDelegatorRewardPeriods | RewardPeriods | [{see below}] | Hard delegator reward periods |
| ClaimMultipliers | Multipliers | [{see below}] | Multipliers applied when rewards are claimed |
| ClaimMultipliers | Time | "2025-12-02T14:00:00Z" | Time when reward claiming ends |
| Key | Type | Example | Description |
| ------------------------ | ------------------ | ---------------------- | -------------------------------------------- |
| USDXMintingRewardPeriods | RewardPeriods | [{see below}] | USDX minting reward periods |
| HardSupplyRewardPeriods | MultiRewardPeriods | [{see below}] | Hard supply reward periods |
| HardBorrowRewardPeriods | MultiRewardPeriods | [{see below}] | Hard borrow reward periods |
| DelegatorRewardPeriods | MultiRewardPeriods | [{see below}] | Delegator reward periods |
| SwapRewardPeriods | MultiRewardPeriods | [{see below}] | Swap reward periods |
| ClaimMultipliers | Multipliers | [{see below}] | Multipliers applied when rewards are claimed |
| ClaimMultipliers | Time | "2025-12-02T14:00:00Z" | Time when reward claiming ends |
Each `RewardPeriod` has the following parameters
| Key | Type | Example | Description |
|------------------|--------------------|------------------------------------|------------------------------------------------------------------|
| Active | bool | "true | boolean for if rewards for this collateral are active |
| CollateralType | string | "bnb-a" | the collateral for which rewards are eligible |
| Start | Time | "2020-12-02T14:00:00Z" | the time at which rewards start |
| End | Time | "2023-12-02T14:00:00Z" | the time at which rewards end |
| AvailableRewards | object (coin) | `{"denom":"hard","amount":"1000"}` | the rewards available per reward period |
| Key | Type | Example | Description |
| ---------------- | ------------- | ---------------------------------- | ----------------------------------------------------- |
| Active | bool | "true | boolean for if rewards for this collateral are active |
| CollateralType | string | "bnb-a" | the collateral for which rewards are eligible |
| Start | Time | "2020-12-02T14:00:00Z" | the time at which rewards start |
| End | Time | "2023-12-02T14:00:00Z" | the time at which rewards end |
| AvailableRewards | object (coin) | `{"denom":"hard","amount":"1000"}` | the rewards available per reward period |
Each `MultiRewardPeriod` has the following parameters
| Key | Type | Example | Description |
|------------------|--------------------|-------------------------------------------------------------------------|------------------------------------------------------------------|
| Active | bool | "true | boolean for if rewards for this collateral are active |
| CollateralType | string | "bnb-a" | the collateral for which rewards are eligible |
| Start | Time | "2020-12-02T14:00:00Z" | the time at which rewards start |
| End | Time | "2023-12-02T14:00:00Z" | the time at which rewards end |
| AvailableRewards | array (coins) | `[{"denom":"hard","amount":"1000"}, {"denom":"ukava","amount":"1000"}]` | the rewards available per reward period |
| Key | Type | Example | Description |
| ---------------- | ------------- | ----------------------------------------------------------------------- | ----------------------------------------------------- |
| Active | bool | "true | boolean for if rewards for this collateral are active |
| CollateralType | string | "bnb-a" | the collateral for which rewards are eligible |
| Start | Time | "2020-12-02T14:00:00Z" | the time at which rewards start |
| End | Time | "2023-12-02T14:00:00Z" | the time at which rewards end |
| AvailableRewards | array (coins) | `[{"denom":"hard","amount":"1000"}, {"denom":"ukava","amount":"1000"}]` | the rewards available per reward period |
Each `Multiplier` has the following parameters:
| Key | Type | Example | Description |
|-----------------------|--------------------|--------------------------|-----------------------------------------------------------------|
| Name | string | "large" | the unique name of the reward multiplier |
| MonthsLockup | int | "6" | number of months tokens with this multiplier are locked |
| Factor | Dec | "0.5" | the scaling factor for tokens claimed with this multiplier |
| Key | Type | Example | Description |
| ------------ | ------ | ------- | ---------------------------------------------------------- |
| Name | string | "large" | the unique name of the reward multiplier |
| MonthsLockup | int | "6" | number of months tokens with this multiplier are locked |
| Factor | Dec | "0.5" | the scaling factor for tokens claimed with this multiplier |

View File

@ -6,9 +6,10 @@ order: 6
This module implements the `Hooks` interface for the following modules:
* cdp
* hard
* staking (defined in cosmos-sdk)
- cdp
- hard
- swap
- staking (defined in cosmos-sdk)
CDP module hooks manage the creation and synchronization of USDX minting incentives.
@ -110,3 +111,17 @@ func (h Hooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress)
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
}
```
Swap module hooks manage the creation and synchronization of Swap protocol liquidity provider rewards.
```go
// ------------------- Swap Module Hooks -------------------
func (h Hooks) AfterPoolDepositCreated(ctx sdk.Context, poolID string, depositor sdk.AccAddress, _ sdk.Int) {
h.k.InitializeSwapReward(ctx, poolID, depositor)
}
func (h Hooks) BeforePoolDepositModified(ctx sdk.Context, poolID string, depositor sdk.AccAddress, sharesOwned sdk.Int) {
h.k.SynchronizeSwapReward(ctx, poolID, depositor, sharesOwned)
}
```

View File

@ -4,35 +4,28 @@ order: 7
# Begin Block
At the start of each block, rewards are accumulated for each reward time. Accumulation refers to computing the total amount of rewards that have accumulated since the previous block and updating a global accumulator value such that whenever a `Claim` object is accessed, it is synchronized with the latest global state. This ensures that all rewards are accurately accounted for without having to iterate over each claim object in the begin blocker
At the start of each block, rewards are accumulated for each reward time. Accumulation refers to computing the total amount of rewards that have accumulated since the previous block and updating a global accumulator value such that whenever a `Claim` object is accessed, it is synchronized with the latest global state. This ensures that all rewards are accurately accounted for without having to iterate over each claim object in the begin blocker.
```go
// BeginBlocker runs at the start of every block
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
params := k.GetParams(ctx)
for _, rp := range params.USDXMintingRewardPeriods {
err := k.AccumulateUSDXMintingRewards(ctx, rp)
if err != nil {
panic(err)
}
}
for _, rp := range params.HardSupplyRewardPeriods {
err := k.AccumulateHardSupplyRewards(ctx, rp)
if err != nil {
panic(err)
}
}
for _, rp := range params.HardBorrowRewardPeriods {
err := k.AccumulateHardBorrowRewards(ctx, rp)
if err != nil {
panic(err)
}
}
for _, rp := range params.HardDelegatorRewardPeriods {
err := k.AccumulateHardDelegatorRewards(ctx, rp)
if err != nil {
panic(err)
}
}
params := k.GetParams(ctx)
for _, rp := range params.USDXMintingRewardPeriods {
k.AccumulateUSDXMintingRewards(ctx, rp)
}
for _, rp := range params.HardSupplyRewardPeriods {
k.AccumulateHardSupplyRewards(ctx, rp)
}
for _, rp := range params.HardBorrowRewardPeriods {
k.AccumulateHardBorrowRewards(ctx, rp)
}
for _, rp := range params.DelegatorRewardPeriods {
k.AccumulateDelegatorRewards(ctx, rp)
}
for _, rp := range params.SwapRewardPeriods {
k.AccumulateSwapRewards(ctx, rp)
}
}
```