Add committee migrations (#818)

* fix: collateral param permission

* wip: kava-5 committee updates

* feat: add committee migrations

* rename functions so git recognizes diffs better

* rename

* remove auction_size param

* address review comments

* add check ltv index count to collateral param perms

* fix: update legacy migration

* use function to define collateral param in test

* use go 1.15 in circle

* address review comments

* fix: no nil values for collateral params
This commit is contained in:
Kevin Davis 2021-02-19 14:05:42 -07:00 committed by GitHub
parent 421f774ec1
commit 1ab2e9965f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 511 additions and 123 deletions

View File

@ -24,7 +24,7 @@ import (
v0_9bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9" v0_9bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11" v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11"
v0_9cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_9" v0_9cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_9"
v0_11committee "github.com/kava-labs/kava/x/committee" v0_11committee "github.com/kava-labs/kava/x/committee/legacy/v0_11"
v0_9committee "github.com/kava-labs/kava/x/committee/legacy/v0_9" v0_9committee "github.com/kava-labs/kava/x/committee/legacy/v0_9"
v0_11harvest "github.com/kava-labs/kava/x/hard/legacy/v0_11" v0_11harvest "github.com/kava-labs/kava/x/hard/legacy/v0_11"
v0_11incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_11" v0_11incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_11"

View File

@ -11,10 +11,12 @@ import (
v0_13cdp "github.com/kava-labs/kava/x/cdp" v0_13cdp "github.com/kava-labs/kava/x/cdp"
v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11" v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11"
v0_13committee "github.com/kava-labs/kava/x/committee"
v0_11committee "github.com/kava-labs/kava/x/committee/legacy/v0_11"
) )
// MigrateCDP migrates from a v0.11 cdp genesis state to a v0.13 cdp genesis state // CDP migrates from a v0.11 cdp genesis state to a v0.13 cdp genesis state
func MigrateCDP(oldGenState v0_11cdp.GenesisState) v0_13cdp.GenesisState { func CDP(oldGenState v0_11cdp.GenesisState) v0_13cdp.GenesisState {
var newCDPs v0_13cdp.CDPs var newCDPs v0_13cdp.CDPs
var newDeposits v0_13cdp.Deposits var newDeposits v0_13cdp.Deposits
var newCollateralParams v0_13cdp.CollateralParams var newCollateralParams v0_13cdp.CollateralParams
@ -78,8 +80,8 @@ func MigrateCDP(oldGenState v0_11cdp.GenesisState) v0_13cdp.GenesisState {
) )
} }
// MigrateAuth migrates from a v0.11 auth genesis state to a v0.13 // Auth migrates from a v0.11 auth genesis state to a v0.13
func MigrateAuth(genesisState auth.GenesisState) auth.GenesisState { func Auth(genesisState auth.GenesisState) auth.GenesisState {
savingsRateMaccCoins := sdk.NewCoins() savingsRateMaccCoins := sdk.NewCoins()
savingsMaccAddr := supply.NewModuleAddress(v0_11cdp.SavingsRateMacc) savingsMaccAddr := supply.NewModuleAddress(v0_11cdp.SavingsRateMacc)
savingsRateMaccIndex := 0 savingsRateMaccIndex := 0
@ -108,6 +110,121 @@ func MigrateAuth(genesisState auth.GenesisState) auth.GenesisState {
return genesisState return genesisState
} }
// Committee migrates from a v0.11 (or v0.12) committee genesis state to a v0.13 committee genesis stat
func Committee(genesisState v0_11committee.GenesisState) v0_13committee.GenesisState {
committees := []v0_13committee.Committee{}
votes := []v0_13committee.Vote{}
proposals := []v0_13committee.Proposal{}
var newStabilityCommittee v0_13committee.Committee
var newSafetyCommittee v0_13committee.Committee
for _, com := range genesisState.Committees {
if com.ID == 1 {
newStabilityCommittee.Description = com.Description
newStabilityCommittee.ID = com.ID
newStabilityCommittee.Members = com.Members
newStabilityCommittee.VoteThreshold = com.VoteThreshold
newStabilityCommittee.ProposalDuration = com.ProposalDuration
var newStabilityCommitteePermissions []v0_13committee.Permission
var newStabilitySubParamPermissions v0_13committee.SubParamChangePermission
for _, perm := range com.Permissions {
subPerm, ok := perm.(v0_11committee.SubParamChangePermission)
if ok {
// update AllowedParams
var newAllowedParams v0_13committee.AllowedParams
for _, ap := range subPerm.AllowedParams {
newAP := v0_13committee.AllowedParam(ap)
newAllowedParams = append(newAllowedParams, newAP)
}
newStabilitySubParamPermissions.AllowedParams = newAllowedParams
// update AllowedCollateralParams
var newCollateralParams v0_13committee.AllowedCollateralParams
for _, cp := range subPerm.AllowedCollateralParams {
newCP := v0_13committee.NewAllowedCollateralParam(
cp.Type,
cp.Denom,
cp.LiquidationRatio,
cp.DebtLimit,
cp.StabilityFee,
cp.AuctionSize,
cp.LiquidationPenalty,
cp.Prefix,
cp.SpotMarketID,
cp.LiquidationMarketID,
cp.ConversionFactor,
true,
true,
)
newCollateralParams = append(newCollateralParams, newCP)
}
newStabilitySubParamPermissions.AllowedCollateralParams = newCollateralParams
// update AllowedDebtParam
newDP := v0_13committee.AllowedDebtParam{
Denom: subPerm.AllowedDebtParam.Denom,
ReferenceAsset: subPerm.AllowedDebtParam.ReferenceAsset,
ConversionFactor: subPerm.AllowedDebtParam.ConversionFactor,
DebtFloor: subPerm.AllowedDebtParam.DebtFloor,
}
newStabilitySubParamPermissions.AllowedDebtParam = newDP
// update AllowedAssetParams
var newAssetParams v0_13committee.AllowedAssetParams
for _, ap := range subPerm.AllowedAssetParams {
newAP := v0_13committee.AllowedAssetParam(ap)
newAssetParams = append(newAssetParams, newAP)
}
newStabilitySubParamPermissions.AllowedAssetParams = newAssetParams
// Update Allowed Markets
var newMarketParams v0_13committee.AllowedMarkets
for _, mp := range subPerm.AllowedMarkets {
newMP := v0_13committee.AllowedMarket(mp)
newMarketParams = append(newMarketParams, newMP)
}
newStabilitySubParamPermissions.AllowedMarkets = newMarketParams
// Add hard money market committee permissions
var newMoneyMarketParams v0_13committee.AllowedMoneyMarkets
hardMMDenoms := []string{"bnb", "busd", "btcb", "xrpb", "usdx", "kava", "hard"}
for _, mmDenom := range hardMMDenoms {
newMoneyMarketParam := v0_13committee.NewAllowedMoneyMarket(mmDenom, true, false, false, true, true, true)
newMoneyMarketParams = append(newMoneyMarketParams, newMoneyMarketParam)
}
newStabilitySubParamPermissions.AllowedMoneyMarkets = newMoneyMarketParams
newStabilityCommitteePermissions = append(newStabilityCommitteePermissions, newStabilitySubParamPermissions)
}
}
newStabilityCommitteePermissions = append(newStabilityCommitteePermissions, v0_13committee.TextPermission{})
newStabilityCommittee.Permissions = newStabilityCommitteePermissions
committees = append(committees, newStabilityCommittee)
} else {
newSafetyCommittee.ID = com.ID
newSafetyCommittee.Description = com.Description
newSafetyCommittee.Members = com.Members
newSafetyCommittee.Permissions = []v0_13committee.Permission{v0_13committee.SoftwareUpgradePermission{}}
newSafetyCommittee.VoteThreshold = com.VoteThreshold
newSafetyCommittee.ProposalDuration = com.ProposalDuration
committees = append(committees, newSafetyCommittee)
}
}
for _, v := range genesisState.Votes {
votes = append(votes, v0_13committee.Vote(v))
}
for _, p := range genesisState.Proposals {
newPubProp := v0_13committee.PubProposal(p.PubProposal)
newProp := v0_13committee.NewProposal(newPubProp, p.ID, p.CommitteeID, p.Deadline)
proposals = append(proposals, newProp)
}
return v0_13committee.NewGenesisState(
genesisState.NextProposalID, committees, proposals, votes)
}
func removeIndex(accs authexported.GenesisAccounts, index int) authexported.GenesisAccounts { func removeIndex(accs authexported.GenesisAccounts, index int) authexported.GenesisAccounts {
ret := make(authexported.GenesisAccounts, 0) ret := make(authexported.GenesisAccounts, 0)
ret = append(ret, accs[:index]...) ret = append(ret, accs[:index]...)

View File

@ -6,11 +6,14 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/kava-labs/kava/app" "github.com/kava-labs/kava/app"
v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11" v0_11cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_11"
v0_13committee "github.com/kava-labs/kava/x/committee"
v0_11committee "github.com/kava-labs/kava/x/committee/legacy/v0_11"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -23,7 +26,7 @@ func TestMain(m *testing.M) {
os.Exit(m.Run()) os.Exit(m.Run())
} }
func TestMigrateCdp(t *testing.T) { func TestCDP(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-4-cdp-state-block-500000.json")) bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-4-cdp-state-block-500000.json"))
require.NoError(t, err) require.NoError(t, err)
var oldGenState v0_11cdp.GenesisState var oldGenState v0_11cdp.GenesisState
@ -32,7 +35,7 @@ func TestMigrateCdp(t *testing.T) {
cdc.MustUnmarshalJSON(bz, &oldGenState) cdc.MustUnmarshalJSON(bz, &oldGenState)
}) })
newGenState := MigrateCDP(oldGenState) newGenState := CDP(oldGenState)
err = newGenState.Validate() err = newGenState.Validate()
require.NoError(t, err) require.NoError(t, err)
@ -43,7 +46,7 @@ func TestMigrateCdp(t *testing.T) {
} }
func TestMigrateAuth(t *testing.T) { func TestAuth(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-4-auth-state-block-500000.json")) bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-4-auth-state-block-500000.json"))
require.NoError(t, err) require.NoError(t, err)
var oldGenState auth.GenesisState var oldGenState auth.GenesisState
@ -51,9 +54,38 @@ func TestMigrateAuth(t *testing.T) {
require.NotPanics(t, func() { require.NotPanics(t, func() {
cdc.MustUnmarshalJSON(bz, &oldGenState) cdc.MustUnmarshalJSON(bz, &oldGenState)
}) })
newGenState := MigrateAuth(oldGenState) newGenState := Auth(oldGenState)
err = auth.ValidateGenesis(newGenState) err = auth.ValidateGenesis(newGenState)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(oldGenState.Accounts), len(newGenState.Accounts)+1) require.Equal(t, len(oldGenState.Accounts), len(newGenState.Accounts)+1)
} }
func TestCommittee(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-4-committee-state.json"))
require.NoError(t, err)
var oldGenState v0_11committee.GenesisState
cdc := codec.New()
sdk.RegisterCodec(cdc)
v0_11committee.RegisterCodec(cdc)
require.NotPanics(t, func() {
cdc.MustUnmarshalJSON(bz, &oldGenState)
})
newGenState := Committee(oldGenState)
err = newGenState.Validate()
require.NoError(t, err)
require.Equal(t, len(oldGenState.Committees), len(newGenState.Committees))
for i := 0; i < len(oldGenState.Committees); i++ {
require.Equal(t, len(oldGenState.Committees[i].Permissions), len(newGenState.Committees[i].Permissions))
}
oldSPCP := oldGenState.Committees[0].Permissions[0].(v0_11committee.SubParamChangePermission)
newSPCP := newGenState.Committees[0].Permissions[0].(v0_13committee.SubParamChangePermission)
require.Equal(t, len(oldSPCP.AllowedParams), len(newSPCP.AllowedParams))
require.Equal(t, len(oldSPCP.AllowedAssetParams), len(newSPCP.AllowedAssetParams))
require.Equal(t, len(oldSPCP.AllowedCollateralParams), len(newSPCP.AllowedCollateralParams))
require.Equal(t, len(oldSPCP.AllowedMarkets), len(newSPCP.AllowedMarkets))
}

View File

@ -0,0 +1 @@
{"committees":[{"description":"Kava Stability Committee","id":"1","members":["kava1gru35up50ql2wxhegr880qy6ynl63ujlv8gum2","kava1sc3mh3pkas5e7xd269am4xm5mp6zweyzmhjagj","kava1c9ye54e3pzwm3e0zpdlel6pnavrj9qqv6e8r4h","kava1m7p6sjqrz6mylz776ct48wj6lpnpcd0z82209d","kava1a9pmkzk570egv3sflu3uwdf3gejl7qfy9hghzl"],"permissions":[{"type":"kava/SubParamChangePermission","value":{"allowed_asset_params":[{"active":true,"coin_id":false,"denom":"bnb","limit":true,"max_swap_amount":true,"min_block_lock":true},{"active":true,"coin_id":true,"denom":"busd","limit":true,"max_swap_amount":true,"min_block_lock":true},{"active":true,"coin_id":false,"denom":"btcb","limit":true,"max_swap_amount":true,"min_block_lock":true},{"active":true,"coin_id":false,"denom":"xrpb","limit":true,"max_swap_amount":true,"min_block_lock":true}],"allowed_collateral_params":[{"auction_size":true,"conversion_factor":false,"debt_limit":true,"denom":false,"liquidation_market_id":false,"liquidation_penalty":false,"liquidation_ratio":false,"prefix":false,"spot_market_id":false,"stability_fee":true,"type":"bnb-a"},{"auction_size":true,"conversion_factor":false,"debt_limit":true,"denom":false,"liquidation_market_id":false,"liquidation_penalty":false,"liquidation_ratio":false,"prefix":false,"spot_market_id":false,"stability_fee":true,"type":"busd-a"},{"auction_size":true,"conversion_factor":false,"debt_limit":true,"denom":false,"liquidation_market_id":false,"liquidation_penalty":false,"liquidation_ratio":false,"prefix":false,"spot_market_id":false,"stability_fee":true,"type":"busd-b"},{"auction_size":true,"conversion_factor":false,"debt_limit":true,"denom":false,"liquidation_market_id":false,"liquidation_penalty":false,"liquidation_ratio":false,"prefix":false,"spot_market_id":false,"stability_fee":true,"type":"btcb-a"},{"auction_size":true,"conversion_factor":false,"debt_limit":true,"denom":false,"liquidation_market_id":false,"liquidation_penalty":false,"liquidation_ratio":false,"prefix":false,"spot_market_id":false,"stability_fee":true,"type":"xrpb-a"}],"allowed_debt_param":{"conversion_factor":false,"debt_floor":true,"denom":false,"reference_asset":false,"savings_rate":true},"allowed_markets":[{"active":true,"base_asset":false,"market_id":"bnb:usd","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"bnb:usd:30","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"btc:usd","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"btc:usd:30","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"xrp:usd","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"xrp:usd:30","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"busd:usd","oracles":false,"quote_asset":false},{"active":true,"base_asset":false,"market_id":"busd:usd:30","oracles":false,"quote_asset":false}],"allowed_params":[{"key":"BidDuration","subspace":"auction"},{"key":"Active","subspace":"harvest"},{"key":"IncrementSurplus","subspace":"auction"},{"key":"Active","subspace":"harvest"},{"key":"IncrementDebt","subspace":"auction"},{"key":"Active","subspace":"harvest"},{"key":"IncrementCollateral","subspace":"auction"},{"key":"Active","subspace":"harvest"},{"key":"AssetParams","subspace":"bep3"},{"key":"Active","subspace":"harvest"},{"key":"GlobalDebtLimit","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"SurplusThreshold","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"SurplusLot","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"DebtThreshold","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"DebtLot","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"DistributionFrequency","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"CollateralParams","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"DebtParam","subspace":"cdp"},{"key":"Active","subspace":"harvest"},{"key":"Active","subspace":"incentive"},{"key":"Active","subspace":"harvest"},{"key":"Active","subspace":"kavadist"},{"key":"Active","subspace":"harvest"},{"key":"Markets","subspace":"pricefeed"},{"key":"Active","subspace":"harvest"}]}},{"type":"kava/TextPermission","value":{}}],"proposal_duration":"604800000000000","vote_threshold":"0.500000000000000000"},{"description":"Kava Safety Committee","id":"2","members":["kava1e0agyg6eug9r62fly9sls77ycjgw8ax6xk73es"],"permissions":[{"type":"kava/SoftwareUpgradePermission","value":{}}],"proposal_duration":"604800000000000","vote_threshold":"0.500000000000000000"}],"next_proposal_id":"40","proposals":[],"votes":[]}

View File

@ -54,6 +54,7 @@ var (
GetKeyFromID = types.GetKeyFromID GetKeyFromID = types.GetKeyFromID
GetVoteKey = types.GetVoteKey GetVoteKey = types.GetVoteKey
NewAllowedCollateralParam = types.NewAllowedCollateralParam NewAllowedCollateralParam = types.NewAllowedCollateralParam
NewAllowedMoneyMarket = types.NewAllowedMoneyMarket
NewCommittee = types.NewCommittee NewCommittee = types.NewCommittee
NewCommitteeChangeProposal = types.NewCommitteeChangeProposal NewCommitteeChangeProposal = types.NewCommitteeChangeProposal
NewCommitteeDeleteProposal = types.NewCommitteeDeleteProposal NewCommitteeDeleteProposal = types.NewCommitteeDeleteProposal
@ -98,6 +99,8 @@ type (
AllowedDebtParam = types.AllowedDebtParam AllowedDebtParam = types.AllowedDebtParam
AllowedMarket = types.AllowedMarket AllowedMarket = types.AllowedMarket
AllowedMarkets = types.AllowedMarkets AllowedMarkets = types.AllowedMarkets
AllowedMoneyMarket = types.AllowedMoneyMarket
AllowedMoneyMarkets = types.AllowedMoneyMarkets
AllowedParam = types.AllowedParam AllowedParam = types.AllowedParam
AllowedParams = types.AllowedParams AllowedParams = types.AllowedParams
Committee = types.Committee Committee = types.Committee

View File

@ -484,6 +484,26 @@ type AllowedCollateralParam struct {
type AllowedCollateralParams []AllowedCollateralParam type AllowedCollateralParams []AllowedCollateralParam
// NewAllowedCollateralParam return a new AllowedCollateralParam
func NewAllowedCollateralParam(
ctype string, denom, liqRatio, debtLimit,
stabilityFee, auctionSize, liquidationPenalty,
prefix, spotMarket, liquidationMarket, conversionFactor bool) AllowedCollateralParam {
return AllowedCollateralParam{
Type: ctype,
Denom: denom,
LiquidationRatio: liqRatio,
DebtLimit: debtLimit,
StabilityFee: stabilityFee,
AuctionSize: auctionSize,
LiquidationPenalty: liquidationPenalty,
Prefix: prefix,
SpotMarketID: spotMarket,
LiquidationMarketID: liquidationMarket,
ConversionFactor: conversionFactor,
}
}
func (acps AllowedCollateralParams) Allows(current, incoming cdptypes.CollateralParams) bool { func (acps AllowedCollateralParams) Allows(current, incoming cdptypes.CollateralParams) bool {
allAllowed := true allAllowed := true
@ -566,6 +586,7 @@ func (adp AllowedDebtParam) Allows(current, incoming cdptypes.DebtParam) bool {
type AllowedAssetParams []AllowedAssetParam type AllowedAssetParams []AllowedAssetParam
// Allows implement permission interface
func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool { func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool {
allAllowed := true allAllowed := true
@ -614,19 +635,25 @@ func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) b
return allAllowed return allAllowed
} }
// AllowedAssetParam bep3 asset parameters that can be changed by committee
type AllowedAssetParam struct { type AllowedAssetParam struct {
Denom string `json:"denom" yaml:"denom"` Denom string `json:"denom" yaml:"denom"`
CoinID bool `json:"coin_id" yaml:"coin_id"` CoinID bool `json:"coin_id" yaml:"coin_id"`
Limit bool `json:"limit" yaml:"limit"` Limit bool `json:"limit" yaml:"limit"`
Active bool `json:"active" yaml:"active"` Active bool `json:"active" yaml:"active"`
MaxSwapAmount bool `json:"max_swap_amount" yaml:"max_swap_amount"`
MinBlockLock bool `json:"min_block_lock" yaml:"min_block_lock"`
} }
// Allows bep3 AssetParam parameters than can be changed by committee
func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool { func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool {
allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal
((current.CoinID == incoming.CoinID) || aap.CoinID) && ((current.CoinID == incoming.CoinID) || aap.CoinID) &&
(current.SupplyLimit.Equals(incoming.SupplyLimit) || aap.Limit) && (current.SupplyLimit.Equals(incoming.SupplyLimit) || aap.Limit) &&
((current.Active == incoming.Active) || aap.Active) ((current.Active == incoming.Active) || aap.Active) &&
((current.MaxSwapAmount.Equal(incoming.MaxSwapAmount)) || aap.MaxSwapAmount) &&
((current.MinBlockLock == incoming.MinBlockLock) || aap.MinBlockLock)
return allowed return allowed
} }
@ -796,3 +823,17 @@ func (gs GenesisState) Validate() error {
} }
return nil return nil
} }
func RegisterCodec(cdc *codec.Codec) {
// Proposals
cdc.RegisterInterface((*PubProposal)(nil), nil)
// Permissions
cdc.RegisterInterface((*Permission)(nil), nil)
cdc.RegisterConcrete(GodPermission{}, "kava/GodPermission", nil)
cdc.RegisterConcrete(SimpleParamChangePermission{}, "kava/SimpleParamChangePermission", nil)
cdc.RegisterConcrete(TextPermission{}, "kava/TextPermission", nil)
cdc.RegisterConcrete(SoftwareUpgradePermission{}, "kava/SoftwareUpgradePermission", nil)
cdc.RegisterConcrete(SubParamChangePermission{}, "kava/SubParamChangePermission", nil)
}

View File

@ -15,6 +15,7 @@ import (
bep3types "github.com/kava-labs/kava/x/bep3/types" bep3types "github.com/kava-labs/kava/x/bep3/types"
cdptypes "github.com/kava-labs/kava/x/cdp/legacy/v0_11" cdptypes "github.com/kava-labs/kava/x/cdp/legacy/v0_11"
"github.com/kava-labs/kava/x/hard"
"github.com/kava-labs/kava/x/pricefeed" "github.com/kava-labs/kava/x/pricefeed"
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types" pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
) )
@ -564,8 +565,10 @@ func (adp AllowedDebtParam) Allows(current, incoming cdptypes.DebtParam) bool {
return allowed return allowed
} }
// AllowedAssetParams slice of AllowedAssetParam
type AllowedAssetParams []AllowedAssetParam type AllowedAssetParams []AllowedAssetParam
// Allows implement permission interface
func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool { func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool {
allAllowed := true allAllowed := true
@ -614,19 +617,25 @@ func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) b
return allAllowed return allAllowed
} }
// AllowedAssetParam bep3 asset parameters that can be changed by committee
type AllowedAssetParam struct { type AllowedAssetParam struct {
Denom string `json:"denom" yaml:"denom"` Denom string `json:"denom" yaml:"denom"`
CoinID bool `json:"coin_id" yaml:"coin_id"` CoinID bool `json:"coin_id" yaml:"coin_id"`
Limit bool `json:"limit" yaml:"limit"` Limit bool `json:"limit" yaml:"limit"`
Active bool `json:"active" yaml:"active"` Active bool `json:"active" yaml:"active"`
MaxSwapAmount bool `json:"max_swap_amount" yaml:"max_swap_amount"`
MinBlockLock bool `json:"min_block_lock" yaml:"min_block_lock"`
} }
// Allows bep3 AssetParam parameters than can be changed by committee
func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool { func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool {
allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal allowed := ((aap.Denom == current.Denom) && (aap.Denom == incoming.Denom)) && // require denoms to be all equal
((current.CoinID == incoming.CoinID) || aap.CoinID) && ((current.CoinID == incoming.CoinID) || aap.CoinID) &&
(current.SupplyLimit.Equals(incoming.SupplyLimit) || aap.Limit) && (current.SupplyLimit.Equals(incoming.SupplyLimit) || aap.Limit) &&
((current.Active == incoming.Active) || aap.Active) ((current.Active == incoming.Active) || aap.Active) &&
((current.MaxSwapAmount.Equal(incoming.MaxSwapAmount)) || aap.MaxSwapAmount) &&
((current.MinBlockLock == incoming.MinBlockLock) || aap.MinBlockLock)
return allowed return allowed
} }
@ -709,6 +718,75 @@ func addressesEqual(addrs1, addrs2 []sdk.AccAddress) bool {
return areEqual return areEqual
} }
// AllowedMoneyMarket permission struct for money market parameters (hard module)
type AllowedMoneyMarket struct {
Denom string `json:"denom" yaml:"denom"`
BorrowLimit bool `json:"borrow_limit" yaml:"borrow_limit"`
SpotMarketID bool `json:"spot_market_id" yaml:"spot_market_id"`
ConversionFactor bool `json:"conversion_factor" yaml:"conversion_factor"`
InterestRateModel bool `json:"interest_rate_model" yaml:"interest_rate_model"`
ReserveFactor bool `json:"reserve_factor" yaml:"reserve_factor"`
AuctionSize bool `json:"auction_size" yaml:"auction_size"`
KeeperRewardPercentage bool `json:"keeper_reward_percentage" yaml:"keeper_reward_percentage"`
}
// Allows implement permission interface
func (amm AllowedMoneyMarket) Allows(current, incoming hard.MoneyMarket) bool {
allowed := ((amm.Denom == current.Denom) && (amm.Denom == incoming.Denom)) &&
((current.BorrowLimit.Equal(incoming.BorrowLimit)) || amm.BorrowLimit) &&
((current.SpotMarketID == incoming.SpotMarketID) || amm.SpotMarketID) &&
((current.ConversionFactor.Equal(incoming.ConversionFactor)) || amm.ConversionFactor) &&
((current.InterestRateModel.Equal(incoming.InterestRateModel)) || amm.InterestRateModel) &&
((current.KeeperRewardPercentage.Equal(incoming.KeeperRewardPercentage)) || amm.KeeperRewardPercentage)
return allowed
}
// AllowedMoneyMarkets slice of AllowedMoneyMarket
type AllowedMoneyMarkets []AllowedMoneyMarket
// Allows implement permission interface
func (amms AllowedMoneyMarkets) Allows(current, incoming hard.MoneyMarkets) bool {
allAllowed := true
if len(incoming) != len(current) {
return false
}
for _, incomingMM := range incoming {
var foundAllowedMM bool
var allowedMM AllowedMoneyMarket
for _, p := range amms {
if p.Denom != incomingMM.Denom {
continue
}
foundAllowedMM = true
allowedMM = p
}
if !foundAllowedMM {
return false
}
var foundCurrentMM bool
var currentMM hard.MoneyMarket
for _, p := range current {
if p.Denom != incomingMM.Denom {
continue
}
foundCurrentMM = true
currentMM = p
}
if !foundCurrentMM {
return false
}
allowed := allowedMM.Allows(currentMM, incomingMM)
allAllowed = allAllowed && allowed
}
return allAllowed
}
// DefaultNextProposalID is the starting poiint for proposal IDs. // DefaultNextProposalID is the starting poiint for proposal IDs.
const DefaultNextProposalID uint64 = 1 const DefaultNextProposalID uint64 = 1

View File

@ -18,45 +18,9 @@ func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
func (suite *PermissionsTestSuite) TestAllowedCollateralParams_Allows() { func (suite *PermissionsTestSuite) TestAllowedCollateralParams_Allows() {
testCPs := cdptypes.CollateralParams{ testCPs := cdptypes.CollateralParams{
{ cdptypes.NewCollateralParam("bnb", "bnb-a", d("2.0"), c("usdx", 1000000000000), d("1.000000001547125958"), i(100), d("0.05"), 0x20, "bnb:usd", "bnb:usd", d("0.01"), i(10), i(6)),
Type: "bnb-a", cdptypes.NewCollateralParam("btc", "btc-a", d("1.5"), c("usdx", 1000000000), d("1.000000001547125958"), i(1000), d("0.1"), 0x30, "btc:usd", "btc:usd", d("0.01"), i(10), i(8)),
Denom: "bnb", cdptypes.NewCollateralParam("atom", "atom-a", d("2.0"), c("usdx", 1000000000), d("1.000000001547125958"), i(1000), d("0.07"), 0x40, "atom:usd", "atom:usd", d("0.01"), i(10), i(6)),
LiquidationRatio: d("2.0"),
DebtLimit: c("usdx", 1000000000000),
StabilityFee: d("1.000000001547125958"),
LiquidationPenalty: d("0.05"),
AuctionSize: i(100),
Prefix: 0x20,
ConversionFactor: i(6),
SpotMarketID: "bnb:usd",
LiquidationMarketID: "bnb:usd",
},
{
Type: "btc-a",
Denom: "btc",
LiquidationRatio: d("1.5"),
DebtLimit: c("usdx", 1000000000),
StabilityFee: d("1.000000001547125958"),
LiquidationPenalty: d("0.10"),
AuctionSize: i(1000),
Prefix: 0x30,
ConversionFactor: i(8),
SpotMarketID: "btc:usd",
LiquidationMarketID: "btc:usd",
},
{
Type: "atom-a",
Denom: "atom",
LiquidationRatio: d("2.0"),
DebtLimit: c("usdx", 1000000000),
StabilityFee: d("1.000000001547125958"),
LiquidationPenalty: d("0.07"),
AuctionSize: i(100),
Prefix: 0x40,
ConversionFactor: i(6),
SpotMarketID: "atom:usd",
LiquidationMarketID: "atom:usd",
},
} }
updatedTestCPs := make(cdptypes.CollateralParams, len(testCPs)) updatedTestCPs := make(cdptypes.CollateralParams, len(testCPs))
updatedTestCPs[0] = testCPs[1] updatedTestCPs[0] = testCPs[1]
@ -87,17 +51,19 @@ func (suite *PermissionsTestSuite) TestAllowedCollateralParams_Allows() {
StabilityFee: true, StabilityFee: true,
}, },
{ // allow all fields { // allow all fields
Type: "atom-a", Type: "atom-a",
Denom: true, Denom: true,
LiquidationRatio: true, LiquidationRatio: true,
DebtLimit: true, DebtLimit: true,
StabilityFee: true, StabilityFee: true,
AuctionSize: true, AuctionSize: true,
LiquidationPenalty: true, LiquidationPenalty: true,
Prefix: true, Prefix: true,
SpotMarketID: true, SpotMarketID: true,
LiquidationMarketID: true, LiquidationMarketID: true,
ConversionFactor: true, ConversionFactor: true,
KeeperRewardPercentage: true,
CheckCollateralizationIndexCount: true,
}, },
}, },
current: testCPs[:2], current: testCPs[:2],
@ -113,17 +79,19 @@ func (suite *PermissionsTestSuite) TestAllowedCollateralParams_Allows() {
}, },
{ {
// allow all fields // allow all fields
Type: "btc-a", Type: "btc-a",
Denom: true, Denom: true,
LiquidationRatio: true, LiquidationRatio: true,
DebtLimit: true, DebtLimit: true,
StabilityFee: true, StabilityFee: true,
AuctionSize: true, AuctionSize: true,
LiquidationPenalty: true, LiquidationPenalty: true,
Prefix: true, Prefix: true,
SpotMarketID: true, SpotMarketID: true,
LiquidationMarketID: true, LiquidationMarketID: true,
ConversionFactor: true, ConversionFactor: true,
KeeperRewardPercentage: true,
CheckCollateralizationIndexCount: true,
}, },
}, },
current: testCPs[:2], current: testCPs[:2],
@ -429,19 +397,21 @@ func (suite *PermissionsTestSuite) TestAllowedMarkets_Allows() {
} }
func (suite *PermissionsTestSuite) TestAllowedCollateralParam_Allows() { func (suite *PermissionsTestSuite) TestAllowedCollateralParam_Allows() {
testCP := cdptypes.CollateralParam{ testCP := cdptypes.NewCollateralParam(
Type: "bnb-a", "bnb",
Denom: "bnb", "bnb-a",
LiquidationRatio: d("1.5"), d("1.5"),
DebtLimit: c("usdx", 1000000000000), c("usdx", 1000000000000),
StabilityFee: d("1.000000001547125958"), // %5 apr d("1.000000001547125958"), // %5 apr
LiquidationPenalty: d("0.05"), i(10000000000000),
AuctionSize: i(100), d("0.05"),
Prefix: 0x20, 0x20,
ConversionFactor: i(6), "bnb:usd",
SpotMarketID: "bnb:usd", "bnb:usd",
LiquidationMarketID: "bnb:usd", d("0.01"),
} i(10),
i(8),
)
newMarketIDCP := testCP newMarketIDCP := testCP
newMarketIDCP.SpotMarketID = "btc:usd" newMarketIDCP.SpotMarketID = "btc:usd"

View File

@ -9,6 +9,7 @@ import (
bep3types "github.com/kava-labs/kava/x/bep3/types" bep3types "github.com/kava-labs/kava/x/bep3/types"
cdptypes "github.com/kava-labs/kava/x/cdp/types" cdptypes "github.com/kava-labs/kava/x/cdp/types"
"github.com/kava-labs/kava/x/hard"
"github.com/kava-labs/kava/x/pricefeed" "github.com/kava-labs/kava/x/pricefeed"
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types" pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
) )
@ -38,8 +39,10 @@ type GodPermission struct{}
var _ Permission = GodPermission{} var _ Permission = GodPermission{}
// Allows implement permission interface
func (GodPermission) Allows(sdk.Context, *codec.Codec, ParamKeeper, PubProposal) bool { return true } func (GodPermission) Allows(sdk.Context, *codec.Codec, ParamKeeper, PubProposal) bool { return true }
// MarshalYAML implement yaml marshalling
func (GodPermission) MarshalYAML() (interface{}, error) { func (GodPermission) MarshalYAML() (interface{}, error) {
valueToMarshal := struct { valueToMarshal := struct {
Type string `yaml:"type"` Type string `yaml:"type"`
@ -60,6 +63,7 @@ type SimpleParamChangePermission struct {
var _ Permission = SimpleParamChangePermission{} var _ Permission = SimpleParamChangePermission{}
// Allows implement permission interface
func (perm SimpleParamChangePermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool { func (perm SimpleParamChangePermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool {
proposal, ok := p.(paramstypes.ParameterChangeProposal) proposal, ok := p.(paramstypes.ParameterChangeProposal)
if !ok { if !ok {
@ -73,6 +77,7 @@ func (perm SimpleParamChangePermission) Allows(_ sdk.Context, _ *codec.Codec, _
return true return true
} }
// MarshalYAML implement yaml marshalling
func (perm SimpleParamChangePermission) MarshalYAML() (interface{}, error) { func (perm SimpleParamChangePermission) MarshalYAML() (interface{}, error) {
valueToMarshal := struct { valueToMarshal := struct {
Type string `yaml:"type"` Type string `yaml:"type"`
@ -84,12 +89,16 @@ func (perm SimpleParamChangePermission) MarshalYAML() (interface{}, error) {
return valueToMarshal, nil return valueToMarshal, nil
} }
// AllowedParam permission type for module parameter keys
type AllowedParam struct { type AllowedParam struct {
Subspace string `json:"subspace" yaml:"subspace"` Subspace string `json:"subspace" yaml:"subspace"`
Key string `json:"key" yaml:"key"` Key string `json:"key" yaml:"key"`
} }
// AllowedParams slice of AllowedParam
type AllowedParams []AllowedParam type AllowedParams []AllowedParam
// Contains checks if a key is included in param permissions
func (allowed AllowedParams) Contains(paramChange paramstypes.ParamChange) bool { func (allowed AllowedParams) Contains(paramChange paramstypes.ParamChange) bool {
for _, p := range allowed { for _, p := range allowed {
if paramChange.Subspace == p.Subspace && paramChange.Key == p.Key { if paramChange.Subspace == p.Subspace && paramChange.Key == p.Key {
@ -108,11 +117,13 @@ type TextPermission struct{}
var _ Permission = TextPermission{} var _ Permission = TextPermission{}
// Allows implement permission interface
func (TextPermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool { func (TextPermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool {
_, ok := p.(govtypes.TextProposal) _, ok := p.(govtypes.TextProposal)
return ok return ok
} }
// MarshalYAML implement yaml marshalling
func (TextPermission) MarshalYAML() (interface{}, error) { func (TextPermission) MarshalYAML() (interface{}, error) {
valueToMarshal := struct { valueToMarshal := struct {
Type string `yaml:"type"` Type string `yaml:"type"`
@ -126,15 +137,18 @@ func (TextPermission) MarshalYAML() (interface{}, error) {
// SoftwareUpgradePermission // SoftwareUpgradePermission
// ------------------------------------------ // ------------------------------------------
// SoftwareUpgradePermission permission type for software upgrade proposals
type SoftwareUpgradePermission struct{} type SoftwareUpgradePermission struct{}
var _ Permission = SoftwareUpgradePermission{} var _ Permission = SoftwareUpgradePermission{}
// Allows implement permission interface
func (SoftwareUpgradePermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool { func (SoftwareUpgradePermission) Allows(_ sdk.Context, _ *codec.Codec, _ ParamKeeper, p PubProposal) bool {
_, ok := p.(upgrade.SoftwareUpgradeProposal) _, ok := p.(upgrade.SoftwareUpgradeProposal)
return ok return ok
} }
// MarshalYAML implement yaml marshalling
func (SoftwareUpgradePermission) MarshalYAML() (interface{}, error) { func (SoftwareUpgradePermission) MarshalYAML() (interface{}, error) {
valueToMarshal := struct { valueToMarshal := struct {
Type string `yaml:"type"` Type string `yaml:"type"`
@ -148,25 +162,28 @@ func (SoftwareUpgradePermission) MarshalYAML() (interface{}, error) {
// SubParamChangePermission // SubParamChangePermission
// ------------------------------------------ // ------------------------------------------
// ParamChangeProposal only allows changes to certain params // SubParamChangePermission permission type for allowing changes to specific sub-keys within module parameter keys
type SubParamChangePermission struct { type SubParamChangePermission struct {
AllowedParams AllowedParams `json:"allowed_params" yaml:"allowed_params"` AllowedParams AllowedParams `json:"allowed_params" yaml:"allowed_params"`
AllowedCollateralParams AllowedCollateralParams `json:"allowed_collateral_params" yaml:"allowed_collateral_params"` AllowedCollateralParams AllowedCollateralParams `json:"allowed_collateral_params" yaml:"allowed_collateral_params"`
AllowedDebtParam AllowedDebtParam `json:"allowed_debt_param" yaml:"allowed_debt_param"` AllowedDebtParam AllowedDebtParam `json:"allowed_debt_param" yaml:"allowed_debt_param"`
AllowedAssetParams AllowedAssetParams `json:"allowed_asset_params" yaml:"allowed_asset_params"` AllowedAssetParams AllowedAssetParams `json:"allowed_asset_params" yaml:"allowed_asset_params"`
AllowedMarkets AllowedMarkets `json:"allowed_markets" yaml:"allowed_markets"` AllowedMarkets AllowedMarkets `json:"allowed_markets" yaml:"allowed_markets"`
AllowedMoneyMarkets AllowedMoneyMarkets `json:"allowed_money_markets" yaml:"allowed_money_markets"`
} }
var _ Permission = SubParamChangePermission{} var _ Permission = SubParamChangePermission{}
// MarshalYAML implement yaml marshalling
func (perm SubParamChangePermission) MarshalYAML() (interface{}, error) { func (perm SubParamChangePermission) MarshalYAML() (interface{}, error) {
valueToMarshal := struct { valueToMarshal := struct {
Type string `yaml:"type"` Type string `yaml:"type" json:"type"`
AllowedParams AllowedParams `yaml:"allowed_params"` AllowedParams AllowedParams `yaml:"allowed_params" json:"allowed_params"`
AllowedCollateralParams AllowedCollateralParams `yaml:"allowed_collateral_params"` AllowedCollateralParams AllowedCollateralParams `yaml:"allowed_collateral_params" json:"allowed_collateral_params"`
AllowedDebtParam AllowedDebtParam `yaml:"allowed_debt_param"` AllowedDebtParam AllowedDebtParam `yaml:"allowed_debt_param" json:"allowed_debt_param"`
AllowedAssetParams AllowedAssetParams `yaml:"allowed_asset_params"` AllowedAssetParams AllowedAssetParams `yaml:"allowed_asset_params" json:"allowed_asset_params"`
AllowedMarkets AllowedMarkets `yaml:"allowed_markets"` AllowedMarkets AllowedMarkets `yaml:"allowed_markets" json:"allowed_markets"`
AllowedMoneyMarkets AllowedMoneyMarkets `json:"allowed_money_markets" yaml:"allowed_money_markets"`
}{ }{
Type: "param_change_permission", Type: "param_change_permission",
AllowedParams: perm.AllowedParams, AllowedParams: perm.AllowedParams,
@ -174,10 +191,12 @@ func (perm SubParamChangePermission) MarshalYAML() (interface{}, error) {
AllowedDebtParam: perm.AllowedDebtParam, AllowedDebtParam: perm.AllowedDebtParam,
AllowedAssetParams: perm.AllowedAssetParams, AllowedAssetParams: perm.AllowedAssetParams,
AllowedMarkets: perm.AllowedMarkets, AllowedMarkets: perm.AllowedMarkets,
AllowedMoneyMarkets: perm.AllowedMoneyMarkets,
} }
return valueToMarshal, nil return valueToMarshal, nil
} }
// Allows implement permission interface
func (perm SubParamChangePermission) Allows(ctx sdk.Context, appCdc *codec.Codec, pk ParamKeeper, p PubProposal) bool { func (perm SubParamChangePermission) Allows(ctx sdk.Context, appCdc *codec.Codec, pk ParamKeeper, p PubProposal) bool {
// Check pubproposal has correct type // Check pubproposal has correct type
proposal, ok := p.(paramstypes.ParameterChangeProposal) proposal, ok := p.(paramstypes.ParameterChangeProposal)
@ -318,11 +337,40 @@ func (perm SubParamChangePermission) Allows(ctx sdk.Context, appCdc *codec.Codec
} }
} }
// Check any MoneyMarket changes are allowed
var foundIncomingMMs bool
var incomingMMs hard.MoneyMarkets
for _, change := range proposal.Changes {
if !(change.Subspace == hard.ModuleName && change.Key == string(hard.KeyMoneyMarkets)) {
continue
}
foundIncomingMMs = true
if err := appCdc.UnmarshalJSON([]byte(change.Value), &incomingMMs); err != nil {
return false
}
}
if foundIncomingMMs {
subspace, found := pk.GetSubspace(hard.ModuleName)
if !found {
return false
}
var currentMMs hard.MoneyMarkets
subspace.Get(ctx, hard.KeyMoneyMarkets, &currentMMs)
mmChangesAllowed := perm.AllowedMoneyMarkets.Allows(currentMMs, incomingMMs)
if !mmChangesAllowed {
return false
}
}
return true return true
} }
// AllowedCollateralParams slice of AllowedCollateralParam
type AllowedCollateralParams []AllowedCollateralParam type AllowedCollateralParams []AllowedCollateralParam
// Allows determine if collateral params changes are permitted
func (acps AllowedCollateralParams) Allows(current, incoming cdptypes.CollateralParams) bool { func (acps AllowedCollateralParams) Allows(current, incoming cdptypes.CollateralParams) bool {
allAllowed := true allAllowed := true
@ -371,40 +419,46 @@ func (acps AllowedCollateralParams) Allows(current, incoming cdptypes.Collateral
return allAllowed return allAllowed
} }
// AllowedCollateralParam permission struct for changes to collateral parameter keys (cdp module)
type AllowedCollateralParam struct { type AllowedCollateralParam struct {
Type string `json:"type" yaml:"type"` Type string `json:"type" yaml:"type"`
Denom bool `json:"denom" yaml:"denom"` Denom bool `json:"denom" yaml:"denom"`
LiquidationRatio bool `json:"liquidation_ratio" yaml:"liquidation_ratio"` LiquidationRatio bool `json:"liquidation_ratio" yaml:"liquidation_ratio"`
DebtLimit bool `json:"debt_limit" yaml:"debt_limit"` DebtLimit bool `json:"debt_limit" yaml:"debt_limit"`
StabilityFee bool `json:"stability_fee" yaml:"stability_fee"` StabilityFee bool `json:"stability_fee" yaml:"stability_fee"`
AuctionSize bool `json:"auction_size" yaml:"auction_size"` AuctionSize bool `json:"auction_size" yaml:"auction_size"`
LiquidationPenalty bool `json:"liquidation_penalty" yaml:"liquidation_penalty"` LiquidationPenalty bool `json:"liquidation_penalty" yaml:"liquidation_penalty"`
Prefix bool `json:"prefix" yaml:"prefix"` Prefix bool `json:"prefix" yaml:"prefix"`
SpotMarketID bool `json:"spot_market_id" yaml:"spot_market_id"` SpotMarketID bool `json:"spot_market_id" yaml:"spot_market_id"`
LiquidationMarketID bool `json:"liquidation_market_id" yaml:"liquidation_market_id"` LiquidationMarketID bool `json:"liquidation_market_id" yaml:"liquidation_market_id"`
ConversionFactor bool `json:"conversion_factor" yaml:"conversion_factor"` ConversionFactor bool `json:"conversion_factor" yaml:"conversion_factor"`
KeeperRewardPercentage bool `json:"keeper_reward_percentage" yaml:"keeper_reward_percentage"`
CheckCollateralizationIndexCount bool `json:"check_collateralization_index_count" yaml:"check_collateralization_index_count"`
} }
// NewAllowedCollateralParam return a new AllowedCollateralParam // NewAllowedCollateralParam return a new AllowedCollateralParam
func NewAllowedCollateralParam( func NewAllowedCollateralParam(
ctype string, denom, liqRatio, debtLimit, ctype string, denom, liqRatio, debtLimit,
stabilityFee, auctionSize, liquidationPenalty, stabilityFee, auctionSize, liquidationPenalty,
prefix, spotMarket, liquidationMarket, conversionFactor bool) AllowedCollateralParam { prefix, spotMarket, liquidationMarket, conversionFactor, keeperReward, ltvIndexCount bool) AllowedCollateralParam {
return AllowedCollateralParam{ return AllowedCollateralParam{
Type: ctype, Type: ctype,
Denom: denom, Denom: denom,
LiquidationRatio: liqRatio, LiquidationRatio: liqRatio,
DebtLimit: debtLimit, DebtLimit: debtLimit,
StabilityFee: stabilityFee, StabilityFee: stabilityFee,
AuctionSize: auctionSize, AuctionSize: auctionSize,
LiquidationPenalty: liquidationPenalty, LiquidationPenalty: liquidationPenalty,
Prefix: prefix, Prefix: prefix,
SpotMarketID: spotMarket, SpotMarketID: spotMarket,
LiquidationMarketID: liquidationMarket, LiquidationMarketID: liquidationMarket,
ConversionFactor: conversionFactor, ConversionFactor: conversionFactor,
KeeperRewardPercentage: keeperReward,
CheckCollateralizationIndexCount: ltvIndexCount,
} }
} }
// Allows determine if collateral param changes are permitted
func (acp AllowedCollateralParam) Allows(current, incoming cdptypes.CollateralParam) bool { func (acp AllowedCollateralParam) Allows(current, incoming cdptypes.CollateralParam) bool {
allowed := ((acp.Type == current.Type) && (acp.Type == incoming.Type)) && // require collateral types to be all equal allowed := ((acp.Type == current.Type) && (acp.Type == incoming.Type)) && // require collateral types to be all equal
(current.Denom == incoming.Denom || acp.Denom) && (current.Denom == incoming.Denom || acp.Denom) &&
@ -416,10 +470,13 @@ func (acp AllowedCollateralParam) Allows(current, incoming cdptypes.CollateralPa
((current.Prefix == incoming.Prefix) || acp.Prefix) && ((current.Prefix == incoming.Prefix) || acp.Prefix) &&
((current.SpotMarketID == incoming.SpotMarketID) || acp.SpotMarketID) && ((current.SpotMarketID == incoming.SpotMarketID) || acp.SpotMarketID) &&
((current.LiquidationMarketID == incoming.LiquidationMarketID) || acp.LiquidationMarketID) && ((current.LiquidationMarketID == incoming.LiquidationMarketID) || acp.LiquidationMarketID) &&
((current.KeeperRewardPercentage.Equal(incoming.KeeperRewardPercentage)) || acp.KeeperRewardPercentage) &&
((current.CheckCollateralizationIndexCount.Equal(incoming.CheckCollateralizationIndexCount)) || acp.CheckCollateralizationIndexCount) &&
(current.ConversionFactor.Equal(incoming.ConversionFactor) || acp.ConversionFactor) (current.ConversionFactor.Equal(incoming.ConversionFactor) || acp.ConversionFactor)
return allowed return allowed
} }
// AllowedDebtParam permission struct for changes to debt parameter keys (cdp module)
type AllowedDebtParam struct { type AllowedDebtParam struct {
Denom bool `json:"denom" yaml:"denom"` Denom bool `json:"denom" yaml:"denom"`
ReferenceAsset bool `json:"reference_asset" yaml:"reference_asset"` ReferenceAsset bool `json:"reference_asset" yaml:"reference_asset"`
@ -427,6 +484,7 @@ type AllowedDebtParam struct {
DebtFloor bool `json:"debt_floor" yaml:"debt_floor"` DebtFloor bool `json:"debt_floor" yaml:"debt_floor"`
} }
// Allows determines if debt params changes are permitted
func (adp AllowedDebtParam) Allows(current, incoming cdptypes.DebtParam) bool { func (adp AllowedDebtParam) Allows(current, incoming cdptypes.DebtParam) bool {
allowed := ((current.Denom == incoming.Denom) || adp.Denom) && allowed := ((current.Denom == incoming.Denom) || adp.Denom) &&
((current.ReferenceAsset == incoming.ReferenceAsset) || adp.ReferenceAsset) && ((current.ReferenceAsset == incoming.ReferenceAsset) || adp.ReferenceAsset) &&
@ -435,8 +493,10 @@ func (adp AllowedDebtParam) Allows(current, incoming cdptypes.DebtParam) bool {
return allowed return allowed
} }
// AllowedAssetParams slice of AllowedAssetParam
type AllowedAssetParams []AllowedAssetParam type AllowedAssetParams []AllowedAssetParam
// Allows determines if asset params changes are permitted
func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool { func (aaps AllowedAssetParams) Allows(current, incoming bep3types.AssetParams) bool {
allAllowed := true allAllowed := true
@ -507,8 +567,10 @@ func (aap AllowedAssetParam) Allows(current, incoming bep3types.AssetParam) bool
return allowed return allowed
} }
// AllowedMarkets slice of AllowedMarket
type AllowedMarkets []AllowedMarket type AllowedMarkets []AllowedMarket
// Allows determines if markets params changed are permitted
func (ams AllowedMarkets) Allows(current, incoming pricefeedtypes.Markets) bool { func (ams AllowedMarkets) Allows(current, incoming pricefeedtypes.Markets) bool {
allAllowed := true allAllowed := true
@ -557,6 +619,7 @@ func (ams AllowedMarkets) Allows(current, incoming pricefeedtypes.Markets) bool
return allAllowed return allAllowed
} }
// AllowedMarket permission struct for market parameters (pricefeed module)
type AllowedMarket struct { type AllowedMarket struct {
MarketID string `json:"market_id" yaml:"market_id"` MarketID string `json:"market_id" yaml:"market_id"`
BaseAsset bool `json:"base_asset" yaml:"base_asset"` BaseAsset bool `json:"base_asset" yaml:"base_asset"`
@ -565,6 +628,7 @@ type AllowedMarket struct {
Active bool `json:"active" yaml:"active"` Active bool `json:"active" yaml:"active"`
} }
// Allows determines if market param changes are permitted
func (am AllowedMarket) Allows(current, incoming pricefeedtypes.Market) bool { func (am AllowedMarket) Allows(current, incoming pricefeedtypes.Market) bool {
allowed := ((am.MarketID == current.MarketID) && (am.MarketID == incoming.MarketID)) && // require denoms to be all equal allowed := ((am.MarketID == current.MarketID) && (am.MarketID == incoming.MarketID)) && // require denoms to be all equal
((current.BaseAsset == incoming.BaseAsset) || am.BaseAsset) && ((current.BaseAsset == incoming.BaseAsset) || am.BaseAsset) &&
@ -585,3 +649,85 @@ func addressesEqual(addrs1, addrs2 []sdk.AccAddress) bool {
} }
return areEqual return areEqual
} }
// AllowedMoneyMarket permission struct for money market parameters (hard module)
type AllowedMoneyMarket struct {
Denom string `json:"denom" yaml:"denom"`
BorrowLimit bool `json:"borrow_limit" yaml:"borrow_limit"`
SpotMarketID bool `json:"spot_market_id" yaml:"spot_market_id"`
ConversionFactor bool `json:"conversion_factor" yaml:"conversion_factor"`
InterestRateModel bool `json:"interest_rate_model" yaml:"interest_rate_model"`
ReserveFactor bool `json:"reserve_factor" yaml:"reserve_factor"`
KeeperRewardPercentage bool `json:"keeper_reward_percentage" yaml:"keeper_reward_percentage"`
}
// NewAllowedMoneyMarket returns a new AllowedMoneyMarket
func NewAllowedMoneyMarket(denom string, bl, sm, cf, irm, rf, kr bool) AllowedMoneyMarket {
return AllowedMoneyMarket{
Denom: denom,
BorrowLimit: bl,
SpotMarketID: sm,
ConversionFactor: cf,
InterestRateModel: irm,
ReserveFactor: rf,
KeeperRewardPercentage: kr,
}
}
// Allows determines if money market param changes are permitted
func (amm AllowedMoneyMarket) Allows(current, incoming hard.MoneyMarket) bool {
allowed := ((amm.Denom == current.Denom) && (amm.Denom == incoming.Denom)) &&
((current.BorrowLimit.Equal(incoming.BorrowLimit)) || amm.BorrowLimit) &&
((current.SpotMarketID == incoming.SpotMarketID) || amm.SpotMarketID) &&
((current.ConversionFactor.Equal(incoming.ConversionFactor)) || amm.ConversionFactor) &&
((current.InterestRateModel.Equal(incoming.InterestRateModel)) || amm.InterestRateModel) &&
((current.ReserveFactor.Equal(incoming.ReserveFactor)) || amm.ReserveFactor) &&
((current.KeeperRewardPercentage.Equal(incoming.KeeperRewardPercentage)) || amm.KeeperRewardPercentage)
return allowed
}
// AllowedMoneyMarkets slice of AllowedMoneyMarket
type AllowedMoneyMarkets []AllowedMoneyMarket
// Allows determins if money market params changes are permitted
func (amms AllowedMoneyMarkets) Allows(current, incoming hard.MoneyMarkets) bool {
allAllowed := true
if len(incoming) != len(current) {
return false
}
for _, incomingMM := range incoming {
var foundAllowedMM bool
var allowedMM AllowedMoneyMarket
for _, p := range amms {
if p.Denom != incomingMM.Denom {
continue
}
foundAllowedMM = true
allowedMM = p
}
if !foundAllowedMM {
return false
}
var foundCurrentMM bool
var currentMM hard.MoneyMarket
for _, p := range current {
if p.Denom != incomingMM.Denom {
continue
}
foundCurrentMM = true
currentMM = p
}
if !foundCurrentMM {
return false
}
allowed := allowedMM.Allows(currentMM, incomingMM)
allAllowed = allAllowed && allowed
}
return allAllowed
}