feat: add swap incentives (#1006)

* feat: add swap incentives

* add tests that verify swp annual rewards

* remove unused testdata file

* add test for swp delegator rewards
This commit is contained in:
Kevin Davis 2021-08-19 12:33:40 -06:00 committed by GitHub
parent 22843cd3df
commit 3d65ba7caa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 8 deletions

View File

@ -2,6 +2,7 @@ package v0_15
import (
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -60,8 +61,15 @@ func Incentive(cdc *codec.Codec, incentiveGS v0_14incentive.GenesisState, cdps v
delegatorRewardPeriods = append(delegatorRewardPeriods, delegatorRewardPeriod)
}
// TODO: finalize swap reward pool IDs, rewards per second, start/end times. Should swap rewards start active?
swapRewardPeriods := v0_15incentive.MultiRewardPeriods{}
swapRewardPeriods := v0_15incentive.MultiRewardPeriods{
v0_15incentive.NewMultiRewardPeriod(true, "bnb:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(47565)))),
v0_15incentive.NewMultiRewardPeriod(true, "btcb:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(47565)))),
v0_15incentive.NewMultiRewardPeriod(true, "busd:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(158549)))),
v0_15incentive.NewMultiRewardPeriod(true, "hard:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(47565)))),
v0_15incentive.NewMultiRewardPeriod(true, "swp:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(190259)))),
v0_15incentive.NewMultiRewardPeriod(true, "ukava:usdx", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(221969)))),
v0_15incentive.NewMultiRewardPeriod(true, "usdx:xrpb", GenesisTime, GenesisTime.Add(time.Hour*24*365*4), sdk.NewCoins(sdk.NewCoin("swp", sdk.NewInt(47565)))),
}
// Build new params from migrated values
params := v0_15incentive.NewParams(

View File

@ -25,12 +25,10 @@ import (
)
var (
GenesisTime = time.Date(2021, 8, 30, 15, 0, 0, 0, time.UTC) // 1630335600
ChainID = "kava-8"
// TODO: update SWP reward per second amount before production
// TODO: update SWP reward per second amount before production
SwpDelegatorRewardsPerSecond = sdk.NewCoin("swp", sdk.OneInt())
SwpLiquidityProviderRewardsPerSecond = sdk.NewCoin("swp", sdk.OneInt())
// TODO: update GenesisTime and chain-id for kava-8 launch
GenesisTime = time.Date(2021, 8, 30, 15, 0, 0, 0, time.UTC)
ChainID = "kava-8"
SwpDelegatorRewardsPerSecond = sdk.NewCoin("swp", sdk.NewInt(198186))
)
// Migrate translates a genesis file from kava v0.14 format to kava v0.15 format

View File

@ -24,6 +24,7 @@ import (
"github.com/kava-labs/kava/x/hard"
v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
"github.com/kava-labs/kava/x/swap"
)
func TestMain(m *testing.M) {
@ -204,6 +205,110 @@ func TestIncentive_Full_TotalRewards(t *testing.T) {
require.Equal(t, oldTotalRewards.Add(additionalRewards...), newTotalRewards)
}
func TestIncentive_SwpLPRewards(t *testing.T) {
expectedAnnualRewards := sdk.NewCoin("swp", sdk.NewInt(24000000e6))
expectedAnnualRewardsMap := map[string]sdk.Coin{
"ukava:usdx": sdk.NewCoin("swp", sdk.NewInt(7000000e6)),
"swp:usdx": sdk.NewCoin("swp", sdk.NewInt(6000000e6)),
"busd:usdx": sdk.NewCoin("swp", sdk.NewInt(5000000e6)),
"bnb:usdx": sdk.NewCoin("swp", sdk.NewInt(1500000e6)),
"btcb:usdx": sdk.NewCoin("swp", sdk.NewInt(1500000e6)),
"hard:usdx": sdk.NewCoin("swp", sdk.NewInt(1500000e6)),
"usdx:xrpb": sdk.NewCoin("swp", sdk.NewInt(1500000e6)),
}
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-incentive-state.json"))
require.NoError(t, err)
var oldIncentiveGenState v0_14incentive.GenesisState
cdc := app.MakeCodec()
require.NotPanics(t, func() {
cdc.MustUnmarshalJSON(bz, &oldIncentiveGenState)
})
secondsPerYear := sdk.NewInt(31536000)
newGenState := v0_15incentive.GenesisState{}
require.NotPanics(t, func() {
newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{})
})
err = newGenState.Validate()
require.NoError(t, err)
actualAnnualRewards := sdk.NewCoin("swp", sdk.ZeroInt())
for _, rp := range newGenState.Params.SwapRewardPeriods {
expected, found := expectedAnnualRewardsMap[rp.CollateralType]
require.True(t, found)
require.True(t, len(rp.RewardsPerSecond) == 1)
require.True(t, rp.RewardsPerSecond[0].Denom == "swp")
annualRewardsAmount := rp.RewardsPerSecond[0].Amount.ToDec().Mul(secondsPerYear.ToDec()).RoundInt()
annualRewardsCoin := sdk.NewCoin("swp", annualRewardsAmount)
actualAnnualRewards = actualAnnualRewards.Add(annualRewardsCoin)
// allow for +- 0.1% deviation for targeted annual rewards
inRange := assertRewardsWithinRange(expected, annualRewardsCoin, sdk.MustNewDecFromStr("0.001"))
require.True(t, inRange, fmt.Sprintf("expected annual rewards: %s, actual %s", expected, annualRewardsCoin))
}
inRange := assertRewardsWithinRange(expectedAnnualRewards, actualAnnualRewards, sdk.MustNewDecFromStr("0.001"))
require.True(t, inRange, fmt.Sprintf("expected annual rewards: %s, actual %s", expectedAnnualRewards, actualAnnualRewards))
}
func TestIncentive_SwpDelegatorRewards(t *testing.T) {
expectedAnnualRewards := sdk.NewCoin("swp", sdk.NewInt(6250000e6))
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-incentive-state.json"))
require.NoError(t, err)
var oldIncentiveGenState v0_14incentive.GenesisState
cdc := app.MakeCodec()
require.NotPanics(t, func() {
cdc.MustUnmarshalJSON(bz, &oldIncentiveGenState)
})
secondsPerYear := sdk.NewInt(31536000)
newGenState := v0_15incentive.GenesisState{}
require.NotPanics(t, func() {
newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{})
})
for _, rp := range newGenState.Params.DelegatorRewardPeriods {
swpRewardsPerSecondDelegators := sdk.NewCoin("swp", rp.RewardsPerSecond.AmountOf("swp"))
annualRewardsAmount := swpRewardsPerSecondDelegators.Amount.ToDec().Mul(secondsPerYear.ToDec()).RoundInt()
annualRewardsCoin := sdk.NewCoin("swp", annualRewardsAmount)
inRange := assertRewardsWithinRange(expectedAnnualRewards, annualRewardsCoin, sdk.MustNewDecFromStr("0.001"))
require.True(t, inRange, fmt.Sprintf("expected annual rewards: %s, actual %s", expectedAnnualRewards, annualRewardsCoin))
}
}
func TestIncentive_SwpPoolsValid(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-incentive-state.json"))
require.NoError(t, err)
appState := genutil.AppMap{v0_14incentive.ModuleName: bz, v0_15cdp.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15cdp.DefaultGenesisState())}
MigrateAppState(appState)
cdc := app.MakeCodec()
var swapGS swap.GenesisState
cdc.MustUnmarshalJSON(appState[swap.ModuleName], &swapGS)
var incentiveGS v0_15incentive.GenesisState
cdc.MustUnmarshalJSON(appState[v0_15incentive.ModuleName], &incentiveGS)
for _, rp := range incentiveGS.Params.SwapRewardPeriods {
found := false
for _, pool := range swapGS.Params.AllowedPools {
if pool.Name() == rp.CollateralType {
found = true
}
}
require.True(t, found, fmt.Sprintf("incentivized pool %s not found in swap genesis state", rp.CollateralType))
}
}
func assertRewardsWithinRange(expected, actual sdk.Coin, tolerance sdk.Dec) bool {
upper := expected.Amount.ToDec().Mul(sdk.OneDec().Add(tolerance))
lower := expected.Amount.ToDec().Mul(sdk.OneDec().Sub(tolerance))
if actual.Amount.ToDec().GTE(lower) && actual.Amount.ToDec().LTE(upper) {
return true
}
return false
}
func TestSwap(t *testing.T) {
swapGS := Swap()
err := swapGS.Validate()