mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-25 15:55:18 +00:00
Incentive migration state fixes: USDX Minting (#998)
* minor migration refactor * overwrite usdx claims with latest reward indexes * add missing usdx claims in migration * add script to calculate missing usdx rewards * generate missing rewards using preliminary data * add missing usdx rewards in migration * update missing rewards data to use correct genesis * test rewards were not decreased * add tests for missing reward calculations * clarify function names * test to assert total new rewards are as expected * remove unecessary todo item
This commit is contained in:
parent
cac7398120
commit
22843cd3df
9
migrate/v0_15/generate-test-incentive-data.sh
Executable file
9
migrate/v0_15/generate-test-incentive-data.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Usage: ./generate-test-incentive-data.sh genesis.json"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq < "$1" -c '{"incentive": .app_state.incentive, "cdp": .app_state.cdp }' > testdata/kava-7-test-incentive-state.json
|
@ -1,14 +1,18 @@
|
||||
package v0_15
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
|
||||
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
// Incentive migrates from a v0.14 incentive genesis state to a v0.15 incentive genesis state
|
||||
func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisState {
|
||||
func Incentive(cdc *codec.Codec, incentiveGS v0_14incentive.GenesisState, cdps v0_15cdp.CDPs) v0_15incentive.GenesisState {
|
||||
// Migrate params
|
||||
claimMultipliers := v0_15incentive.Multipliers{}
|
||||
for _, m := range incentiveGS.Params.ClaimMultipliers {
|
||||
@ -78,12 +82,13 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt
|
||||
swapGenesisRewardState := v0_15incentive.DefaultGenesisRewardState // There is no previous swap rewards so accumulation starts at genesis time.
|
||||
|
||||
// Migrate USDX minting claims
|
||||
usdxMintingClaims := v0_15incentive.USDXMintingClaims{}
|
||||
for _, claim := range incentiveGS.USDXMintingClaims {
|
||||
rewardIndexes := migrateRewardIndexes(claim.RewardIndexes)
|
||||
usdxMintingClaim := v0_15incentive.NewUSDXMintingClaim(claim.Owner, claim.Reward, rewardIndexes)
|
||||
usdxMintingClaims = append(usdxMintingClaims, usdxMintingClaim)
|
||||
}
|
||||
usdxMintingClaims := migrateUSDXMintingClaims(incentiveGS.USDXMintingClaims)
|
||||
usdxMintingFormattedIndexes := convertRewardIndexesToUSDXMintingIndexes(usdxGenesisRewardState.MultiRewardIndexes)
|
||||
usdxMintingClaims = replaceUSDXClaimIndexes(usdxMintingClaims, usdxMintingFormattedIndexes)
|
||||
usdxMintingClaims = ensureAllCDPsHaveClaims(usdxMintingClaims, cdps, usdxMintingFormattedIndexes)
|
||||
var missedRewards map[string]sdk.Coin
|
||||
cdc.MustUnmarshalJSON([]byte(missedUSDXMintingRewards), &missedRewards)
|
||||
usdxMintingClaims = addRewards(usdxMintingClaims, missedRewards)
|
||||
|
||||
// Migrate Hard protocol claims (includes creating new Delegator claims)
|
||||
hardClaims := v0_15incentive.HardLiquidityProviderClaims{}
|
||||
@ -135,6 +140,83 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt
|
||||
)
|
||||
}
|
||||
|
||||
// migrateUSDXMintingClaims converts the a slice of v0.14 USDX minting claims into v0.15 USDX minting claims.
|
||||
// As both types are the same underneath, this just converts types and does no other modification.
|
||||
func migrateUSDXMintingClaims(oldClaims v0_14incentive.USDXMintingClaims) v0_15incentive.USDXMintingClaims {
|
||||
newClaims := v0_15incentive.USDXMintingClaims{}
|
||||
for _, oldClaim := range oldClaims {
|
||||
rewardIndexes := migrateRewardIndexes(oldClaim.RewardIndexes)
|
||||
usdxMintingClaim := v0_15incentive.NewUSDXMintingClaim(oldClaim.Owner, oldClaim.Reward, rewardIndexes)
|
||||
newClaims = append(newClaims, usdxMintingClaim)
|
||||
}
|
||||
return newClaims
|
||||
}
|
||||
|
||||
// replaceUSDXClaimIndexes overwrites the reward indexes in all the claims with the current global indexes.
|
||||
func replaceUSDXClaimIndexes(claims v0_15incentive.USDXMintingClaims, globalIndexes v0_15incentive.RewardIndexes) v0_15incentive.USDXMintingClaims {
|
||||
var amendedClaims v0_15incentive.USDXMintingClaims
|
||||
for _, claim := range claims {
|
||||
claim.RewardIndexes = globalIndexes
|
||||
amendedClaims = append(amendedClaims, claim)
|
||||
}
|
||||
return amendedClaims
|
||||
}
|
||||
|
||||
// convertRewardIndexesToUSDXMintingIndexes converts a genesis reward indexes into the format used within usdx minting claims.
|
||||
func convertRewardIndexesToUSDXMintingIndexes(mris v0_15incentive.MultiRewardIndexes) v0_15incentive.RewardIndexes {
|
||||
var newIndexes v0_15incentive.RewardIndexes
|
||||
for _, mri := range mris {
|
||||
factor, found := mri.RewardIndexes.Get(v0_15incentive.USDXMintingRewardDenom)
|
||||
if !found {
|
||||
panic(fmt.Sprintf("found global usdx minting reward index without denom '%s': %s", v0_15incentive.USDXMintingRewardDenom, mri))
|
||||
}
|
||||
newIndexes = newIndexes.With(mri.CollateralType, factor)
|
||||
}
|
||||
return newIndexes
|
||||
}
|
||||
|
||||
// ensureAllCDPsHaveClaims ensures that there is a claim for every cdp in the provided list.
|
||||
// It uses the provided global indexes as the indexes for any added claim.
|
||||
func ensureAllCDPsHaveClaims(newClaims v0_15incentive.USDXMintingClaims, cdps v0_15cdp.CDPs, globalIndexes v0_15incentive.RewardIndexes) v0_15incentive.USDXMintingClaims {
|
||||
for _, cdp := range cdps {
|
||||
|
||||
claimFound := false
|
||||
for _, claim := range newClaims {
|
||||
if claim.Owner.Equals(cdp.Owner) {
|
||||
claimFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !claimFound {
|
||||
|
||||
claim := v0_15incentive.NewUSDXMintingClaim(
|
||||
cdp.Owner,
|
||||
sdk.NewCoin(v0_15incentive.USDXMintingRewardDenom, sdk.ZeroInt()),
|
||||
globalIndexes,
|
||||
)
|
||||
newClaims = append(newClaims, claim)
|
||||
}
|
||||
|
||||
}
|
||||
return newClaims
|
||||
}
|
||||
|
||||
// addRewards adds some coins to a list of claims according to a map of address: coin.
|
||||
// It panics if any coin denom doesn't match the denom in the claim.
|
||||
func addRewards(newClaims v0_15incentive.USDXMintingClaims, rewards map[string]sdk.Coin) v0_15incentive.USDXMintingClaims {
|
||||
|
||||
var amendedClaims v0_15incentive.USDXMintingClaims
|
||||
for _, claim := range newClaims {
|
||||
r, found := rewards[claim.Owner.String()]
|
||||
if found {
|
||||
claim.Reward = claim.Reward.Add(r)
|
||||
}
|
||||
amendedClaims = append(amendedClaims, claim)
|
||||
}
|
||||
return amendedClaims
|
||||
}
|
||||
|
||||
func migrateMultiRewardPeriods(oldPeriods v0_14incentive.MultiRewardPeriods) v0_15incentive.MultiRewardPeriods {
|
||||
newPeriods := v0_15incentive.MultiRewardPeriods{}
|
||||
for _, rp := range oldPeriods {
|
||||
|
184
migrate/v0_15/incentive_test.go
Normal file
184
migrate/v0_15/incentive_test.go
Normal file
@ -0,0 +1,184 @@
|
||||
package v0_15
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
"github.com/kava-labs/kava/x/incentive"
|
||||
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
// d parses a string into an sdk.Dec type.
|
||||
// It is an alias for sdk.MustNewDecFromStr.
|
||||
var d = sdk.MustNewDecFromStr
|
||||
|
||||
func TestReplaceUSDXClaimIndexes(t *testing.T) {
|
||||
claims := incentive.USDXMintingClaims{
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 1e9),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.1")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address2"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.2")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address3"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{},
|
||||
),
|
||||
}
|
||||
|
||||
globalIndexes := incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.5")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.8")},
|
||||
}
|
||||
|
||||
syncedClaims := replaceUSDXClaimIndexes(claims, globalIndexes)
|
||||
|
||||
for i, claim := range syncedClaims {
|
||||
// check fields are unchanged
|
||||
require.Equal(t, claim.Owner, claims[i].Owner)
|
||||
require.Equal(t, claim.Reward, claims[i].Reward)
|
||||
// except for indexes which have been overwritten
|
||||
require.Equal(t, globalIndexes, claim.RewardIndexes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureAllCDPsHaveClaims(t *testing.T) {
|
||||
claims := incentive.USDXMintingClaims{
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 1e9),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.1")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address2"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.2")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address3"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{},
|
||||
),
|
||||
}
|
||||
|
||||
cdps := v0_15cdp.CDPs{
|
||||
{Owner: sdk.AccAddress("address4")}, // don't need anything more than owner for this test
|
||||
{Owner: sdk.AccAddress("address1")}, // there can be several cdps of different types with same owner
|
||||
{Owner: sdk.AccAddress("address1")},
|
||||
{Owner: sdk.AccAddress("address1")},
|
||||
{Owner: sdk.AccAddress("address2")},
|
||||
}
|
||||
|
||||
globalIndexes := incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.5")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.8")},
|
||||
}
|
||||
|
||||
expectedClaims := incentive.USDXMintingClaims{
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 1e9),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.1")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address2"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.2")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address3"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address4"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.5")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.8")},
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
require.Equal(t, expectedClaims, ensureAllCDPsHaveClaims(claims, cdps, globalIndexes))
|
||||
}
|
||||
|
||||
func TestAddRewards(t *testing.T) {
|
||||
claims := v0_15incentive.USDXMintingClaims{
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 1e9),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.1")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address2"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.2")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address3"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{},
|
||||
),
|
||||
}
|
||||
|
||||
rewards := map[string]sdk.Coin{
|
||||
sdk.AccAddress("address1").String(): sdk.NewInt64Coin(v0_15incentive.USDXMintingRewardDenom, 1e9),
|
||||
sdk.AccAddress("address3").String(): sdk.NewInt64Coin(v0_15incentive.USDXMintingRewardDenom, 3e9),
|
||||
sdk.AccAddress("address4").String(): sdk.NewInt64Coin(v0_15incentive.USDXMintingRewardDenom, 1e6),
|
||||
}
|
||||
|
||||
expectedClaims := v0_15incentive.USDXMintingClaims{
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 2e9),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0.1")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address2"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 0),
|
||||
incentive.RewardIndexes{
|
||||
{CollateralType: "bnb-a", RewardFactor: d("0")},
|
||||
{CollateralType: "xrpb-a", RewardFactor: d("0.2")},
|
||||
},
|
||||
),
|
||||
incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address3"),
|
||||
sdk.NewInt64Coin(incentive.USDXMintingRewardDenom, 3e9),
|
||||
incentive.RewardIndexes{},
|
||||
),
|
||||
}
|
||||
|
||||
amendedClaims := addRewards(claims, rewards)
|
||||
require.Equal(t, expectedClaims, amendedClaims)
|
||||
}
|
@ -14,6 +14,7 @@ import (
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
|
||||
v0_15committee "github.com/kava-labs/kava/x/committee/types"
|
||||
v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
|
||||
@ -78,7 +79,12 @@ func MigrateAppState(v0_14AppState genutil.AppMap) {
|
||||
var incentiveGenState v0_14incentive.GenesisState
|
||||
v0_14Codec.MustUnmarshalJSON(v0_14AppState[v0_14incentive.ModuleName], &incentiveGenState)
|
||||
delete(v0_14AppState, v0_14incentive.ModuleName)
|
||||
v0_14AppState[v0_15incentive.ModuleName] = v0_15Codec.MustMarshalJSON(Incentive(incentiveGenState))
|
||||
|
||||
// unmarshal all cdps using v0_15 types as there has been no changes since v0_14
|
||||
var cdpGenState v0_15cdp.GenesisState
|
||||
v0_15Codec.MustUnmarshalJSON(v0_14AppState[v0_15cdp.ModuleName], &cdpGenState)
|
||||
|
||||
v0_14AppState[v0_15incentive.ModuleName] = v0_15Codec.MustMarshalJSON(Incentive(v0_15Codec, incentiveGenState, cdpGenState.CDPs))
|
||||
}
|
||||
|
||||
// Migrate commmittee app state
|
||||
|
@ -13,11 +13,12 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
|
||||
v0_15committee "github.com/kava-labs/kava/x/committee/types"
|
||||
"github.com/kava-labs/kava/x/hard"
|
||||
@ -63,40 +64,144 @@ func TestCommittee(t *testing.T) {
|
||||
require.Equal(t, len(oldSPCP.AllowedMarkets), len(newSPCP.AllowedMarkets))
|
||||
require.Equal(t, len(oldSPCP.AllowedMoneyMarkets), len(newSPCP.AllowedMoneyMarkets))
|
||||
}
|
||||
func TestIncentive_MainnetState(t *testing.T) {
|
||||
// TODO add copy of mainnet state to json
|
||||
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-incentive-state.json"))
|
||||
|
||||
func TestIncentive_Full(t *testing.T) {
|
||||
t.Skip() // skip to avoid having to commit a large genesis file to the repo
|
||||
|
||||
genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "genesis.json"))
|
||||
require.NoError(t, err)
|
||||
|
||||
cdc := makeV014Codec()
|
||||
|
||||
var oldState genutil.AppMap
|
||||
cdc.MustUnmarshalJSON(genDoc.AppState, &oldState)
|
||||
|
||||
var oldIncentiveGenState v0_14incentive.GenesisState
|
||||
cdc := app.MakeCodec()
|
||||
require.NotPanics(t, func() {
|
||||
cdc.MustUnmarshalJSON(bz, &oldIncentiveGenState)
|
||||
})
|
||||
cdc.MustUnmarshalJSON(oldState[v0_14incentive.ModuleName], &oldIncentiveGenState)
|
||||
|
||||
newGenState := v0_15incentive.GenesisState{}
|
||||
require.NotPanics(t, func() {
|
||||
newGenState = Incentive(oldIncentiveGenState)
|
||||
})
|
||||
err = newGenState.Validate()
|
||||
require.NoError(t, err)
|
||||
var oldCDPGenState v0_15cdp.GenesisState
|
||||
cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState)
|
||||
|
||||
newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs)
|
||||
require.NoError(t, newGenState.Validate())
|
||||
|
||||
// TODO check params, indexes, and accumulation times
|
||||
|
||||
// Ensure the usdx claim indexes match global
|
||||
globalIndexes := newGenState.USDXRewardState.MultiRewardIndexes
|
||||
for _, claim := range newGenState.USDXMintingClaims {
|
||||
|
||||
for _, globalIndex := range globalIndexes {
|
||||
expectedFactor, found := globalIndex.RewardIndexes.Get(v0_15incentive.USDXMintingRewardDenom)
|
||||
require.True(t, found)
|
||||
|
||||
factor, found := claim.RewardIndexes.Get(globalIndex.CollateralType)
|
||||
require.True(t, found)
|
||||
|
||||
require.Equal(t, expectedFactor, factor)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure there is a usdx claim for every cdp
|
||||
for _, cdp := range oldCDPGenState.CDPs {
|
||||
numClaims := 0
|
||||
for _, claim := range newGenState.USDXMintingClaims {
|
||||
if cdp.Owner.Equals(claim.Owner) {
|
||||
numClaims++
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, numClaims, "cdp '%s' has invalid number of claims '%d'", cdp.Owner, numClaims)
|
||||
|
||||
// also check cdp indexes are valid
|
||||
require.True(t, cdp.InterestFactor.GTE(sdk.OneDec()), "found cdp with interest factor < 1")
|
||||
}
|
||||
|
||||
// Check reward amounts
|
||||
for _, claim := range newGenState.USDXMintingClaims {
|
||||
|
||||
// check a few high value accounts
|
||||
switch claim.Owner.String() {
|
||||
// check reward is: additional reward + existing unclaimed reward
|
||||
// note, non zero unclaimed rewards could change if the user submits a claim tx before launch
|
||||
case "kava1k8lymw58tduy9gm6jkt04ddkjd83nf7sm8xthl":
|
||||
require.Equal(t, sdk.NewInt(370982556999+0), claim.Reward.Amount)
|
||||
case "kava1p3ucd3ptpw902fluyjzhq3ffgq4ntddaysyq8h":
|
||||
require.Equal(t, sdk.NewInt(77550672285+16960713469), claim.Reward.Amount)
|
||||
case "kava1qe6ahdnhnfugle29054d8uqg7fa44ryx934yc6":
|
||||
require.Equal(t, sdk.NewInt(40874651319+0), claim.Reward.Amount)
|
||||
case "kava12h6pq2xqzgtxttrzg7q2rplsyxtv2dc5gwh8rl":
|
||||
require.Equal(t, sdk.NewInt(30867752254+0), claim.Reward.Amount)
|
||||
case "kava10hczxv0p3eadcwgt5u79yhahsyuw98u26qan50":
|
||||
require.Equal(t, sdk.NewInt(22429344254+0), claim.Reward.Amount)
|
||||
case "kava15wyjwhj6zh79m7adm69pwl3nsq9z8gs9ezs4k7":
|
||||
require.Equal(t, sdk.NewInt(10252596901+0), claim.Reward.Amount)
|
||||
case "kava1yg4840l77dfs5zqflldhut27en2mhvvc8vj93x":
|
||||
require.Equal(t, sdk.NewInt(9898765520+0), claim.Reward.Amount)
|
||||
case "kava1x242qk6jf2rv23ruvk6fmxp97gg2y75a9r2caq":
|
||||
require.Equal(t, sdk.NewInt(7761701231+0), claim.Reward.Amount)
|
||||
case "kava1tstf3u4cw7u4xyu7wxdrnmrpvvmfamq3twcj7f":
|
||||
require.Equal(t, sdk.NewInt(2466900572+0), claim.Reward.Amount)
|
||||
}
|
||||
|
||||
// check no rewards have been reduced
|
||||
for _, oldClaim := range oldIncentiveGenState.USDXMintingClaims {
|
||||
if oldClaim.Owner.Equals(claim.Owner) {
|
||||
require.Truef(t, claim.Reward.IsGTE(oldClaim.Reward), "found claim with reduced rewards, old %s, new %s", oldClaim, claim)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require.Equal(t, len(oldIncentiveGenState.USDXMintingClaims), len(newGenState.USDXMintingClaims))
|
||||
require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.HardLiquidityProviderClaims))
|
||||
// 1 new DelegatorClaim should have been created for each existing HardLiquidityProviderClaim
|
||||
require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.DelegatorClaims))
|
||||
}
|
||||
|
||||
func TestIncentive(t *testing.T) {
|
||||
bz, err := ioutil.ReadFile(filepath.Join("testdata", "v0_14-incentive-state.json"))
|
||||
require.NoError(t, err)
|
||||
appState := genutil.AppMap{v0_14incentive.ModuleName: bz}
|
||||
func TestIncentive_Full_TotalRewards(t *testing.T) {
|
||||
t.Skip() // skip to avoid having to commit a large genesis file to the repo
|
||||
|
||||
MigrateAppState(appState)
|
||||
|
||||
bz, err = ioutil.ReadFile(filepath.Join("testdata", "v0_15-incentive-state.json"))
|
||||
genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "genesis.json"))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, string(bz), string(appState[v0_15incentive.ModuleName]))
|
||||
cdc := makeV014Codec()
|
||||
|
||||
var oldState genutil.AppMap
|
||||
cdc.MustUnmarshalJSON(genDoc.AppState, &oldState)
|
||||
|
||||
var oldIncentiveGenState v0_14incentive.GenesisState
|
||||
cdc.MustUnmarshalJSON(oldState[v0_14incentive.ModuleName], &oldIncentiveGenState)
|
||||
|
||||
var oldCDPGenState v0_15cdp.GenesisState
|
||||
cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState)
|
||||
|
||||
newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs)
|
||||
|
||||
// total previous rewards
|
||||
oldTotalRewards := sdk.NewCoins() // total synced unclaimed rewards
|
||||
for _, claim := range oldIncentiveGenState.HardLiquidityProviderClaims {
|
||||
oldTotalRewards = oldTotalRewards.Add(claim.Reward...)
|
||||
}
|
||||
for _, claim := range oldIncentiveGenState.USDXMintingClaims {
|
||||
oldTotalRewards = oldTotalRewards.Add(claim.Reward)
|
||||
}
|
||||
|
||||
// total new rewards
|
||||
newTotalRewards := sdk.NewCoins() // total synced unclaimed rewards
|
||||
for _, claim := range newGenState.USDXMintingClaims {
|
||||
newTotalRewards = newTotalRewards.Add(claim.Reward)
|
||||
}
|
||||
for _, claim := range newGenState.HardLiquidityProviderClaims {
|
||||
newTotalRewards = newTotalRewards.Add(claim.Reward...)
|
||||
}
|
||||
|
||||
// rewards added in migration
|
||||
additionalRewards := sdk.NewCoins()
|
||||
var missedRewards map[string]sdk.Coin
|
||||
cdc.MustUnmarshalJSON([]byte(missedUSDXMintingRewards), &missedRewards)
|
||||
for _, c := range missedRewards {
|
||||
additionalRewards = additionalRewards.Add(c)
|
||||
}
|
||||
|
||||
require.Equal(t, oldTotalRewards.Add(additionalRewards...), newTotalRewards)
|
||||
}
|
||||
|
||||
func TestSwap(t *testing.T) {
|
||||
|
5
migrate/v0_15/rewards.go
Normal file
5
migrate/v0_15/rewards.go
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
277
migrate/v0_15/testdata/v0_14-incentive-state.json
vendored
277
migrate/v0_15/testdata/v0_14-incentive-state.json
vendored
@ -1,277 +0,0 @@
|
||||
{
|
||||
"hard_borrow_accumulation_times": [],
|
||||
"hard_borrow_reward_indexes": [],
|
||||
"hard_delegator_accumulation_times": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"hard_delegator_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"hard_liquidity_provider_claims": [
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zx2gfs37vszrgrxke22mtlfj6hpl72y03ur7xr",
|
||||
"reward": [
|
||||
{
|
||||
"amount": "48396109",
|
||||
"denom": "hard"
|
||||
},
|
||||
{
|
||||
"amount": "1",
|
||||
"denom": "ukava"
|
||||
}
|
||||
]
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"delegator_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
],
|
||||
"supply_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu77sruwsk7vw8pkcrj20ees0gyjlfntrgahy",
|
||||
"reward": []
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"delegator_reward_indexes": [],
|
||||
"supply_reward_indexes": []
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu7gxmdcd7x83ndl2nvegj57lasf7cel4nrex",
|
||||
"reward": [
|
||||
{
|
||||
"amount": "6442528",
|
||||
"denom": "hard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"delegator_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
],
|
||||
"supply_reward_indexes": []
|
||||
}
|
||||
],
|
||||
"hard_supply_accumulation_times": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"hard_supply_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"claim_end": "2026-04-08T14:00:00Z",
|
||||
"claim_multipliers": [
|
||||
{
|
||||
"factor": "0.200000000000000000",
|
||||
"months_lockup": "1",
|
||||
"name": "small"
|
||||
},
|
||||
{
|
||||
"factor": "1.000000000000000000",
|
||||
"months_lockup": "12",
|
||||
"name": "large"
|
||||
}
|
||||
],
|
||||
"hard_borrow_reward_periods": [],
|
||||
"hard_delegator_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "ukava",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": {
|
||||
"amount": "633761",
|
||||
"denom": "hard"
|
||||
},
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
}
|
||||
],
|
||||
"hard_supply_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "usdx",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": [
|
||||
{
|
||||
"amount": "373919",
|
||||
"denom": "hard"
|
||||
},
|
||||
{
|
||||
"amount": "373919",
|
||||
"denom": "ukava"
|
||||
}
|
||||
],
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
},
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "bnb",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": [
|
||||
{
|
||||
"amount": "12675",
|
||||
"denom": "hard"
|
||||
}
|
||||
],
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
}
|
||||
],
|
||||
"usdx_minting_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "btcb-a",
|
||||
"end": "2022-04-08T14:00:00Z",
|
||||
"rewards_per_second": {
|
||||
"amount": "110780",
|
||||
"denom": "ukava"
|
||||
},
|
||||
"start": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "bnb-a",
|
||||
"end": "2022-04-08T14:00:00Z",
|
||||
"rewards_per_second": {
|
||||
"amount": "122354",
|
||||
"denom": "ukava"
|
||||
},
|
||||
"start": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"usdx_accumulation_times": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"usdx_minting_claims": [
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava177dtrf8ahjp3wud6p3aqurpuyqae3mq8n069m9",
|
||||
"reward": {
|
||||
"amount": "81528",
|
||||
"denom": "ukava"
|
||||
}
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava18dde5uvs9h474wj5pe69wg66s2v30whpsqgwee",
|
||||
"reward": {
|
||||
"amount": "4825232",
|
||||
"denom": "ukava"
|
||||
}
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"usdx_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
367
migrate/v0_15/testdata/v0_15-incentive-state.json
vendored
367
migrate/v0_15/testdata/v0_15-incentive-state.json
vendored
@ -1,367 +0,0 @@
|
||||
{
|
||||
"delegator_claims": [
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zx2gfs37vszrgrxke22mtlfj6hpl72y03ur7xr",
|
||||
"reward": []
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu77sruwsk7vw8pkcrj20ees0gyjlfntrgahy",
|
||||
"reward": []
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_indexes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu7gxmdcd7x83ndl2nvegj57lasf7cel4nrex",
|
||||
"reward": []
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"delegator_reward_state": {
|
||||
"accumulation_times": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"multi_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"hard_borrow_reward_state": {
|
||||
"accumulation_times": [],
|
||||
"multi_reward_indexes": []
|
||||
},
|
||||
"hard_liquidity_provider_claims": [
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zx2gfs37vszrgrxke22mtlfj6hpl72y03ur7xr",
|
||||
"reward": [
|
||||
{
|
||||
"amount": "48396109",
|
||||
"denom": "hard"
|
||||
},
|
||||
{
|
||||
"amount": "1",
|
||||
"denom": "ukava"
|
||||
}
|
||||
]
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"supply_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu77sruwsk7vw8pkcrj20ees0gyjlfntrgahy",
|
||||
"reward": []
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"supply_reward_indexes": []
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava1zyu7gxmdcd7x83ndl2nvegj57lasf7cel4nrex",
|
||||
"reward": [
|
||||
{
|
||||
"amount": "6442528",
|
||||
"denom": "hard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"borrow_reward_indexes": [],
|
||||
"supply_reward_indexes": []
|
||||
}
|
||||
],
|
||||
"hard_supply_reward_state": {
|
||||
"accumulation_times": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"multi_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "usdx",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "hard",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"claim_end": "2026-04-08T14:00:00Z",
|
||||
"claim_multipliers": [
|
||||
{
|
||||
"denom": "hard",
|
||||
"multipliers": [
|
||||
{
|
||||
"name": "small",
|
||||
"months_lockup": "1",
|
||||
"factor": "0.200000000000000000"
|
||||
},
|
||||
{
|
||||
"name": "large",
|
||||
"months_lockup": "12",
|
||||
"factor": "1.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"denom": "ukava",
|
||||
"multipliers": [
|
||||
{
|
||||
"name": "small",
|
||||
"months_lockup": "1",
|
||||
"factor": "0.200000000000000000"
|
||||
},
|
||||
{
|
||||
"name": "large",
|
||||
"months_lockup": "12",
|
||||
"factor": "1.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"denom": "swp",
|
||||
"multipliers": [
|
||||
{
|
||||
"name": "small",
|
||||
"months_lockup": "1",
|
||||
"factor": "0.100000000000000000"
|
||||
},
|
||||
{
|
||||
"name": "large",
|
||||
"months_lockup": "12",
|
||||
"factor": "1.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"delegator_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "ukava",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": [
|
||||
{
|
||||
"amount": "633761",
|
||||
"denom": "hard"
|
||||
},
|
||||
{
|
||||
"amount": "1",
|
||||
"denom": "swp"
|
||||
}
|
||||
],
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
}
|
||||
],
|
||||
"hard_borrow_reward_periods": [],
|
||||
"hard_supply_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "usdx",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": [
|
||||
{
|
||||
"amount": "373919",
|
||||
"denom": "hard"
|
||||
},
|
||||
{
|
||||
"amount": "373919",
|
||||
"denom": "ukava"
|
||||
}
|
||||
],
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
},
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "bnb",
|
||||
"end": "2024-10-16T14:00:00Z",
|
||||
"rewards_per_second": [
|
||||
{
|
||||
"amount": "12675",
|
||||
"denom": "hard"
|
||||
}
|
||||
],
|
||||
"start": "2020-10-16T14:00:00Z"
|
||||
}
|
||||
],
|
||||
"swap_reward_periods": [],
|
||||
"usdx_minting_reward_periods": [
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "btcb-a",
|
||||
"end": "2022-04-08T14:00:00Z",
|
||||
"rewards_per_second": {
|
||||
"amount": "110780",
|
||||
"denom": "ukava"
|
||||
},
|
||||
"start": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"active": true,
|
||||
"collateral_type": "bnb-a",
|
||||
"end": "2022-04-08T14:00:00Z",
|
||||
"rewards_per_second": {
|
||||
"amount": "122354",
|
||||
"denom": "ukava"
|
||||
},
|
||||
"start": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"swap_claims": [],
|
||||
"swap_reward_state": {
|
||||
"accumulation_times": [],
|
||||
"multi_reward_indexes": []
|
||||
},
|
||||
"usdx_minting_claims": [
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava177dtrf8ahjp3wud6p3aqurpuyqae3mq8n069m9",
|
||||
"reward": {
|
||||
"amount": "81528",
|
||||
"denom": "ukava"
|
||||
}
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"base_claim": {
|
||||
"owner": "kava18dde5uvs9h474wj5pe69wg66s2v30whpsqgwee",
|
||||
"reward": {
|
||||
"amount": "4825232",
|
||||
"denom": "ukava"
|
||||
}
|
||||
},
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"usdx_reward_state": {
|
||||
"accumulation_times": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"previous_accumulation_time": "2021-04-08T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"multi_reward_indexes": [
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.000000000000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
108
migrate/v0_15/usdx_rewards/calculate.go
Normal file
108
migrate/v0_15/usdx_rewards/calculate.go
Normal file
@ -0,0 +1,108 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_15incentive "github.com/kava-labs/kava/x/incentive"
|
||||
)
|
||||
|
||||
type rewards map[string]sdk.Coin
|
||||
|
||||
type rewardsCalculator struct {
|
||||
claims v0_15incentive.USDXMintingClaims
|
||||
globalIndexes v0_15incentive.RewardIndexes
|
||||
cdps v0_15cdp.CDPs
|
||||
}
|
||||
|
||||
func NewRewardsCalculator(claims v0_15incentive.USDXMintingClaims, globalIndexes v0_15incentive.RewardIndexes, cdps v0_15cdp.CDPs) rewardsCalculator {
|
||||
return rewardsCalculator{
|
||||
claims: claims,
|
||||
globalIndexes: globalIndexes,
|
||||
cdps: cdps,
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate synchronizes all of the claims and returns the new rewards to be added by owner address.
|
||||
func (rc rewardsCalculator) Calculate() (rewards, error) {
|
||||
rewards := rewards{}
|
||||
|
||||
for _, claim := range rc.claims {
|
||||
|
||||
reward, err := rc.calculateRewardsForClaim(claim)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, found := rewards[claim.Owner.String()]; found {
|
||||
return nil, fmt.Errorf("duplicate claim found: %s", claim.Owner)
|
||||
}
|
||||
if !reward.IsZero() {
|
||||
rewards[claim.Owner.String()] = reward
|
||||
}
|
||||
}
|
||||
return rewards, nil
|
||||
}
|
||||
|
||||
// calculateRewardsForClaim synchronizes the claim to and returns the new rewards that should be added.
|
||||
// It syncs against the stored global indexes, looking up cdps for the source share amounts.
|
||||
func (rc rewardsCalculator) calculateRewardsForClaim(claim v0_15incentive.USDXMintingClaim) (sdk.Coin, error) {
|
||||
reward := sdk.ZeroInt()
|
||||
|
||||
for _, index := range rc.globalIndexes {
|
||||
oldFactor, found := claim.RewardIndexes.Get(index.CollateralType)
|
||||
if !found {
|
||||
oldFactor = sdk.ZeroDec()
|
||||
}
|
||||
|
||||
sourceShares := sdk.ZeroDec()
|
||||
cdp, found := rc.getCDP(claim.Owner, index.CollateralType)
|
||||
if found {
|
||||
sourceShares = cdp.GetTotalPrincipal().Amount.ToDec()
|
||||
}
|
||||
|
||||
amount, err := rc.calculateSingleReward(oldFactor, index.RewardFactor, sourceShares)
|
||||
if err != nil {
|
||||
return sdk.Coin{}, err
|
||||
}
|
||||
|
||||
reward = reward.Add(amount)
|
||||
}
|
||||
return sdk.NewCoin(v0_15incentive.USDXMintingRewardDenom, reward), nil
|
||||
}
|
||||
|
||||
// calculateSingleReward computes how much rewards should have accrued to a reward source (eg a user's btcb-a cdp principal)
|
||||
// between two index values.
|
||||
func (rc rewardsCalculator) calculateSingleReward(oldIndex, newIndex, sourceShares sdk.Dec) (sdk.Int, error) {
|
||||
increase := newIndex.Sub(oldIndex)
|
||||
if increase.IsNegative() {
|
||||
return sdk.Int{}, sdkerrors.Wrapf(v0_15incentive.ErrDecreasingRewardFactor, "old: %v, new: %v", oldIndex, newIndex)
|
||||
}
|
||||
reward := increase.Mul(sourceShares).RoundInt()
|
||||
return reward, nil
|
||||
}
|
||||
|
||||
// getCDP looks up a cdp by owner and collateral type.
|
||||
func (rc rewardsCalculator) getCDP(owner sdk.AccAddress, collateralType string) (v0_15cdp.CDP, bool) {
|
||||
for _, cdp := range rc.cdps {
|
||||
if cdp.Owner.Equals(owner) && cdp.Type == collateralType {
|
||||
return cdp, true
|
||||
}
|
||||
}
|
||||
return v0_15cdp.CDP{}, false
|
||||
}
|
||||
|
||||
func convertRewardIndexesToUSDXMintingIndexes(mris v0_15incentive.MultiRewardIndexes) v0_15incentive.RewardIndexes {
|
||||
var newIndexes v0_15incentive.RewardIndexes
|
||||
for _, mri := range mris {
|
||||
factor, found := mri.RewardIndexes.Get(v0_15incentive.USDXMintingRewardDenom)
|
||||
if !found {
|
||||
panic(fmt.Sprintf("found global usdx minting reward index without denom '%s': %s", v0_15incentive.USDXMintingRewardDenom, mri))
|
||||
}
|
||||
newIndexes = newIndexes.With(mri.CollateralType, factor)
|
||||
}
|
||||
return newIndexes
|
||||
}
|
124
migrate/v0_15/usdx_rewards/calculate_test.go
Normal file
124
migrate/v0_15/usdx_rewards/calculate_test.go
Normal file
@ -0,0 +1,124 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
|
||||
)
|
||||
|
||||
func TestCalculateRewardsForClaim(t *testing.T) {
|
||||
type expect struct {
|
||||
amount sdk.Int
|
||||
err bool
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
claimIndexes v0_15incentive.RewardIndexes
|
||||
globalIndexes v0_15incentive.RewardIndexes
|
||||
cdps v0_15cdp.CDPs
|
||||
expected expect
|
||||
}{
|
||||
{
|
||||
name: "single cdp is synced",
|
||||
claimIndexes: v0_15incentive.RewardIndexes{
|
||||
{
|
||||
CollateralType: "busd-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("0.1"),
|
||||
},
|
||||
},
|
||||
globalIndexes: v0_15incentive.RewardIndexes{
|
||||
{
|
||||
CollateralType: "busd-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("0.2"),
|
||||
},
|
||||
},
|
||||
cdps: v0_15cdp.CDPs{{
|
||||
Owner: sdk.AccAddress("address1"),
|
||||
Type: "busd-a",
|
||||
Principal: sdk.NewInt64Coin("usdx", 1000),
|
||||
AccumulatedFees: sdk.NewInt64Coin("usdx", 10),
|
||||
}},
|
||||
expected: expect{amount: sdk.NewInt(101)},
|
||||
},
|
||||
{
|
||||
name: "missing claim index is assumed 0",
|
||||
claimIndexes: v0_15incentive.RewardIndexes{},
|
||||
globalIndexes: v0_15incentive.RewardIndexes{
|
||||
{
|
||||
CollateralType: "busd-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("0.2"),
|
||||
},
|
||||
},
|
||||
cdps: v0_15cdp.CDPs{{
|
||||
Owner: sdk.AccAddress("address1"),
|
||||
Type: "busd-a",
|
||||
Principal: sdk.NewInt64Coin("usdx", 1000),
|
||||
AccumulatedFees: sdk.NewInt64Coin("usdx", 10),
|
||||
}},
|
||||
expected: expect{amount: sdk.NewInt(202)},
|
||||
},
|
||||
{
|
||||
name: "multiple cdps are synced",
|
||||
claimIndexes: v0_15incentive.RewardIndexes{
|
||||
{
|
||||
CollateralType: "busd-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("0.1"),
|
||||
},
|
||||
{
|
||||
CollateralType: "xrpb-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("1"),
|
||||
},
|
||||
},
|
||||
globalIndexes: v0_15incentive.RewardIndexes{
|
||||
{
|
||||
CollateralType: "busd-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("0.2"),
|
||||
},
|
||||
{
|
||||
CollateralType: "xrpb-a",
|
||||
RewardFactor: sdk.MustNewDecFromStr("2"),
|
||||
},
|
||||
},
|
||||
cdps: v0_15cdp.CDPs{
|
||||
{
|
||||
Owner: sdk.AccAddress("address1"),
|
||||
Type: "busd-a",
|
||||
Principal: sdk.NewInt64Coin("usdx", 1000),
|
||||
AccumulatedFees: sdk.NewInt64Coin("usdx", 100),
|
||||
},
|
||||
{
|
||||
Owner: sdk.AccAddress("address1"),
|
||||
Type: "xrpb-a",
|
||||
Principal: sdk.NewInt64Coin("usdx", 10),
|
||||
AccumulatedFees: sdk.NewInt64Coin("usdx", 1),
|
||||
}},
|
||||
expected: expect{amount: sdk.NewInt(110 + 11)},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
rc := rewardsCalculator{
|
||||
globalIndexes: tc.globalIndexes,
|
||||
cdps: tc.cdps,
|
||||
}
|
||||
reward, err := rc.calculateRewardsForClaim(v0_15incentive.NewUSDXMintingClaim(
|
||||
sdk.AccAddress("address1"),
|
||||
sdk.NewInt64Coin("ukava", 0),
|
||||
tc.claimIndexes,
|
||||
))
|
||||
|
||||
if tc.expected.err {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, v0_15incentive.USDXMintingRewardDenom, reward.Denom)
|
||||
require.Truef(t, tc.expected.amount.Equal(reward.Amount), "amount not equal %s, %s", tc.expected.amount, reward.Amount)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
41137
migrate/v0_15/usdx_rewards/cdp-cdps-829296.json
Normal file
41137
migrate/v0_15/usdx_rewards/cdp-cdps-829296.json
Normal file
File diff suppressed because it is too large
Load Diff
43040
migrate/v0_15/usdx_rewards/incentive-usdx-claims-829296.json
Normal file
43040
migrate/v0_15/usdx_rewards/incentive-usdx-claims-829296.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
||||
[
|
||||
{
|
||||
"collateral_type": "bnb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.043949244534927716"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "btcb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.046551281526135881"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "busd-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.011468527653896411"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "hard-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.123365881475003544"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "hbtc-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "1.472331865900201761"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "ukava-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.038864939729274249"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collateral_type": "xrpb-a",
|
||||
"reward_indexes": [
|
||||
{
|
||||
"collateral_type": "ukava",
|
||||
"reward_factor": "0.020676676769949043"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
87
migrate/v0_15/usdx_rewards/main.go
Normal file
87
migrate/v0_15/usdx_rewards/main.go
Normal file
@ -0,0 +1,87 @@
|
||||
// package main calculates missing rewards from kava-7 so they can be include in the migration to kava-8.
|
||||
// In the migration folder run `go run ./usdx_rewards` to compute the output file. The output is a go file so it can be included in the migrations.
|
||||
// Data is taken from an export at height 829296 of kava-7 using v0.14.3.
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/kava-labs/kava/app"
|
||||
v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
|
||||
v0_15incentive "github.com/kava-labs/kava/x/incentive"
|
||||
)
|
||||
|
||||
var (
|
||||
outFileName = "rewards.go"
|
||||
|
||||
dirPath = "./usdx_rewards"
|
||||
cdpsFileName = filepath.Join(dirPath, "cdp-cdps-829296.json")
|
||||
indexesFileName = filepath.Join(dirPath, "incentive-usdx-indexes-829296.json")
|
||||
claimsFileName = filepath.Join(dirPath, "incentive-usdx-claims-829296.json")
|
||||
)
|
||||
|
||||
func main() {
|
||||
app.SetBech32AddressPrefixes(sdk.GetConfig())
|
||||
cdc := app.MakeCodec()
|
||||
|
||||
var cdps v0_15cdp.CDPs
|
||||
if err := fetchFromJSONFile(cdc, cdpsFileName, &cdps); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
var globalIndexes v0_15incentive.MultiRewardIndexes
|
||||
if err := fetchFromJSONFile(cdc, indexesFileName, &globalIndexes); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
var claims v0_15incentive.USDXMintingClaims
|
||||
if err := fetchFromJSONFile(cdc, claimsFileName, &claims); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
calculator := NewRewardsCalculator(claims, convertRewardIndexesToUSDXMintingIndexes(globalIndexes), cdps)
|
||||
rewards, err := calculator.Calculate()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
out := createOutputString(cdc, rewards)
|
||||
|
||||
if err = ioutil.WriteFile(outFileName, []byte(out), 0644); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fetchFromJSONFile reads and unmarshals the contents of a json file.
|
||||
func fetchFromJSONFile(cdc *codec.Codec, filePath string, pointer interface{}) error {
|
||||
|
||||
bz, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cdc.UnmarshalJSON(bz, pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createOutputString(cdc *codec.Codec, rewards rewards) string {
|
||||
bz := cdc.MustMarshalJSON(rewards)
|
||||
|
||||
// sort json keys so make changes easier to compare
|
||||
bz = sdk.MustSortJSON(bz)
|
||||
|
||||
out := `// Code generated by package ./usdx_rewards DO NOT EDIT.
|
||||
|
||||
package v0_15
|
||||
|
||||
var missedUSDXMintingRewards = ` + "`" + string(bz) + "`\n"
|
||||
|
||||
return out
|
||||
}
|
Loading…
Reference in New Issue
Block a user