Incentive migration state fixes: delegator (#1004)

* add missing delegator claims

* fix tests
This commit is contained in:
Ruaridh 2021-08-20 04:13:59 +01:00 committed by GitHub
parent 7d85361240
commit a52f606447
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 158 additions and 8 deletions

View File

@ -7,6 +7,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
v0_15staking "github.com/cosmos/cosmos-sdk/x/staking/types"
v0_15hard "github.com/kava-labs/kava/x/hard/types" v0_15hard "github.com/kava-labs/kava/x/hard/types"
@ -16,7 +17,7 @@ import (
) )
// Incentive migrates from a v0.14 incentive genesis state to a v0.15 incentive genesis state // Incentive migrates from a v0.14 incentive genesis state to a v0.15 incentive genesis state
func Incentive(cdc *codec.Codec, incentiveGS v0_14incentive.GenesisState, cdps v0_15cdp.CDPs, hardGS v0_15hard.GenesisState) v0_15incentive.GenesisState { func Incentive(cdc *codec.Codec, incentiveGS v0_14incentive.GenesisState, cdps v0_15cdp.CDPs, hardGS v0_15hard.GenesisState, delegations v0_15staking.Delegations) v0_15incentive.GenesisState {
// Migrate params // Migrate params
claimMultipliers := v0_15incentive.Multipliers{} claimMultipliers := v0_15incentive.Multipliers{}
for _, m := range incentiveGS.Params.ClaimMultipliers { for _, m := range incentiveGS.Params.ClaimMultipliers {
@ -117,6 +118,8 @@ func Incentive(cdc *codec.Codec, incentiveGS v0_14incentive.GenesisState, cdps v
hardSupplyGenesisRewardState.MultiRewardIndexes, hardBorrowGenesisRewardState.MultiRewardIndexes, hardSupplyGenesisRewardState.MultiRewardIndexes, hardBorrowGenesisRewardState.MultiRewardIndexes,
) )
delegatorClaims = addMissingDelegatorClaims(delegatorClaims, delegations, delegatorGenesisRewardState.MultiRewardIndexes)
// Add Swap Claims // Add Swap Claims
swapClaims := v0_15incentive.DefaultSwapClaims swapClaims := v0_15incentive.DefaultSwapClaims
@ -395,6 +398,36 @@ func getHardClaimByOwner(claims v0_15incentive.HardLiquidityProviderClaims, owne
return v0_15incentive.HardLiquidityProviderClaim{}, false return v0_15incentive.HardLiquidityProviderClaim{}, false
} }
// getDelegatorClaimByOwner picks out the first delegator claim matching an address.
func getDelegatorClaimByOwner(claims v0_15incentive.DelegatorClaims, owner sdk.AccAddress) (v0_15incentive.DelegatorClaim, bool) {
for _, claim := range claims {
if claim.Owner.Equals(owner) {
return claim, true
}
}
return v0_15incentive.DelegatorClaim{}, false
}
// addMissingDelegatorClaims checks if there are delegations without claims, and if so creates new claims for them.
func addMissingDelegatorClaims(claims v0_15incentive.DelegatorClaims, delegations v0_15staking.Delegations, globalIndexes v0_15incentive.MultiRewardIndexes) v0_15incentive.DelegatorClaims {
for _, delegation := range delegations {
_, found := getDelegatorClaimByOwner(claims, delegation.DelegatorAddress)
if !found {
claim := v0_15incentive.NewDelegatorClaim(
delegation.DelegatorAddress,
sdk.NewCoins(),
globalIndexes, // indexes are set to current so rewards start accumulating from genesis
)
claims = append(claims, claim)
}
}
return claims
}
// getHardDepositByOwner picks out the first deposit matching an address. // getHardDepositByOwner picks out the first deposit matching an address.
func getHardDepositByOwner(deposits v0_15hard.Deposits, owner sdk.AccAddress) (v0_15hard.Deposit, bool) { func getHardDepositByOwner(deposits v0_15hard.Deposits, owner sdk.AccAddress) (v0_15hard.Deposit, bool) {
for _, deposit := range deposits { for _, deposit := range deposits {

View File

@ -4,6 +4,7 @@ import (
"testing" "testing"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
v0_15staking "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
v0_15cdp "github.com/kava-labs/kava/x/cdp/types" v0_15cdp "github.com/kava-labs/kava/x/cdp/types"
@ -525,3 +526,79 @@ func TestAddRewards(t *testing.T) {
amendedClaims := addRewards(claims, rewards) amendedClaims := addRewards(claims, rewards)
require.Equal(t, expectedClaims, amendedClaims) require.Equal(t, expectedClaims, amendedClaims)
} }
func TestAddMissingDelegatorClaims(t *testing.T) {
claims := v0_15incentive.DelegatorClaims{
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address1"),
nil,
nil,
),
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address3"),
nil,
nil,
),
}
delegations := v0_15staking.Delegations{
{
DelegatorAddress: sdk.AccAddress("address2"),
},
{
DelegatorAddress: sdk.AccAddress("address1"),
},
{
DelegatorAddress: sdk.AccAddress("address3"),
},
{
DelegatorAddress: sdk.AccAddress("address3"), // there can be multiple delegations per delegator
},
{
DelegatorAddress: sdk.AccAddress("address4"),
},
{
DelegatorAddress: sdk.AccAddress("address4"),
},
}
globalIndexes := v0_15incentive.MultiRewardIndexes{{
CollateralType: "ukava",
RewardIndexes: v0_15incentive.RewardIndexes{
{
CollateralType: "hard",
RewardFactor: sdk.MustNewDecFromStr("0.1"),
},
{
CollateralType: "swp",
RewardFactor: sdk.MustNewDecFromStr("0.2"),
},
},
}}
expectedClaims := v0_15incentive.DelegatorClaims{
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address1"),
nil,
nil,
),
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address3"),
nil,
nil,
),
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address2"),
sdk.NewCoins(),
globalIndexes,
),
v0_15incentive.NewDelegatorClaim(
sdk.AccAddress("address4"),
sdk.NewCoins(),
globalIndexes,
),
}
newClaims := addMissingDelegatorClaims(claims, delegations, globalIndexes)
require.Equal(t, expectedClaims, newClaims)
}

View File

@ -9,6 +9,7 @@ import (
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
v0_15staking "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/cosmos-sdk/x/supply" "github.com/cosmos/cosmos-sdk/x/supply"
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
@ -79,6 +80,9 @@ func MigrateAppState(v0_14AppState genutil.AppMap) {
v0_14Codec.MustUnmarshalJSON(v0_14AppState[v0_14incentive.ModuleName], &incentiveGenState) v0_14Codec.MustUnmarshalJSON(v0_14AppState[v0_14incentive.ModuleName], &incentiveGenState)
delete(v0_14AppState, v0_14incentive.ModuleName) delete(v0_14AppState, v0_14incentive.ModuleName)
var stakingGenState v0_15staking.GenesisState // staking unchanged between v0_14 and v0_15
v0_14Codec.MustUnmarshalJSON(v0_14AppState[v0_15staking.ModuleName], &stakingGenState)
var hardGenState v0_15hard.GenesisState // v0_14 hard genesis state is the same as v0_15 var hardGenState v0_15hard.GenesisState // v0_14 hard genesis state is the same as v0_15
v0_15Codec.MustUnmarshalJSON(v0_14AppState[v0_15hard.ModuleName], &hardGenState) v0_15Codec.MustUnmarshalJSON(v0_14AppState[v0_15hard.ModuleName], &hardGenState)
@ -86,7 +90,9 @@ func MigrateAppState(v0_14AppState genutil.AppMap) {
var cdpGenState v0_15cdp.GenesisState var cdpGenState v0_15cdp.GenesisState
v0_15Codec.MustUnmarshalJSON(v0_14AppState[v0_15cdp.ModuleName], &cdpGenState) v0_15Codec.MustUnmarshalJSON(v0_14AppState[v0_15cdp.ModuleName], &cdpGenState)
v0_14AppState[v0_15incentive.ModuleName] = v0_15Codec.MustMarshalJSON(Incentive(v0_15Codec, incentiveGenState, cdpGenState.CDPs, hardGenState)) v0_14AppState[v0_15incentive.ModuleName] = v0_15Codec.MustMarshalJSON(
Incentive(v0_15Codec, incentiveGenState, cdpGenState.CDPs, hardGenState, stakingGenState.Delegations),
)
} }
// Migrate commmittee app state // Migrate commmittee app state

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
v0_15staking "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
@ -83,10 +84,13 @@ func TestIncentive_Full(t *testing.T) {
var oldHardGenState v0_15hard.GenesisState var oldHardGenState v0_15hard.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15hard.ModuleName], &oldHardGenState) cdc.MustUnmarshalJSON(oldState[v0_15hard.ModuleName], &oldHardGenState)
var oldStakingGenState v0_15staking.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15staking.ModuleName], &oldStakingGenState)
var oldCDPGenState v0_15cdp.GenesisState var oldCDPGenState v0_15cdp.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState) cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState)
newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs, oldHardGenState) newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs, oldHardGenState, oldStakingGenState.Delegations)
require.NoError(t, newGenState.Validate()) require.NoError(t, newGenState.Validate())
// TODO check params, indexes, and accumulation times // TODO check params, indexes, and accumulation times
@ -224,8 +228,34 @@ func TestIncentive_Full(t *testing.T) {
} }
} }
// 1 new DelegatorClaim should have been created for each existing HardLiquidityProviderClaim // Ensure every delegation has a claim
require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.DelegatorClaims)) for _, delegation := range oldStakingGenState.Delegations {
numClaims := 0
for _, claim := range newGenState.DelegatorClaims {
if delegation.DelegatorAddress.Equals(claim.Owner) {
numClaims++
}
}
require.Equal(t, 1, numClaims, "delegation '%s' has invalid number of claims '%d'", delegation.DelegatorAddress, numClaims)
}
// Ensure all delegation indexes are ≤ global values
for _, claim := range newGenState.DelegatorClaims {
for _, ri := range claim.RewardIndexes {
require.Equal(t, v0_15incentive.BondDenom, ri.CollateralType)
global, found := newGenState.DelegatorRewardState.MultiRewardIndexes.Get(ri.CollateralType)
if !found {
global = v0_15incentive.RewardIndexes{}
}
require.Truef(t, indexesAllLessThanOrEqual(ri.RewardIndexes, global), "invalid delegator claim indexes %s %s", ri.RewardIndexes, global)
}
}
// Ensure delegator rewards are all initialized at 0
for _, claim := range newGenState.DelegatorClaims {
require.Equal(t, sdk.NewCoins(), claim.Reward)
}
} }
// collateralTypesMatch checks if the set of coin denoms is equal to the set of CollateralTypes in the indexes. // collateralTypesMatch checks if the set of coin denoms is equal to the set of CollateralTypes in the indexes.
@ -276,10 +306,13 @@ func TestIncentive_Full_TotalRewards(t *testing.T) {
var oldHardGenState v0_15hard.GenesisState var oldHardGenState v0_15hard.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15hard.ModuleName], &oldHardGenState) cdc.MustUnmarshalJSON(oldState[v0_15hard.ModuleName], &oldHardGenState)
var oldStakingGenState v0_15staking.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15staking.ModuleName], &oldStakingGenState)
var oldCDPGenState v0_15cdp.GenesisState var oldCDPGenState v0_15cdp.GenesisState
cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState) cdc.MustUnmarshalJSON(oldState[v0_15cdp.ModuleName], &oldCDPGenState)
newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs, oldHardGenState) newGenState := Incentive(app.MakeCodec(), oldIncentiveGenState, oldCDPGenState.CDPs, oldHardGenState, oldStakingGenState.Delegations)
// total previous rewards // total previous rewards
oldTotalRewards := sdk.NewCoins() // total synced unclaimed rewards oldTotalRewards := sdk.NewCoins() // total synced unclaimed rewards
@ -333,7 +366,7 @@ func TestIncentive_SwpLPRewards(t *testing.T) {
newGenState := v0_15incentive.GenesisState{} newGenState := v0_15incentive.GenesisState{}
require.NotPanics(t, func() { require.NotPanics(t, func() {
newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{}, v0_15hard.DefaultGenesisState()) newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{}, v0_15hard.DefaultGenesisState(), v0_15staking.Delegations{})
}) })
err = newGenState.Validate() err = newGenState.Validate()
require.NoError(t, err) require.NoError(t, err)
@ -369,7 +402,7 @@ func TestIncentive_SwpDelegatorRewards(t *testing.T) {
newGenState := v0_15incentive.GenesisState{} newGenState := v0_15incentive.GenesisState{}
require.NotPanics(t, func() { require.NotPanics(t, func() {
newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{}, v0_15hard.DefaultGenesisState()) newGenState = Incentive(app.MakeCodec(), oldIncentiveGenState, v0_15cdp.CDPs{}, v0_15hard.DefaultGenesisState(), v0_15staking.Delegations{})
}) })
for _, rp := range newGenState.Params.DelegatorRewardPeriods { for _, rp := range newGenState.Params.DelegatorRewardPeriods {
@ -389,6 +422,7 @@ func TestIncentive_SwpPoolsValid(t *testing.T) {
v0_14incentive.ModuleName: bz, v0_14incentive.ModuleName: bz,
v0_15cdp.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15cdp.DefaultGenesisState()), v0_15cdp.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15cdp.DefaultGenesisState()),
v0_15hard.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15hard.DefaultGenesisState()), v0_15hard.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15hard.DefaultGenesisState()),
v0_15staking.ModuleName: app.MakeCodec().MustMarshalJSON(v0_15staking.DefaultGenesisState()),
} }
MigrateAppState(appState) MigrateAppState(appState)