mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 11:17:28 +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