Cdp migration (#663)

* draft kava-3 to kava-4 cdp migration

* fix: use starting cdp id from the old genesis state

* update auction size for xrp
This commit is contained in:
Kevin Davis 2020-09-30 18:58:50 -04:00 committed by GitHub
parent c416423412
commit 056f9c0cf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 10656 additions and 125 deletions

View File

@ -7,6 +7,8 @@ import (
v0_11bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_11"
v0_9bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
v0_11cdp "github.com/kava-labs/kava/x/cdp"
v0_9cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_9"
v0_11incentive "github.com/kava-labs/kava/x/incentive"
v0_9incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_9"
v0_11pricefeed "github.com/kava-labs/kava/x/pricefeed"
@ -70,6 +72,52 @@ func MigrateBep3(oldGenState v0_9bep3.GenesisState) v0_11bep3.GenesisState {
}
}
// MigrateCDP migrates from a v0.9 (or v0.10) cdp genesis state to a v0.11 cdp genesis state
func MigrateCDP(oldGenState v0_9cdp.GenesisState) v0_11cdp.GenesisState {
var newCDPs v0_11cdp.CDPs
var newDeposits v0_11cdp.Deposits
var newCollateralParams v0_11cdp.CollateralParams
newStartingID := oldGenState.StartingCdpID
for _, cdp := range oldGenState.CDPs {
newCDP := v0_11cdp.NewCDPWithFees(cdp.ID, cdp.Owner, cdp.Collateral, "bnb-a", cdp.Principal, cdp.AccumulatedFees, cdp.FeesUpdated)
newCDPs = append(newCDPs, newCDP)
}
for _, dep := range oldGenState.Deposits {
newDep := v0_11cdp.NewDeposit(dep.CdpID, dep.Depositor, dep.Amount)
newDeposits = append(newDeposits, newDep)
}
for _, cp := range oldGenState.Params.CollateralParams {
newCollateralParam := v0_11cdp.NewCollateralParam(cp.Denom, "bnb-a", cp.LiquidationRatio, cp.DebtLimit, cp.StabilityFee, cp.AuctionSize, cp.LiquidationPenalty, 0x01, cp.SpotMarketID, cp.LiquidationMarketID, cp.ConversionFactor)
newCollateralParams = append(newCollateralParams, newCollateralParam)
}
btcbCollateralParam := v0_11cdp.NewCollateralParam("btcb", "btcb-a", sdk.MustNewDecFromStr("1.5"), sdk.NewCoin("usdx", sdk.NewInt(100000000000)), sdk.MustNewDecFromStr("1.000000001547125958"), sdk.NewInt(100000000), sdk.MustNewDecFromStr("0.075000000000000000"), 0x02, "btc:usd", "btc:usd:30", sdk.NewInt(8))
busdaCollateralParam := v0_11cdp.NewCollateralParam("busd", "busd-a", sdk.MustNewDecFromStr("1.01"), sdk.NewCoin("usdx", sdk.NewInt(3000000000000)), sdk.OneDec(), sdk.NewInt(1000000000000), sdk.MustNewDecFromStr("0.075000000000000000"), 0x03, "busd:usd", "busd:usd:30", sdk.NewInt(8))
busdbCollateralParam := v0_11cdp.NewCollateralParam("busd", "busd-b", sdk.MustNewDecFromStr("1.1"), sdk.NewCoin("usdx", sdk.NewInt(1000000000000)), sdk.MustNewDecFromStr("1.000000012857214317"), sdk.NewInt(1000000000000), sdk.MustNewDecFromStr("0.075000000000000000"), 0x04, "busd:usd", "busd:usd:30", sdk.NewInt(8))
xrpbCollateralParam := v0_11cdp.NewCollateralParam("xrpb", "xrpb-a", sdk.MustNewDecFromStr("1.5"), sdk.NewCoin("usdx", sdk.NewInt(100000000000)), sdk.MustNewDecFromStr("1.000000001547125958"), sdk.NewInt(4000000000000), sdk.MustNewDecFromStr("0.075000000000000000"), 0x05, "xrp:usd", "xrp:usd:30", sdk.NewInt(8))
newCollateralParams = append(newCollateralParams, btcbCollateralParam, busdaCollateralParam, busdbCollateralParam, xrpbCollateralParam)
oldDebtParam := oldGenState.Params.DebtParam
newDebtParam := v0_11cdp.NewDebtParam(oldDebtParam.Denom, oldDebtParam.ReferenceAsset, oldDebtParam.ConversionFactor, oldDebtParam.DebtFloor, oldDebtParam.SavingsRate)
newGlobalDebtLimit := oldGenState.Params.GlobalDebtLimit.Add(btcbCollateralParam.DebtLimit).Add(busdaCollateralParam.DebtLimit).Add(busdbCollateralParam.DebtLimit).Add(xrpbCollateralParam.DebtLimit)
newParams := v0_11cdp.NewParams(newGlobalDebtLimit, newCollateralParams, newDebtParam, oldGenState.Params.SurplusAuctionThreshold, oldGenState.Params.SurplusAuctionLot, oldGenState.Params.DebtAuctionThreshold, oldGenState.Params.DebtAuctionLot, oldGenState.Params.SavingsDistributionFrequency, false)
return v0_11cdp.NewGenesisState(
newParams,
newCDPs,
newDeposits,
newStartingID,
oldGenState.DebtDenom,
oldGenState.GovDenom,
oldGenState.PreviousDistributionTime,
sdk.ZeroInt(),
)
}
// MigrateIncentive migrates from a v0.9 (or v0.10) incentive genesis state to a v0.11 incentive genesis state
func MigrateIncentive(oldGenState v0_9incentive.GenesisState) v0_11incentive.GenesisState {
var newRewards v0_11incentive.Rewards

View File

@ -12,6 +12,7 @@ import (
"github.com/kava-labs/kava/app"
v0_9bep3 "github.com/kava-labs/kava/x/bep3/legacy/v0_9"
v0_9cdp "github.com/kava-labs/kava/x/cdp/legacy/v0_9"
v0_9incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_9"
v0_9pricefeed "github.com/kava-labs/kava/x/pricefeed/legacy/v0_9"
)
@ -38,6 +39,19 @@ func TestMigrateBep3(t *testing.T) {
require.NoError(t, err)
}
func TestMigrateCdp(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "cdp-v09.json"))
require.NoError(t, err)
var oldGenState v0_9cdp.GenesisState
cdc := app.MakeCodec()
require.NotPanics(t, func() {
cdc.MustUnmarshalJSON(bz, &oldGenState)
})
newGenState := MigrateCDP(oldGenState)
err = newGenState.Validate()
require.NoError(t, err)
}
func TestMigrateIncentive(t *testing.T) {
bz, err := ioutil.ReadFile(filepath.Join("testdata", "incentive-v09.json"))
require.NoError(t, err)

9821
migrate/v0_11/testdata/cdp-v09.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,168 +1,180 @@
package cdp
// DO NOT EDIT - generated by aliasgen tool (github.com/rhuairahrighairidh/aliasgen)
import (
"github.com/kava-labs/kava/x/cdp/keeper"
"github.com/kava-labs/kava/x/cdp/types"
)
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/kava-labs/kava/x/cdp/keeper
// ALIASGEN: github.com/kava-labs/kava/x/cdp/types
const (
BaseDigitFactor = keeper.BaseDigitFactor
EventTypeCreateCdp = types.EventTypeCreateCdp
EventTypeCdpDeposit = types.EventTypeCdpDeposit
EventTypeCdpDraw = types.EventTypeCdpDraw
EventTypeCdpRepay = types.EventTypeCdpRepay
EventTypeCdpClose = types.EventTypeCdpClose
EventTypeCdpWithdrawal = types.EventTypeCdpWithdrawal
EventTypeCdpLiquidation = types.EventTypeCdpLiquidation
EventTypeBeginBlockerFatal = types.EventTypeBeginBlockerFatal
AttributeKeyCdpID = types.AttributeKeyCdpID
AttributeKeyDeposit = types.AttributeKeyDeposit
AttributeValueCategory = types.AttributeValueCategory
AttributeKeyError = types.AttributeKeyError
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
AttributeValueCategory = types.AttributeValueCategory
DefaultParamspace = types.DefaultParamspace
EventTypeBeginBlockerFatal = types.EventTypeBeginBlockerFatal
EventTypeCdpClose = types.EventTypeCdpClose
EventTypeCdpDeposit = types.EventTypeCdpDeposit
EventTypeCdpDraw = types.EventTypeCdpDraw
EventTypeCdpLiquidation = types.EventTypeCdpLiquidation
EventTypeCdpRepay = types.EventTypeCdpRepay
EventTypeCdpWithdrawal = types.EventTypeCdpWithdrawal
EventTypeCreateCdp = types.EventTypeCreateCdp
LiquidatorMacc = types.LiquidatorMacc
SavingsRateMacc = types.SavingsRateMacc
ModuleName = types.ModuleName
QuerierRoute = types.QuerierRoute
QueryGetAccounts = types.QueryGetAccounts
QueryGetCdp = types.QueryGetCdp
QueryGetCdpDeposits = types.QueryGetCdpDeposits
QueryGetCdps = types.QueryGetCdps
QueryGetCdpsByCollateralType = types.QueryGetCdpsByCollateralType
QueryGetCdpsByCollateralization = types.QueryGetCdpsByCollateralization
QueryGetParams = types.QueryGetParams
RestOwner = types.RestOwner
QueryGetSavingsRateDistributed = types.QueryGetSavingsRateDistributed
RestCollateralType = types.RestCollateralType
RestOwner = types.RestOwner
RestRatio = types.RestRatio
RouterKey = types.RouterKey
SavingsRateMacc = types.SavingsRateMacc
StoreKey = types.StoreKey
)
var (
// functions aliases
// function aliases
FilterCDPs = keeper.FilterCDPs
FindIntersection = keeper.FindIntersection
NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
NewCDP = types.NewCDP
NewAugmentedCDP = types.NewAugmentedCDP
RegisterCodec = types.RegisterCodec
NewDeposit = types.NewDeposit
NewGenesisState = types.NewGenesisState
CdpKey = types.CdpKey
CollateralRatioBytes = types.CollateralRatioBytes
CollateralRatioIterKey = types.CollateralRatioIterKey
CollateralRatioKey = types.CollateralRatioKey
DefaultGenesisState = types.DefaultGenesisState
DefaultParams = types.DefaultParams
DenomIterKey = types.DenomIterKey
DepositIterKey = types.DepositIterKey
DepositKey = types.DepositKey
GetCdpIDBytes = types.GetCdpIDBytes
GetCdpIDFromBytes = types.GetCdpIDFromBytes
CdpKey = types.CdpKey
SplitCdpKey = types.SplitCdpKey
DenomIterKey = types.DenomIterKey
SplitDenomIterKey = types.SplitDenomIterKey
DepositKey = types.DepositKey
SplitDepositKey = types.SplitDepositKey
DepositIterKey = types.DepositIterKey
SplitDepositIterKey = types.SplitDepositIterKey
CollateralRatioBytes = types.CollateralRatioBytes
CollateralRatioKey = types.CollateralRatioKey
SplitCollateralRatioKey = types.SplitCollateralRatioKey
CollateralRatioIterKey = types.CollateralRatioIterKey
SplitCollateralRatioIterKey = types.SplitCollateralRatioIterKey
NewAugmentedCDP = types.NewAugmentedCDP
NewCDP = types.NewCDP
NewCDPWithFees = types.NewCDPWithFees
NewCollateralParam = types.NewCollateralParam
NewDebtParam = types.NewDebtParam
NewDeposit = types.NewDeposit
NewGenesisState = types.NewGenesisState
NewMsgCreateCDP = types.NewMsgCreateCDP
NewMsgDeposit = types.NewMsgDeposit
NewMsgWithdraw = types.NewMsgWithdraw
NewMsgDrawDebt = types.NewMsgDrawDebt
NewMsgRepayDebt = types.NewMsgRepayDebt
NewMsgWithdraw = types.NewMsgWithdraw
NewParams = types.NewParams
DefaultParams = types.DefaultParams
ParamKeyTable = types.ParamKeyTable
NewQueryCdpsParams = types.NewQueryCdpsParams
NewQueryCdpParams = types.NewQueryCdpParams
NewQueryCdpDeposits = types.NewQueryCdpDeposits
NewQueryCdpParams = types.NewQueryCdpParams
NewQueryCdpsByCollateralTypeParams = types.NewQueryCdpsByCollateralTypeParams
NewQueryCdpsByRatioParams = types.NewQueryCdpsByRatioParams
ValidSortableDec = types.ValidSortableDec
SortableDecBytes = types.SortableDecBytes
NewQueryCdpsParams = types.NewQueryCdpsParams
ParamKeyTable = types.ParamKeyTable
ParseDecBytes = types.ParseDecBytes
RegisterCodec = types.RegisterCodec
RelativePow = types.RelativePow
SortableDecBytes = types.SortableDecBytes
SplitCdpKey = types.SplitCdpKey
SplitCollateralRatioIterKey = types.SplitCollateralRatioIterKey
SplitCollateralRatioKey = types.SplitCollateralRatioKey
SplitDenomIterKey = types.SplitDenomIterKey
SplitDepositIterKey = types.SplitDepositIterKey
SplitDepositKey = types.SplitDepositKey
ValidSortableDec = types.ValidSortableDec
// variable aliases
ModuleCdc = types.ModuleCdc
ErrCdpAlreadyExists = types.ErrCdpAlreadyExists
ErrInvalidCollateralLength = types.ErrInvalidCollateralLength
ErrCollateralNotSupported = types.ErrCollateralNotSupported
ErrDebtNotSupported = types.ErrDebtNotSupported
ErrExceedsDebtLimit = types.ErrExceedsDebtLimit
ErrInvalidCollateralRatio = types.ErrInvalidCollateralRatio
ErrCdpNotFound = types.ErrCdpNotFound
ErrDepositNotFound = types.ErrDepositNotFound
ErrInvalidDeposit = types.ErrInvalidDeposit
ErrInvalidPayment = types.ErrInvalidPayment
ErrDepositNotAvailable = types.ErrDepositNotAvailable
ErrInvalidWithdrawAmount = types.ErrInvalidWithdrawAmount
ErrCdpNotAvailable = types.ErrCdpNotAvailable
ErrBelowDebtFloor = types.ErrBelowDebtFloor
ErrLoadingAugmentedCDP = types.ErrLoadingAugmentedCDP
ErrInvalidDebtRequest = types.ErrInvalidDebtRequest
ErrDenomPrefixNotFound = types.ErrDenomPrefixNotFound
ErrPricefeedDown = types.ErrPricefeedDown
CdpIDKey = types.CdpIDKey
CdpIDKeyPrefix = types.CdpIDKeyPrefix
CdpKeyPrefix = types.CdpKeyPrefix
CollateralRatioIndexPrefix = types.CollateralRatioIndexPrefix
CdpIDKey = types.CdpIDKey
DebtDenomKey = types.DebtDenomKey
GovDenomKey = types.GovDenomKey
DepositKeyPrefix = types.DepositKeyPrefix
PrincipalKeyPrefix = types.PrincipalKeyPrefix
PreviousDistributionTimeKey = types.PreviousDistributionTimeKey
PricefeedStatusKeyPrefix = types.PricefeedStatusKeyPrefix
KeyGlobalDebtLimit = types.KeyGlobalDebtLimit
KeyCollateralParams = types.KeyCollateralParams
KeyDebtParam = types.KeyDebtParam
KeyDistributionFrequency = types.KeyDistributionFrequency
KeyCircuitBreaker = types.KeyCircuitBreaker
KeyDebtThreshold = types.KeyDebtThreshold
KeyDebtLot = types.KeyDebtLot
KeySurplusThreshold = types.KeySurplusThreshold
KeySurplusLot = types.KeySurplusLot
DefaultGlobalDebt = types.DefaultGlobalDebt
DefaultCdpStartingID = types.DefaultCdpStartingID
DefaultCircuitBreaker = types.DefaultCircuitBreaker
DefaultCollateralParams = types.DefaultCollateralParams
DefaultDebtParam = types.DefaultDebtParam
DefaultCdpStartingID = types.DefaultCdpStartingID
DefaultDebtDenom = types.DefaultDebtDenom
DefaultGovDenom = types.DefaultGovDenom
DefaultStableDenom = types.DefaultStableDenom
DefaultSurplusThreshold = types.DefaultSurplusThreshold
DefaultDebtThreshold = types.DefaultDebtThreshold
DefaultSurplusLot = types.DefaultSurplusLot
DefaultDebtLot = types.DefaultDebtLot
DefaultDebtParam = types.DefaultDebtParam
DefaultDebtThreshold = types.DefaultDebtThreshold
DefaultGlobalDebt = types.DefaultGlobalDebt
DefaultGovDenom = types.DefaultGovDenom
DefaultPreviousDistributionTime = types.DefaultPreviousDistributionTime
DefaultSavingsDistributionFrequency = types.DefaultSavingsDistributionFrequency
DefaultSavingsRateDistributed = types.DefaultSavingsRateDistributed
DefaultStableDenom = types.DefaultStableDenom
DefaultSurplusLot = types.DefaultSurplusLot
DefaultSurplusThreshold = types.DefaultSurplusThreshold
DepositKeyPrefix = types.DepositKeyPrefix
ErrBelowDebtFloor = types.ErrBelowDebtFloor
ErrCdpAlreadyExists = types.ErrCdpAlreadyExists
ErrCdpNotAvailable = types.ErrCdpNotAvailable
ErrCdpNotFound = types.ErrCdpNotFound
ErrCollateralNotSupported = types.ErrCollateralNotSupported
ErrDebtNotSupported = types.ErrDebtNotSupported
ErrDenomPrefixNotFound = types.ErrDenomPrefixNotFound
ErrDepositNotAvailable = types.ErrDepositNotAvailable
ErrDepositNotFound = types.ErrDepositNotFound
ErrExceedsDebtLimit = types.ErrExceedsDebtLimit
ErrInvalidCollateral = types.ErrInvalidCollateral
ErrInvalidCollateralLength = types.ErrInvalidCollateralLength
ErrInvalidCollateralRatio = types.ErrInvalidCollateralRatio
ErrInvalidDebtRequest = types.ErrInvalidDebtRequest
ErrInvalidDeposit = types.ErrInvalidDeposit
ErrInvalidPayment = types.ErrInvalidPayment
ErrInvalidWithdrawAmount = types.ErrInvalidWithdrawAmount
ErrLoadingAugmentedCDP = types.ErrLoadingAugmentedCDP
ErrPricefeedDown = types.ErrPricefeedDown
GovDenomKey = types.GovDenomKey
KeyCircuitBreaker = types.KeyCircuitBreaker
KeyCollateralParams = types.KeyCollateralParams
KeyDebtLot = types.KeyDebtLot
KeyDebtParam = types.KeyDebtParam
KeyDebtThreshold = types.KeyDebtThreshold
KeyDistributionFrequency = types.KeyDistributionFrequency
KeyGlobalDebtLimit = types.KeyGlobalDebtLimit
KeySavingsRateDistributed = types.KeySavingsRateDistributed
KeySurplusLot = types.KeySurplusLot
KeySurplusThreshold = types.KeySurplusThreshold
MaxSortableDec = types.MaxSortableDec
ModuleCdc = types.ModuleCdc
PreviousDistributionTimeKey = types.PreviousDistributionTimeKey
PricefeedStatusKeyPrefix = types.PricefeedStatusKeyPrefix
PrincipalKeyPrefix = types.PrincipalKeyPrefix
SavingsRateDistributedKey = types.SavingsRateDistributedKey
)
type (
Keeper = keeper.Keeper
CDP = types.CDP
CDPs = types.CDPs
AccountKeeper = types.AccountKeeper
AuctionKeeper = types.AuctionKeeper
AugmentedCDP = types.AugmentedCDP
AugmentedCDPs = types.AugmentedCDPs
CDP = types.CDP
CDPs = types.CDPs
CollateralParam = types.CollateralParam
CollateralParams = types.CollateralParams
DebtParam = types.DebtParam
DebtParams = types.DebtParams
Deposit = types.Deposit
Deposits = types.Deposits
GenesisState = types.GenesisState
MsgCreateCDP = types.MsgCreateCDP
MsgDeposit = types.MsgDeposit
MsgWithdraw = types.MsgWithdraw
MsgDrawDebt = types.MsgDrawDebt
MsgRepayDebt = types.MsgRepayDebt
MsgWithdraw = types.MsgWithdraw
Params = types.Params
CollateralParam = types.CollateralParam
CollateralParams = types.CollateralParams
DebtParam = types.DebtParam
DebtParams = types.DebtParams
QueryCdpsParams = types.QueryCdpsParams
QueryCdpParams = types.QueryCdpParams
PricefeedKeeper = types.PricefeedKeeper
QueryCdpDeposits = types.QueryCdpDeposits
QueryCdpParams = types.QueryCdpParams
QueryCdpsByCollateralTypeParams = types.QueryCdpsByCollateralTypeParams
QueryCdpsByRatioParams = types.QueryCdpsByRatioParams
QueryCdpsParams = types.QueryCdpsParams
SupplyKeeper = types.SupplyKeeper
)

595
x/cdp/legacy/v0_11/types.go Normal file
View File

@ -0,0 +1,595 @@
package v0_11
import (
"errors"
"fmt"
"strings"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
stabilityFeeMax = sdk.MustNewDecFromStr("1.000000051034942716") // 500% APR
minCollateralPrefix = 0
maxCollateralPrefix = 255
)
// CDP is the state of a single collateralized debt position.
type CDP struct {
ID uint64 `json:"id" yaml:"id"` // unique id for cdp
Owner sdk.AccAddress `json:"owner" yaml:"owner"` // Account that authorizes changes to the CDP
Type string `json:"type" yaml:"type"`
Collateral sdk.Coin `json:"collateral" yaml:"collateral"` // Amount of collateral stored in this CDP
Principal sdk.Coin `json:"principal" yaml:"principal"`
AccumulatedFees sdk.Coin `json:"accumulated_fees" yaml:"accumulated_fees"`
FeesUpdated time.Time `json:"fees_updated" yaml:"fees_updated"` // Amount of stable coin drawn from this CDP
}
// NewCDP creates a new CDP object
func NewCDP(id uint64, owner sdk.AccAddress, collateral sdk.Coin, collateralType string, principal, fees sdk.Coin, time time.Time) CDP {
return CDP{
ID: id,
Owner: owner,
Type: collateralType,
Collateral: collateral,
Principal: principal,
AccumulatedFees: fees,
FeesUpdated: time,
}
}
func (cdp CDP) Validate() error {
if cdp.ID == 0 {
return errors.New("cdp id cannot be 0")
}
if cdp.Owner.Empty() {
return errors.New("cdp owner cannot be empty")
}
if !cdp.Collateral.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "collateral %s", cdp.Collateral)
}
if !cdp.Principal.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "principal %s", cdp.Principal)
}
if !cdp.AccumulatedFees.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "accumulated fees %s", cdp.AccumulatedFees)
}
if cdp.FeesUpdated.IsZero() {
return errors.New("cdp updated fee time cannot be zero")
}
if strings.TrimSpace(cdp.Type) == "" {
return fmt.Errorf("cdp type cannot be empty")
}
return nil
}
// String implements fmt.stringer
func (cdp CDP) String() string {
return strings.TrimSpace(fmt.Sprintf(`CDP:
Owner: %s
ID: %d
Collateral Type: %s
Collateral: %s
Principal: %s
AccumulatedFees: %s
Fees Last Updated: %s`,
cdp.Owner,
cdp.ID,
cdp.Type,
cdp.Collateral,
cdp.Principal,
cdp.AccumulatedFees,
cdp.FeesUpdated,
))
}
// CDPs a collection of CDP objects
type CDPs []CDP
// Validate validates each CDP
func (cdps CDPs) Validate() error {
for _, cdp := range cdps {
if err := cdp.Validate(); err != nil {
return err
}
}
return nil
}
// Deposit defines an amount of coins deposited by an account to a cdp
type Deposit struct {
CdpID uint64 `json:"cdp_id" yaml:"cdp_id"` // cdpID of the cdp
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"` // Address of the depositor
Amount sdk.Coin `json:"amount" yaml:"amount"` // Deposit amount
}
// NewDeposit creates a new Deposit object
func NewDeposit(cdpID uint64, depositor sdk.AccAddress, amount sdk.Coin) Deposit {
return Deposit{cdpID, depositor, amount}
}
// Validate performs a basic validation of the deposit fields.
func (d Deposit) Validate() error {
if d.CdpID == 0 {
return errors.New("deposit's cdp id cannot be 0")
}
if d.Depositor.Empty() {
return errors.New("depositor cannot be empty")
}
if !d.Amount.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "deposit %s", d.Amount)
}
return nil
}
// Deposits a collection of Deposit objects
type Deposits []Deposit
// Validate validates each deposit
func (ds Deposits) Validate() error {
for _, d := range ds {
if err := d.Validate(); err != nil {
return err
}
}
return nil
}
// Params governance parameters for cdp module
type Params struct {
CollateralParams CollateralParams `json:"collateral_params" yaml:"collateral_params"`
DebtParam DebtParam `json:"debt_param" yaml:"debt_param"`
GlobalDebtLimit sdk.Coin `json:"global_debt_limit" yaml:"global_debt_limit"`
SurplusAuctionThreshold sdk.Int `json:"surplus_auction_threshold" yaml:"surplus_auction_threshold"`
SurplusAuctionLot sdk.Int `json:"surplus_auction_lot" yaml:"surplus_auction_lot"`
DebtAuctionThreshold sdk.Int `json:"debt_auction_threshold" yaml:"debt_auction_threshold"`
DebtAuctionLot sdk.Int `json:"debt_auction_lot" yaml:"debt_auction_lot"`
SavingsDistributionFrequency time.Duration `json:"savings_distribution_frequency" yaml:"savings_distribution_frequency"`
CircuitBreaker bool `json:"circuit_breaker" yaml:"circuit_breaker"`
}
// NewParams returns a new params object
func NewParams(
debtLimit sdk.Coin, collateralParams CollateralParams, debtParam DebtParam, surplusThreshold,
surplusLot, debtThreshold, debtLot sdk.Int, distributionFreq time.Duration, breaker bool,
) Params {
return Params{
GlobalDebtLimit: debtLimit,
CollateralParams: collateralParams,
DebtParam: debtParam,
SurplusAuctionThreshold: surplusThreshold,
SurplusAuctionLot: surplusLot,
DebtAuctionThreshold: debtThreshold,
DebtAuctionLot: debtLot,
SavingsDistributionFrequency: distributionFreq,
CircuitBreaker: breaker,
}
}
// String implements fmt.Stringer
func (p Params) String() string {
return fmt.Sprintf(`Params:
Global Debt Limit: %s
Collateral Params: %s
Debt Params: %s
Surplus Auction Threshold: %s
Surplus Auction Lot: %s
Debt Auction Threshold: %s
Debt Auction Lot: %s
Savings Distribution Frequency: %s
Circuit Breaker: %t`,
p.GlobalDebtLimit, p.CollateralParams, p.DebtParam, p.SurplusAuctionThreshold, p.SurplusAuctionLot,
p.DebtAuctionThreshold, p.DebtAuctionLot, p.SavingsDistributionFrequency, p.CircuitBreaker,
)
}
// CollateralParam governance parameters for each collateral type within the cdp module
type CollateralParam struct {
Denom string `json:"denom" yaml:"denom"` // Coin name of collateral type
Type string `json:"type" yaml:"type"`
LiquidationRatio sdk.Dec `json:"liquidation_ratio" yaml:"liquidation_ratio"` // The ratio (Collateral (priced in stable coin) / Debt) under which a CDP will be liquidated
DebtLimit sdk.Coin `json:"debt_limit" yaml:"debt_limit"` // Maximum amount of debt allowed to be drawn from this collateral type
StabilityFee sdk.Dec `json:"stability_fee" yaml:"stability_fee"` // per second stability fee for loans opened using this collateral
AuctionSize sdk.Int `json:"auction_size" yaml:"auction_size"` // Max amount of collateral to sell off in any one auction.
LiquidationPenalty sdk.Dec `json:"liquidation_penalty" yaml:"liquidation_penalty"` // percentage penalty (between [0, 1]) applied to a cdp if it is liquidated
Prefix byte `json:"prefix" yaml:"prefix"`
SpotMarketID string `json:"spot_market_id" yaml:"spot_market_id"` // marketID of the spot price of the asset from the pricefeed - used for opening CDPs, depositing, withdrawing
LiquidationMarketID string `json:"liquidation_market_id" yaml:"liquidation_market_id"` // marketID of the pricefeed used for liquidation
ConversionFactor sdk.Int `json:"conversion_factor" yaml:"conversion_factor"` // factor for converting internal units to one base unit of collateral
}
// NewCollateralParam returns a new CollateralParam
func NewCollateralParam(denom, ctype string, liqRatio sdk.Dec, debtLimit sdk.Coin, stabilityFee sdk.Dec, auctionSize sdk.Int, liqPenalty sdk.Dec, prefix byte, spotMarketID, liquidationMarketID string, conversionFactor sdk.Int) CollateralParam {
return CollateralParam{
Denom: denom,
Type: ctype,
LiquidationRatio: liqRatio,
DebtLimit: debtLimit,
StabilityFee: stabilityFee,
AuctionSize: auctionSize,
LiquidationPenalty: liqPenalty,
Prefix: prefix,
SpotMarketID: spotMarketID,
LiquidationMarketID: liquidationMarketID,
ConversionFactor: conversionFactor,
}
}
// String implements fmt.Stringer
func (cp CollateralParam) String() string {
return fmt.Sprintf(`Collateral:
Denom: %s
Type: %s
Liquidation Ratio: %s
Stability Fee: %s
Liquidation Penalty: %s
Debt Limit: %s
Auction Size: %s
Prefix: %b
Spot Market ID: %s
Liquidation Market ID: %s
Conversion Factor: %s`,
cp.Denom, cp.Type, cp.LiquidationRatio, cp.StabilityFee, cp.LiquidationPenalty, cp.DebtLimit, cp.AuctionSize, cp.Prefix, cp.SpotMarketID, cp.LiquidationMarketID, cp.ConversionFactor)
}
// CollateralParams array of CollateralParam
type CollateralParams []CollateralParam
// String implements fmt.Stringer
func (cps CollateralParams) String() string {
out := "Collateral Params\n"
for _, cp := range cps {
out += fmt.Sprintf("%s\n", cp)
}
return out
}
// DebtParam governance params for debt assets
type DebtParam struct {
Denom string `json:"denom" yaml:"denom"`
ReferenceAsset string `json:"reference_asset" yaml:"reference_asset"`
ConversionFactor sdk.Int `json:"conversion_factor" yaml:"conversion_factor"`
DebtFloor sdk.Int `json:"debt_floor" yaml:"debt_floor"` // minimum active loan size, used to prevent dust
SavingsRate sdk.Dec `json:"savings_rate" yaml:"savings_rate"` // the percentage of stability fees that are redirected to savings rate
}
// NewDebtParam returns a new DebtParam
func NewDebtParam(denom, refAsset string, conversionFactor, debtFloor sdk.Int, savingsRate sdk.Dec) DebtParam {
return DebtParam{
Denom: denom,
ReferenceAsset: refAsset,
ConversionFactor: conversionFactor,
DebtFloor: debtFloor,
SavingsRate: savingsRate,
}
}
func (dp DebtParam) String() string {
return fmt.Sprintf(`Debt:
Denom: %s
Reference Asset: %s
Conversion Factor: %s
Debt Floor %s
Savings Rate %s
`, dp.Denom, dp.ReferenceAsset, dp.ConversionFactor, dp.DebtFloor, dp.SavingsRate)
}
// Validate checks that the parameters have valid values.
func (p Params) Validate() error {
if err := validateGlobalDebtLimitParam(p.GlobalDebtLimit); err != nil {
return err
}
if err := validateCollateralParams(p.CollateralParams); err != nil {
return err
}
if err := validateDebtParam(p.DebtParam); err != nil {
return err
}
if err := validateCircuitBreakerParam(p.CircuitBreaker); err != nil {
return err
}
if err := validateSurplusAuctionThresholdParam(p.SurplusAuctionThreshold); err != nil {
return err
}
if err := validateSurplusAuctionLotParam(p.SurplusAuctionLot); err != nil {
return err
}
if err := validateDebtAuctionThresholdParam(p.DebtAuctionThreshold); err != nil {
return err
}
if err := validateDebtAuctionLotParam(p.DebtAuctionLot); err != nil {
return err
}
if err := validateSavingsDistributionFrequencyParam(p.SavingsDistributionFrequency); err != nil {
return err
}
if len(p.CollateralParams) == 0 { // default value OK
return nil
}
if (DebtParam{}) != p.DebtParam {
if p.DebtParam.Denom != p.GlobalDebtLimit.Denom {
return fmt.Errorf("debt denom %s does not match global debt denom %s",
p.DebtParam.Denom, p.GlobalDebtLimit.Denom)
}
}
// validate collateral params
collateralDupMap := make(map[string]int)
prefixDupMap := make(map[int]int)
collateralParamsDebtLimit := sdk.ZeroInt()
for _, cp := range p.CollateralParams {
prefix := int(cp.Prefix)
prefixDupMap[prefix] = 1
collateralDupMap[cp.Denom] = 1
if cp.DebtLimit.Denom != p.GlobalDebtLimit.Denom {
return fmt.Errorf("collateral debt limit denom %s does not match global debt limit denom %s",
cp.DebtLimit.Denom, p.GlobalDebtLimit.Denom)
}
collateralParamsDebtLimit = collateralParamsDebtLimit.Add(cp.DebtLimit.Amount)
if cp.DebtLimit.Amount.GT(p.GlobalDebtLimit.Amount) {
return fmt.Errorf("collateral debt limit %s exceeds global debt limit: %s", cp.DebtLimit, p.GlobalDebtLimit)
}
}
if collateralParamsDebtLimit.GT(p.GlobalDebtLimit.Amount) {
return fmt.Errorf("sum of collateral debt limits %s exceeds global debt limit %s",
collateralParamsDebtLimit, p.GlobalDebtLimit)
}
return nil
}
func validateGlobalDebtLimitParam(i interface{}) error {
globalDebtLimit, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if !globalDebtLimit.IsValid() {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "global debt limit %s", globalDebtLimit.String())
}
return nil
}
func validateCollateralParams(i interface{}) error {
collateralParams, ok := i.(CollateralParams)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
prefixDupMap := make(map[int]bool)
typeDupMap := make(map[string]bool)
for _, cp := range collateralParams {
if err := sdk.ValidateDenom(cp.Denom); err != nil {
return fmt.Errorf("collateral denom invalid %s", cp.Denom)
}
if strings.TrimSpace(cp.SpotMarketID) == "" {
return fmt.Errorf("spot market id cannot be blank %s", cp)
}
if strings.TrimSpace(cp.Type) == "" {
return fmt.Errorf("collateral type cannot be blank %s", cp)
}
if strings.TrimSpace(cp.LiquidationMarketID) == "" {
return fmt.Errorf("liquidation market id cannot be blank %s", cp)
}
prefix := int(cp.Prefix)
if prefix < minCollateralPrefix || prefix > maxCollateralPrefix {
return fmt.Errorf("invalid prefix for collateral denom %s: %b", cp.Denom, cp.Prefix)
}
_, found := prefixDupMap[prefix]
if found {
return fmt.Errorf("duplicate prefix for collateral denom %s: %v", cp.Denom, []byte{cp.Prefix})
}
prefixDupMap[prefix] = true
_, found = typeDupMap[cp.Type]
if found {
return fmt.Errorf("duplicate cdp collateral type: %s", cp.Type)
}
typeDupMap[cp.Type] = true
if !cp.DebtLimit.IsValid() {
return fmt.Errorf("debt limit for all collaterals should be positive, is %s for %s", cp.DebtLimit, cp.Denom)
}
if cp.LiquidationPenalty.LT(sdk.ZeroDec()) || cp.LiquidationPenalty.GT(sdk.OneDec()) {
return fmt.Errorf("liquidation penalty should be between 0 and 1, is %s for %s", cp.LiquidationPenalty, cp.Denom)
}
if !cp.AuctionSize.IsPositive() {
return fmt.Errorf("auction size should be positive, is %s for %s", cp.AuctionSize, cp.Denom)
}
if cp.StabilityFee.LT(sdk.OneDec()) || cp.StabilityFee.GT(stabilityFeeMax) {
return fmt.Errorf("stability fee must be ≥ 1.0, ≤ %s, is %s for %s", stabilityFeeMax, cp.StabilityFee, cp.Denom)
}
}
return nil
}
func validateDebtParam(i interface{}) error {
debtParam, ok := i.(DebtParam)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if err := sdk.ValidateDenom(debtParam.Denom); err != nil {
return fmt.Errorf("debt denom invalid %s", debtParam.Denom)
}
if debtParam.SavingsRate.LT(sdk.ZeroDec()) || debtParam.SavingsRate.GT(sdk.OneDec()) {
return fmt.Errorf("savings rate should be between 0 and 1, is %s for %s", debtParam.SavingsRate, debtParam.Denom)
}
return nil
}
func validateCircuitBreakerParam(i interface{}) error {
_, ok := i.(bool)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
return nil
}
func validateSurplusAuctionThresholdParam(i interface{}) error {
sat, ok := i.(sdk.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if !sat.IsPositive() {
return fmt.Errorf("surplus auction threshold should be positive: %s", sat)
}
return nil
}
func validateSurplusAuctionLotParam(i interface{}) error {
sal, ok := i.(sdk.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if !sal.IsPositive() {
return fmt.Errorf("surplus auction lot should be positive: %s", sal)
}
return nil
}
func validateDebtAuctionThresholdParam(i interface{}) error {
dat, ok := i.(sdk.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if !dat.IsPositive() {
return fmt.Errorf("debt auction threshold should be positive: %s", dat)
}
return nil
}
func validateDebtAuctionLotParam(i interface{}) error {
dal, ok := i.(sdk.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if !dal.IsPositive() {
return fmt.Errorf("debt auction lot should be positive: %s", dal)
}
return nil
}
func validateSavingsDistributionFrequencyParam(i interface{}) error {
sdf, ok := i.(time.Duration)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if sdf.Seconds() <= float64(0) {
return fmt.Errorf("savings distribution frequency should be positive: %s", sdf)
}
return nil
}
// GenesisState is the state that must be provided at genesis.
type GenesisState struct {
Params Params `json:"params" yaml:"params"`
CDPs CDPs `json:"cdps" yaml:"cdps"`
Deposits Deposits `json:"deposits" yaml:"deposits"`
StartingCdpID uint64 `json:"starting_cdp_id" yaml:"starting_cdp_id"`
DebtDenom string `json:"debt_denom" yaml:"debt_denom"`
GovDenom string `json:"gov_denom" yaml:"gov_denom"`
PreviousDistributionTime time.Time `json:"previous_distribution_time" yaml:"previous_distribution_time"`
SavingsRateDistributed sdk.Int `json:"savings_rate_distributed" yaml:"savings_rate_distributed"`
}
// NewGenesisState returns a new genesis state
func NewGenesisState(params Params, cdps CDPs, deposits Deposits, startingCdpID uint64,
debtDenom, govDenom string, previousDistTime time.Time, savingsRateDist sdk.Int) GenesisState {
return GenesisState{
Params: params,
CDPs: cdps,
Deposits: deposits,
StartingCdpID: startingCdpID,
DebtDenom: debtDenom,
GovDenom: govDenom,
PreviousDistributionTime: previousDistTime,
SavingsRateDistributed: savingsRateDist,
}
}
// Validate performs basic validation of genesis data returning an
// error for any failed validation criteria.
func (gs GenesisState) Validate() error {
if err := gs.Params.Validate(); err != nil {
return err
}
if err := gs.CDPs.Validate(); err != nil {
return err
}
if err := gs.Deposits.Validate(); err != nil {
return err
}
if gs.PreviousDistributionTime.IsZero() {
return fmt.Errorf("previous distribution time not set")
}
if err := validateSavingsRateDistributed(gs.SavingsRateDistributed); err != nil {
return err
}
if err := sdk.ValidateDenom(gs.DebtDenom); err != nil {
return fmt.Errorf(fmt.Sprintf("debt denom invalid: %v", err))
}
if err := sdk.ValidateDenom(gs.GovDenom); err != nil {
return fmt.Errorf(fmt.Sprintf("gov denom invalid: %v", err))
}
return nil
}
func validateSavingsRateDistributed(i interface{}) error {
savingsRateDist, ok := i.(sdk.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if savingsRateDist.IsNegative() {
return fmt.Errorf("savings rate distributed should not be negative: %s", savingsRateDist)
}
return nil
}

View File

@ -35,6 +35,19 @@ func NewCDP(id uint64, owner sdk.AccAddress, collateral sdk.Coin, collateralType
}
}
// NewCDPWithFees creates a new CDP object, for use during migration
func NewCDPWithFees(id uint64, owner sdk.AccAddress, collateral sdk.Coin, collateralType string, principal, fees sdk.Coin, time time.Time) CDP {
return CDP{
ID: id,
Owner: owner,
Type: collateralType,
Collateral: collateral,
Principal: principal,
AccumulatedFees: fees,
FeesUpdated: time,
}
}
// String implements fmt.stringer
func (cdp CDP) String() string {
return strings.TrimSpace(fmt.Sprintf(`CDP:

View File

@ -122,6 +122,23 @@ type CollateralParam struct {
ConversionFactor sdk.Int `json:"conversion_factor" yaml:"conversion_factor"` // factor for converting internal units to one base unit of collateral
}
// NewCollateralParam returns a new CollateralParam
func NewCollateralParam(denom, ctype string, liqRatio sdk.Dec, debtLimit sdk.Coin, stabilityFee sdk.Dec, auctionSize sdk.Int, liqPenalty sdk.Dec, prefix byte, spotMarketID, liquidationMarketID string, conversionFactor sdk.Int) CollateralParam {
return CollateralParam{
Denom: denom,
Type: ctype,
LiquidationRatio: liqRatio,
DebtLimit: debtLimit,
StabilityFee: stabilityFee,
AuctionSize: auctionSize,
LiquidationPenalty: liqPenalty,
Prefix: prefix,
SpotMarketID: spotMarketID,
LiquidationMarketID: liquidationMarketID,
ConversionFactor: conversionFactor,
}
}
// String implements fmt.Stringer
func (cp CollateralParam) String() string {
return fmt.Sprintf(`Collateral:
@ -160,6 +177,17 @@ type DebtParam struct {
SavingsRate sdk.Dec `json:"savings_rate" yaml:"savings_rate"` // the percentage of stability fees that are redirected to savings rate
}
// NewDebtParam returns a new DebtParam
func NewDebtParam(denom, refAsset string, conversionFactor, debtFloor sdk.Int, savingsRate sdk.Dec) DebtParam {
return DebtParam{
Denom: denom,
ReferenceAsset: refAsset,
ConversionFactor: conversionFactor,
DebtFloor: debtFloor,
SavingsRate: savingsRate,
}
}
func (dp DebtParam) String() string {
return fmt.Sprintf(`Debt:
Denom: %s