mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +00:00
Add collateral type to cdp (#629)
* add collateral type field to cdp and collateral param * fix upstream tests * fix simulations * fix validation logic * update incentive to use collateral type instead of denom * use collateral type instead of denom in cdp * remove unused code * address review comments
This commit is contained in:
parent
60d7f522e2
commit
daa1b2bb83
10
CHANGELOG.md
10
CHANGELOG.md
@ -46,6 +46,16 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
[\#578](https://github.com/Kava-Labs/kava/pulls/578) Add v0.3 compatible REST client that supports
|
[\#578](https://github.com/Kava-Labs/kava/pulls/578) Add v0.3 compatible REST client that supports
|
||||||
|
|
||||||
|
[\#629](https://github.com/Kava-Labs/kava/pulls/629) Add CDP collateral type as a field for CDPs and collateral parameters.
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* CDPs have an additional field, Type, which is a string that represents the unique collateral type that this CDP holds. This enables, for example, a single denom such as 'bnb' to have two CDP types, 'bnb-a' and 'bnb-b'.
|
||||||
|
* CollateralParam has an additional field, Type, which is a string that represents the collateral type of CDPs that this collateral parameter governs. It must be non-empty at genesis or when altering CDP fields. It is UNSAFE to alter the type of an existing collateral param using unchain governance.
|
||||||
|
* CDP messages must specify the collateral type 'bnb-a', rather than the denom of the cdp.
|
||||||
|
* In the incentive module, fields previously named `Denom` have been changed to `CollateralType`. Previously, 'Denom' was validated to check that it satisfied `sdk.ValidateDenom`, now, the validation checks that the `CollateralType` is not blank.
|
||||||
|
* Incentive module messages now require the user to specify the collateral type ('bnb-a'), rather than the denom of the cdp ('bnb')
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
/v0_3/node_info
|
/v0_3/node_info
|
||||||
/v0_3/auth/accounts/<address>
|
/v0_3/auth/accounts/<address>
|
||||||
|
@ -121,6 +121,7 @@ func sendBtcCdp() {
|
|||||||
addr,
|
addr,
|
||||||
sdk.NewInt64Coin("btc", 200000000),
|
sdk.NewInt64Coin("btc", 200000000),
|
||||||
sdk.NewInt64Coin("usdx", 10000000),
|
sdk.NewInt64Coin("usdx", 10000000),
|
||||||
|
"btc-a",
|
||||||
)
|
)
|
||||||
|
|
||||||
// helper methods for transactions
|
// helper methods for transactions
|
||||||
@ -154,6 +155,7 @@ func sendXrpCdp() {
|
|||||||
addr,
|
addr,
|
||||||
sdk.NewInt64Coin("xrp", 200000000),
|
sdk.NewInt64Coin("xrp", 200000000),
|
||||||
sdk.NewInt64Coin("usdx", 10000000),
|
sdk.NewInt64Coin("usdx", 10000000),
|
||||||
|
"xrp-a",
|
||||||
)
|
)
|
||||||
|
|
||||||
// helper methods for transactions
|
// helper methods for transactions
|
||||||
|
@ -31,12 +31,12 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err := k.UpdateFeesForAllCdps(ctx, cp.Denom)
|
err := k.UpdateFeesForAllCdps(ctx, cp.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.LiquidateCdps(ctx, cp.LiquidationMarketID, cp.Denom, cp.LiquidationRatio)
|
err = k.LiquidateCdps(ctx, cp.LiquidationMarketID, cp.Type, cp.LiquidationRatio)
|
||||||
if err != nil && !errors.Is(err, pricefeedtypes.ErrNoValidPrice) {
|
if err != nil && !errors.Is(err, pricefeedtypes.ErrNoValidPrice) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -103,8 +103,8 @@ func (suite *ModuleTestSuite) createCdps() {
|
|||||||
tracker.debt += int64(debt)
|
tracker.debt += int64(debt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suite.Nil(suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt))))
|
suite.Nil(suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt)), collateral+"-a"))
|
||||||
c, f := suite.keeper.GetCDP(suite.ctx, collateral, uint64(j+1))
|
c, f := suite.keeper.GetCDP(suite.ctx, collateral+"-a", uint64(j+1))
|
||||||
suite.True(f)
|
suite.True(f)
|
||||||
cdps[j] = c
|
cdps[j] = c
|
||||||
}
|
}
|
||||||
@ -153,9 +153,9 @@ func (suite *ModuleTestSuite) TestBeginBlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ModuleTestSuite) TestSeizeSingleCdpWithFees() {
|
func (suite *ModuleTestSuite) TestSeizeSingleCdpWithFees() {
|
||||||
err := suite.keeper.AddCdp(suite.ctx, suite.addrs[0], c("xrp", 10000000000), c("usdx", 1000000000))
|
err := suite.keeper.AddCdp(suite.ctx, suite.addrs[0], c("xrp", 10000000000), c("usdx", 1000000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.Equal(i(1000000000), suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx"))
|
suite.Equal(i(1000000000), suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx"))
|
||||||
sk := suite.app.GetSupplyKeeper()
|
sk := suite.app.GetSupplyKeeper()
|
||||||
cdpMacc := sk.GetModuleAccount(suite.ctx, cdp.ModuleName)
|
cdpMacc := sk.GetModuleAccount(suite.ctx, cdp.ModuleName)
|
||||||
suite.Equal(i(1000000000), cdpMacc.GetCoins().AmountOf("debt"))
|
suite.Equal(i(1000000000), cdpMacc.GetCoins().AmountOf("debt"))
|
||||||
@ -166,11 +166,11 @@ func (suite *ModuleTestSuite) TestSeizeSingleCdpWithFees() {
|
|||||||
|
|
||||||
cdpMacc = sk.GetModuleAccount(suite.ctx, cdp.ModuleName)
|
cdpMacc = sk.GetModuleAccount(suite.ctx, cdp.ModuleName)
|
||||||
suite.Equal(i(1000000900), (cdpMacc.GetCoins().AmountOf("debt")))
|
suite.Equal(i(1000000900), (cdpMacc.GetCoins().AmountOf("debt")))
|
||||||
cdp, _ := suite.keeper.GetCDP(suite.ctx, "xrp", 1)
|
cdp, _ := suite.keeper.GetCDP(suite.ctx, "xrp-a", 1)
|
||||||
|
|
||||||
err = suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
err = suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
_, found := suite.keeper.GetCDP(suite.ctx, "xrp", 1)
|
_, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", 1)
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ const (
|
|||||||
QueryGetCdpsByCollateralization = types.QueryGetCdpsByCollateralization
|
QueryGetCdpsByCollateralization = types.QueryGetCdpsByCollateralization
|
||||||
QueryGetParams = types.QueryGetParams
|
QueryGetParams = types.QueryGetParams
|
||||||
RestOwner = types.RestOwner
|
RestOwner = types.RestOwner
|
||||||
RestCollateralDenom = types.RestCollateralDenom
|
RestCollateralType = types.RestCollateralType
|
||||||
RestRatio = types.RestRatio
|
RestRatio = types.RestRatio
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
|||||||
|
|
||||||
cdpQueryCmd.AddCommand(flags.GetCommands(
|
cdpQueryCmd.AddCommand(flags.GetCommands(
|
||||||
QueryCdpCmd(queryRoute, cdc),
|
QueryCdpCmd(queryRoute, cdc),
|
||||||
QueryCdpsByDenomCmd(queryRoute, cdc),
|
QueryCdpsByCollateralTypeCmd(queryRoute, cdc),
|
||||||
QueryCdpsByDenomAndRatioCmd(queryRoute, cdc),
|
QueryCdpsByCollateralTypeAndRatioCmd(queryRoute, cdc),
|
||||||
QueryCdpDepositsCmd(queryRoute, cdc),
|
QueryCdpDepositsCmd(queryRoute, cdc),
|
||||||
QueryParamsCmd(queryRoute, cdc),
|
QueryParamsCmd(queryRoute, cdc),
|
||||||
QueryGetAccounts(queryRoute, cdc),
|
QueryGetAccounts(queryRoute, cdc),
|
||||||
@ -39,13 +39,13 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
|||||||
// QueryCdpCmd returns the command handler for querying a particular cdp
|
// QueryCdpCmd returns the command handler for querying a particular cdp
|
||||||
func QueryCdpCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
func QueryCdpCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "cdp [owner-addr] [collateral-name]",
|
Use: "cdp [owner-addr] [collateral-type]",
|
||||||
Short: "get info about a cdp",
|
Short: "get info about a cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Get a CDP by the owner address and the collateral name.
|
fmt.Sprintf(`Get a CDP by the owner address and the collateral name.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s query %s cdp kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
$ %s query %s cdp kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw atom-a
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -57,8 +57,8 @@ $ %s query %s cdp kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bz, err := cdc.MarshalJSON(types.QueryCdpParams{
|
bz, err := cdc.MarshalJSON(types.QueryCdpParams{
|
||||||
CollateralDenom: args[1],
|
CollateralType: args[1],
|
||||||
Owner: ownerAddress,
|
Owner: ownerAddress,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -79,23 +79,23 @@ $ %s query %s cdp kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryCdpsByDenomCmd returns the command handler for querying cdps for a collateral type
|
// QueryCdpsByCollateralTypeCmd returns the command handler for querying cdps for a collateral type
|
||||||
func QueryCdpsByDenomCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
func QueryCdpsByCollateralTypeCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "cdps [collateral-name]",
|
Use: "cdps [collateral-type]",
|
||||||
Short: "query CDPs by collateral",
|
Short: "query CDPs by collateral",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`List all CDPs collateralized with the specified asset.
|
fmt.Sprintf(`List all CDPs collateralized with the specified asset.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s query %s cdps uatom
|
$ %s query %s cdps atom-a
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
|
|
||||||
// Prepare params for querier
|
// Prepare params for querier
|
||||||
bz, err := cdc.MarshalJSON(types.QueryCdpsParams{CollateralDenom: args[0]})
|
bz, err := cdc.MarshalJSON(types.QueryCdpsParams{CollateralType: args[0]})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -115,18 +115,18 @@ $ %s query %s cdps uatom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryCdpsByDenomAndRatioCmd returns the command handler for querying cdps
|
// QueryCdpsByCollateralTypeAndRatioCmd returns the command handler for querying cdps
|
||||||
// that are under the specified collateral ratio
|
// that are under the specified collateral ratio
|
||||||
func QueryCdpsByDenomAndRatioCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
func QueryCdpsByCollateralTypeAndRatioCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "cdps-by-ratio [collateral-name] [collateralization-ratio]",
|
Use: "cdps-by-ratio [collateral-type] [collateralization-ratio]",
|
||||||
Short: "get cdps under a collateralization ratio",
|
Short: "get cdps under a collateralization ratio",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`List all CDPs under a specified collateralization ratio.
|
fmt.Sprintf(`List all CDPs under a specified collateralization ratio.
|
||||||
Collateralization ratio is: collateral * price / debt.
|
Collateralization ratio is: collateral * price / debt.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s query %s cdps-by-ratio uatom 1.5
|
$ %s query %s cdps-by-ratio atom-a 1.6
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -138,8 +138,8 @@ $ %s query %s cdps-by-ratio uatom 1.5
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bz, err := cdc.MarshalJSON(types.QueryCdpsByRatioParams{
|
bz, err := cdc.MarshalJSON(types.QueryCdpsByRatioParams{
|
||||||
CollateralDenom: args[0],
|
CollateralType: args[0],
|
||||||
Ratio: ratio,
|
Ratio: ratio,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -163,13 +163,13 @@ $ %s query %s cdps-by-ratio uatom 1.5
|
|||||||
// QueryCdpDepositsCmd returns the command handler for querying the deposits of a particular cdp
|
// QueryCdpDepositsCmd returns the command handler for querying the deposits of a particular cdp
|
||||||
func QueryCdpDepositsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
func QueryCdpDepositsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "deposits [owner-addr] [collateral-name]",
|
Use: "deposits [owner-addr] [collateral-type]",
|
||||||
Short: "get deposits for a cdp",
|
Short: "get deposits for a cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Get the deposits of a CDP.
|
fmt.Sprintf(`Get the deposits of a CDP.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s query %s deposits kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
$ %s query %s deposits kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw atom-a
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -181,8 +181,8 @@ $ %s query %s deposits kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bz, err := cdc.MarshalJSON(types.QueryCdpParams{
|
bz, err := cdc.MarshalJSON(types.QueryCdpParams{
|
||||||
CollateralDenom: args[1],
|
CollateralType: args[1],
|
||||||
Owner: ownerAddress,
|
Owner: ownerAddress,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -39,15 +39,15 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command {
|
|||||||
// GetCmdCreateCdp returns the command handler for creating a cdp
|
// GetCmdCreateCdp returns the command handler for creating a cdp
|
||||||
func GetCmdCreateCdp(cdc *codec.Codec) *cobra.Command {
|
func GetCmdCreateCdp(cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "create [collateral] [debt]",
|
Use: "create [collateral] [debt] [collateral-type]",
|
||||||
Short: "create a new cdp",
|
Short: "create a new cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Create a new cdp, depositing some collateral and drawing some debt.
|
fmt.Sprintf(`Create a new cdp, depositing some collateral and drawing some debt.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s tx %s create 10000000uatom 1000usdx --from myKeyName
|
$ %s tx %s create 10000000uatom 1000usdx atom-a --from myKeyName
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(3),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
@ -61,7 +61,7 @@ $ %s tx %s create 10000000uatom 1000usdx --from myKeyName
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg := types.NewMsgCreateCDP(cliCtx.GetFromAddress(), collateral, debt)
|
msg := types.NewMsgCreateCDP(cliCtx.GetFromAddress(), collateral, debt, args[2])
|
||||||
err = msg.ValidateBasic()
|
err = msg.ValidateBasic()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -74,15 +74,15 @@ $ %s tx %s create 10000000uatom 1000usdx --from myKeyName
|
|||||||
// GetCmdDeposit cli command for depositing to a cdp.
|
// GetCmdDeposit cli command for depositing to a cdp.
|
||||||
func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
|
func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "deposit [owner-addr] [collateral]",
|
Use: "deposit [owner-addr] [collateral] [collateral-type]",
|
||||||
Short: "deposit collateral to an existing cdp",
|
Short: "deposit collateral to an existing cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Add collateral to an existing cdp.
|
fmt.Sprintf(`Add collateral to an existing cdp.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s tx %s deposit kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --from myKeyName
|
$ %s tx %s deposit kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom atom-a --from myKeyName
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(3),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||||
@ -96,7 +96,7 @@ $ %s tx %s deposit kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --f
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg := types.NewMsgDeposit(owner, cliCtx.GetFromAddress(), collateral)
|
msg := types.NewMsgDeposit(owner, cliCtx.GetFromAddress(), collateral, args[2])
|
||||||
err = msg.ValidateBasic()
|
err = msg.ValidateBasic()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -109,13 +109,13 @@ $ %s tx %s deposit kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --f
|
|||||||
// GetCmdWithdraw cli command for withdrawing from a cdp.
|
// GetCmdWithdraw cli command for withdrawing from a cdp.
|
||||||
func GetCmdWithdraw(cdc *codec.Codec) *cobra.Command {
|
func GetCmdWithdraw(cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "withdraw [owner-addr] [collateral]",
|
Use: "withdraw [owner-addr] [collateral] [collateral-type]",
|
||||||
Short: "withdraw collateral from an existing cdp",
|
Short: "withdraw collateral from an existing cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Remove collateral from an existing cdp.
|
fmt.Sprintf(`Remove collateral from an existing cdp.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s tx %s withdraw kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --from myKeyName
|
$ %s tx %s withdraw kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom atom-a --from myKeyName
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -131,7 +131,7 @@ $ %s tx %s withdraw kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg := types.NewMsgWithdraw(owner, cliCtx.GetFromAddress(), collateral)
|
msg := types.NewMsgWithdraw(owner, cliCtx.GetFromAddress(), collateral, args[2])
|
||||||
err = msg.ValidateBasic()
|
err = msg.ValidateBasic()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -144,13 +144,13 @@ $ %s tx %s withdraw kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw 10000000uatom --
|
|||||||
// GetCmdDraw cli command for depositing to a cdp.
|
// GetCmdDraw cli command for depositing to a cdp.
|
||||||
func GetCmdDraw(cdc *codec.Codec) *cobra.Command {
|
func GetCmdDraw(cdc *codec.Codec) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "draw [collateral-name] [debt]",
|
Use: "draw [collateral-type] [debt]",
|
||||||
Short: "draw debt off an existing cdp",
|
Short: "draw debt off an existing cdp",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`Create debt in an existing cdp and send the newly minted asset to your account.
|
fmt.Sprintf(`Create debt in an existing cdp and send the newly minted asset to your account.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s tx %s draw uatom 1000usdx --from myKeyName
|
$ %s tx %s draw atom-a 1000usdx --from myKeyName
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -181,7 +181,7 @@ func GetCmdRepay(cdc *codec.Codec) *cobra.Command {
|
|||||||
fmt.Sprintf(`Cancel out debt in an existing cdp.
|
fmt.Sprintf(`Cancel out debt in an existing cdp.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ %s tx %s repay uatom 1000usdx --from myKeyName
|
$ %s tx %s repay atom-a 1000usdx --from myKeyName
|
||||||
`, version.ClientName, types.ModuleName)),
|
`, version.ClientName, types.ModuleName)),
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -16,10 +16,10 @@ import (
|
|||||||
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||||
r.HandleFunc("/cdp/accounts", getAccountsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc("/cdp/accounts", getAccountsHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc("/cdp/parameters", getParamsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc("/cdp/parameters", getParamsHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/cdp/cdps/cdp/{%s}/{%s}", types.RestOwner, types.RestCollateralDenom), queryCdpHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/cdp/cdps/cdp/{%s}/{%s}", types.RestOwner, types.RestCollateralType), queryCdpHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/cdp/cdps/denom/{%s}", types.RestCollateralDenom), queryCdpsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/cdp/cdps/collateralType/{%s}", types.RestCollateralType), queryCdpsHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/cdp/cdps/ratio/{%s}/{%s}", types.RestCollateralDenom, types.RestRatio), queryCdpsByRatioHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/cdp/cdps/ratio/{%s}/{%s}", types.RestCollateralType, types.RestRatio), queryCdpsByRatioHandlerFn(cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/cdp/cdps/cdp/deposits/{%s}/{%s}", types.RestOwner, types.RestCollateralDenom), queryCdpDepositsHandlerFn(cliCtx)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/cdp/cdps/cdp/deposits/{%s}/{%s}", types.RestOwner, types.RestCollateralType), queryCdpDepositsHandlerFn(cliCtx)).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
func queryCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
||||||
@ -31,7 +31,7 @@ func queryCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
ownerBech32 := vars[types.RestOwner]
|
ownerBech32 := vars[types.RestOwner]
|
||||||
collateralDenom := vars[types.RestCollateralDenom]
|
collateralType := vars[types.RestCollateralType]
|
||||||
|
|
||||||
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,7 +39,7 @@ func queryCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := types.NewQueryCdpParams(owner, collateralDenom)
|
params := types.NewQueryCdpParams(owner, collateralType)
|
||||||
|
|
||||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -66,9 +66,9 @@ func queryCdpsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
collateralDenom := vars[types.RestCollateralDenom]
|
collateralType := vars[types.RestCollateralType]
|
||||||
|
|
||||||
params := types.NewQueryCdpsParams(collateralDenom)
|
params := types.NewQueryCdpsParams(collateralType)
|
||||||
|
|
||||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -95,7 +95,7 @@ func queryCdpsByRatioHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
collateralDenom := vars[types.RestCollateralDenom]
|
collateralType := vars[types.RestCollateralType]
|
||||||
ratioStr := vars[types.RestRatio]
|
ratioStr := vars[types.RestRatio]
|
||||||
|
|
||||||
ratioDec, sdkError := sdk.NewDecFromStr(ratioStr)
|
ratioDec, sdkError := sdk.NewDecFromStr(ratioStr)
|
||||||
@ -104,7 +104,7 @@ func queryCdpsByRatioHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := types.NewQueryCdpsByRatioParams(collateralDenom, ratioDec)
|
params := types.NewQueryCdpsByRatioParams(collateralType, ratioDec)
|
||||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
|
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
|
||||||
@ -131,7 +131,7 @@ func queryCdpDepositsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
ownerBech32 := vars[types.RestOwner]
|
ownerBech32 := vars[types.RestOwner]
|
||||||
collateralDenom := vars[types.RestCollateralDenom]
|
collateralType := vars[types.RestCollateralType]
|
||||||
|
|
||||||
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -139,7 +139,7 @@ func queryCdpDepositsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := types.NewQueryCdpDeposits(owner, collateralDenom)
|
params := types.NewQueryCdpDeposits(owner, collateralType)
|
||||||
|
|
||||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,40 +16,43 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
|||||||
|
|
||||||
// PostCdpReq defines the properties of cdp request's body.
|
// PostCdpReq defines the properties of cdp request's body.
|
||||||
type PostCdpReq struct {
|
type PostCdpReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
|
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostDepositReq defines the properties of cdp request's body.
|
// PostDepositReq defines the properties of cdp request's body.
|
||||||
type PostDepositReq struct {
|
type PostDepositReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostWithdrawalReq defines the properties of cdp request's body.
|
// PostWithdrawalReq defines the properties of cdp request's body.
|
||||||
type PostWithdrawalReq struct {
|
type PostWithdrawalReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostDrawReq defines the properties of cdp request's body.
|
// PostDrawReq defines the properties of cdp request's body.
|
||||||
type PostDrawReq struct {
|
type PostDrawReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostRepayReq defines the properties of cdp request's body.
|
// PostRepayReq defines the properties of cdp request's body.
|
||||||
type PostRepayReq struct {
|
type PostRepayReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
Payment sdk.Coin `json:"payment" yaml:"payment"`
|
Payment sdk.Coin `json:"payment" yaml:"payment"`
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ import (
|
|||||||
|
|
||||||
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||||
r.HandleFunc("/cdp", postCdpHandlerFn(cliCtx)).Methods("POST")
|
r.HandleFunc("/cdp", postCdpHandlerFn(cliCtx)).Methods("POST")
|
||||||
r.HandleFunc("/cdp/{owner}/{denom}/deposits", postDepositHandlerFn(cliCtx)).Methods("POST")
|
r.HandleFunc("/cdp/{owner}/{collateralType}/deposits", postDepositHandlerFn(cliCtx)).Methods("POST")
|
||||||
r.HandleFunc("/cdp/{owner}/{denom}/withdraw", postWithdrawHandlerFn(cliCtx)).Methods("POST")
|
r.HandleFunc("/cdp/{owner}/{collateralType}/withdraw", postWithdrawHandlerFn(cliCtx)).Methods("POST")
|
||||||
r.HandleFunc("/cdp/{owner}/{denom}/draw", postDrawHandlerFn(cliCtx)).Methods("POST")
|
r.HandleFunc("/cdp/{owner}/{collateralType}/draw", postDrawHandlerFn(cliCtx)).Methods("POST")
|
||||||
r.HandleFunc("/cdp/{owner}/{denom}/repay", postRepayHandlerFn(cliCtx)).Methods("POST")
|
r.HandleFunc("/cdp/{owner}/{collateralType}/repay", postRepayHandlerFn(cliCtx)).Methods("POST")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ func postCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
requestBody.Sender,
|
requestBody.Sender,
|
||||||
requestBody.Collateral,
|
requestBody.Collateral,
|
||||||
requestBody.Principal,
|
requestBody.Principal,
|
||||||
|
requestBody.CollateralType,
|
||||||
)
|
)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
@ -76,6 +77,7 @@ func postDepositHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
requestBody.Owner,
|
requestBody.Owner,
|
||||||
requestBody.Depositor,
|
requestBody.Depositor,
|
||||||
requestBody.Collateral,
|
requestBody.Collateral,
|
||||||
|
requestBody.CollateralType,
|
||||||
)
|
)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
@ -102,6 +104,7 @@ func postWithdrawHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
requestBody.Owner,
|
requestBody.Owner,
|
||||||
requestBody.Depositor,
|
requestBody.Depositor,
|
||||||
requestBody.Collateral,
|
requestBody.Collateral,
|
||||||
|
requestBody.CollateralType,
|
||||||
)
|
)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
@ -137,7 +140,7 @@ func postDrawHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
msg := types.NewMsgDrawDebt(
|
msg := types.NewMsgDrawDebt(
|
||||||
requestBody.Owner,
|
requestBody.Owner,
|
||||||
requestBody.Denom,
|
requestBody.CollateralType,
|
||||||
requestBody.Principal,
|
requestBody.Principal,
|
||||||
)
|
)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
@ -174,7 +177,7 @@ func postRepayHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
msg := types.NewMsgRepayDebt(
|
msg := types.NewMsgRepayDebt(
|
||||||
requestBody.Owner,
|
requestBody.Owner,
|
||||||
requestBody.Denom,
|
requestBody.CollateralType,
|
||||||
requestBody.Payment,
|
requestBody.Payment,
|
||||||
)
|
)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
|
@ -59,7 +59,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, pk types.PricefeedKeeper, sk types.S
|
|||||||
|
|
||||||
// set the per second fee rate for each collateral type
|
// set the per second fee rate for each collateral type
|
||||||
for _, cp := range gs.Params.CollateralParams {
|
for _, cp := range gs.Params.CollateralParams {
|
||||||
k.SetTotalPrincipal(ctx, cp.Denom, gs.Params.DebtParam.Denom, sdk.ZeroInt())
|
k.SetTotalPrincipal(ctx, cp.Type, gs.Params.DebtParam.Denom, sdk.ZeroInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
// add cdps
|
// add cdps
|
||||||
@ -72,9 +72,9 @@ func InitGenesis(ctx sdk.Context, k Keeper, pk types.PricefeedKeeper, sk types.S
|
|||||||
panic(fmt.Sprintf("error setting cdp: %v", err))
|
panic(fmt.Sprintf("error setting cdp: %v", err))
|
||||||
}
|
}
|
||||||
k.IndexCdpByOwner(ctx, cdp)
|
k.IndexCdpByOwner(ctx, cdp)
|
||||||
ratio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
ratio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
k.IndexCdpByCollateralRatio(ctx, cdp.Collateral.Denom, cdp.ID, ratio)
|
k.IndexCdpByCollateralRatio(ctx, cdp.Type, cdp.ID, ratio)
|
||||||
k.IncrementTotalPrincipal(ctx, cdp.Collateral.Denom, cdp.GetTotalPrincipal())
|
k.IncrementTotalPrincipal(ctx, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
}
|
}
|
||||||
|
|
||||||
k.SetNextCdpID(ctx, gs.StartingCdpID)
|
k.SetNextCdpID(ctx, gs.StartingCdpID)
|
||||||
|
@ -27,7 +27,7 @@ func NewHandler(k Keeper) sdk.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgCreateCDP(ctx sdk.Context, k Keeper, msg MsgCreateCDP) (*sdk.Result, error) {
|
func handleMsgCreateCDP(ctx sdk.Context, k Keeper, msg MsgCreateCDP) (*sdk.Result, error) {
|
||||||
err := k.AddCdp(ctx, msg.Sender, msg.Collateral, msg.Principal)
|
err := k.AddCdp(ctx, msg.Sender, msg.Collateral, msg.Principal, msg.CollateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ func handleMsgCreateCDP(ctx sdk.Context, k Keeper, msg MsgCreateCDP) (*sdk.Resul
|
|||||||
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()),
|
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
id, _ := k.GetCdpID(ctx, msg.Sender, msg.Collateral.Denom)
|
id, _ := k.GetCdpID(ctx, msg.Sender, msg.CollateralType)
|
||||||
|
|
||||||
return &sdk.Result{
|
return &sdk.Result{
|
||||||
Data: GetCdpIDBytes(id),
|
Data: GetCdpIDBytes(id),
|
||||||
@ -48,7 +48,7 @@ func handleMsgCreateCDP(ctx sdk.Context, k Keeper, msg MsgCreateCDP) (*sdk.Resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgDeposit(ctx sdk.Context, k Keeper, msg MsgDeposit) (*sdk.Result, error) {
|
func handleMsgDeposit(ctx sdk.Context, k Keeper, msg MsgDeposit) (*sdk.Result, error) {
|
||||||
err := k.DepositCollateral(ctx, msg.Owner, msg.Depositor, msg.Collateral)
|
err := k.DepositCollateral(ctx, msg.Owner, msg.Depositor, msg.Collateral, msg.CollateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ func handleMsgDeposit(ctx sdk.Context, k Keeper, msg MsgDeposit) (*sdk.Result, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgWithdraw(ctx sdk.Context, k Keeper, msg MsgWithdraw) (*sdk.Result, error) {
|
func handleMsgWithdraw(ctx sdk.Context, k Keeper, msg MsgWithdraw) (*sdk.Result, error) {
|
||||||
err := k.WithdrawCollateral(ctx, msg.Owner, msg.Depositor, msg.Collateral)
|
err := k.WithdrawCollateral(ctx, msg.Owner, msg.Depositor, msg.Collateral, msg.CollateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ func handleMsgWithdraw(ctx sdk.Context, k Keeper, msg MsgWithdraw) (*sdk.Result,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgDrawDebt(ctx sdk.Context, k Keeper, msg MsgDrawDebt) (*sdk.Result, error) {
|
func handleMsgDrawDebt(ctx sdk.Context, k Keeper, msg MsgDrawDebt) (*sdk.Result, error) {
|
||||||
err := k.AddPrincipal(ctx, msg.Sender, msg.CdpDenom, msg.Principal)
|
err := k.AddPrincipal(ctx, msg.Sender, msg.CollateralType, msg.Principal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ func handleMsgDrawDebt(ctx sdk.Context, k Keeper, msg MsgDrawDebt) (*sdk.Result,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgRepayDebt(ctx sdk.Context, k Keeper, msg MsgRepayDebt) (*sdk.Result, error) {
|
func handleMsgRepayDebt(ctx sdk.Context, k Keeper, msg MsgRepayDebt) (*sdk.Result, error) {
|
||||||
err := k.RepayPrincipal(ctx, msg.Sender, msg.CdpDenom, msg.Payment)
|
err := k.RepayPrincipal(ctx, msg.Sender, msg.CollateralType, msg.Payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ func (suite *HandlerTestSuite) TestMsgCreateCdp() {
|
|||||||
addrs[0],
|
addrs[0],
|
||||||
c("xrp", 200000000),
|
c("xrp", 200000000),
|
||||||
c("usdx", 10000000),
|
c("usdx", 10000000),
|
||||||
|
"xrp-a",
|
||||||
)
|
)
|
||||||
res, err := suite.handler(suite.ctx, msg)
|
res, err := suite.handler(suite.ctx, msg)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
@ -49,6 +49,7 @@ func NewCDPGenState(asset string, liquidationRatio sdk.Dec) app.GenesisState {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: asset,
|
Denom: asset,
|
||||||
|
Type: asset + "-a",
|
||||||
LiquidationRatio: liquidationRatio,
|
LiquidationRatio: liquidationRatio,
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -114,6 +115,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -126,6 +128,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
|
Type: "btc-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
||||||
@ -156,10 +159,10 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
|
|
||||||
func cdps() (cdps cdp.CDPs) {
|
func cdps() (cdps cdp.CDPs) {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(3)
|
_, addrs := app.GeneratePrivKeyAddressPairs(3)
|
||||||
c1 := cdp.NewCDP(uint64(1), addrs[0], sdk.NewCoin("xrp", sdk.NewInt(100000000)), sdk.NewCoin("usdx", sdk.NewInt(8000000)), tmtime.Canonical(time.Now()))
|
c1 := cdp.NewCDP(uint64(1), addrs[0], sdk.NewCoin("xrp", sdk.NewInt(100000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(8000000)), tmtime.Canonical(time.Now()))
|
||||||
c2 := cdp.NewCDP(uint64(2), addrs[1], sdk.NewCoin("xrp", sdk.NewInt(100000000)), sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
c2 := cdp.NewCDP(uint64(2), addrs[1], sdk.NewCoin("xrp", sdk.NewInt(100000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
||||||
c3 := cdp.NewCDP(uint64(3), addrs[1], sdk.NewCoin("btc", sdk.NewInt(1000000000)), sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
c3 := cdp.NewCDP(uint64(3), addrs[1], sdk.NewCoin("btc", sdk.NewInt(1000000000)), "btc-a", sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
||||||
c4 := cdp.NewCDP(uint64(4), addrs[2], sdk.NewCoin("xrp", sdk.NewInt(1000000000)), sdk.NewCoin("usdx", sdk.NewInt(50000000)), tmtime.Canonical(time.Now()))
|
c4 := cdp.NewCDP(uint64(4), addrs[2], sdk.NewCoin("xrp", sdk.NewInt(1000000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(50000000)), tmtime.Canonical(time.Now()))
|
||||||
cdps = append(cdps, c1, c2, c3, c4)
|
cdps = append(cdps, c1, c2, c3, c4)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,14 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AuctionCollateral creates auctions from the input deposits which attempt to raise the corresponding amount of debt
|
// AuctionCollateral creates auctions from the input deposits which attempt to raise the corresponding amount of debt
|
||||||
func (k Keeper) AuctionCollateral(ctx sdk.Context, deposits types.Deposits, debt sdk.Int, bidDenom string) error {
|
func (k Keeper) AuctionCollateral(ctx sdk.Context, deposits types.Deposits, collateralType string, debt sdk.Int, bidDenom string) error {
|
||||||
|
|
||||||
auctionSize := k.getAuctionSize(ctx, deposits[0].Amount.Denom)
|
auctionSize := k.getAuctionSize(ctx, collateralType)
|
||||||
totalCollateral := deposits.SumCollateral()
|
totalCollateral := deposits.SumCollateral()
|
||||||
for _, deposit := range deposits {
|
for _, deposit := range deposits {
|
||||||
|
|
||||||
debtCoveredByDeposit := (sdk.NewDecFromInt(deposit.Amount.Amount).Quo(sdk.NewDecFromInt(totalCollateral))).Mul(sdk.NewDecFromInt(debt)).RoundInt()
|
debtCoveredByDeposit := (sdk.NewDecFromInt(deposit.Amount.Amount).Quo(sdk.NewDecFromInt(totalCollateral))).Mul(sdk.NewDecFromInt(debt)).RoundInt()
|
||||||
err := k.CreateAuctionsFromDeposit(ctx, deposit.Amount, deposit.Depositor, debtCoveredByDeposit, auctionSize, bidDenom)
|
err := k.CreateAuctionsFromDeposit(ctx, deposit.Amount, collateralType, deposit.Depositor, debtCoveredByDeposit, auctionSize, bidDenom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ func (k Keeper) AuctionCollateral(ctx sdk.Context, deposits types.Deposits, debt
|
|||||||
|
|
||||||
// CreateAuctionsFromDeposit creates auctions from the input deposit
|
// CreateAuctionsFromDeposit creates auctions from the input deposit
|
||||||
func (k Keeper) CreateAuctionsFromDeposit(
|
func (k Keeper) CreateAuctionsFromDeposit(
|
||||||
ctx sdk.Context, collateral sdk.Coin, returnAddr sdk.AccAddress, debt, auctionSize sdk.Int,
|
ctx sdk.Context, collateral sdk.Coin, collateralType string, returnAddr sdk.AccAddress, debt, auctionSize sdk.Int,
|
||||||
principalDenom string) error {
|
principalDenom string) error {
|
||||||
|
|
||||||
// number of auctions of auctionSize
|
// number of auctions of auctionSize
|
||||||
@ -69,7 +69,7 @@ func (k Keeper) CreateAuctionsFromDeposit(
|
|||||||
unallocatedDebt = unallocatedDebt.Sub(sdk.OneInt())
|
unallocatedDebt = unallocatedDebt.Sub(sdk.OneInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
penalty := k.ApplyLiquidationPenalty(ctx, collateral.Denom, debtAmount)
|
penalty := k.ApplyLiquidationPenalty(ctx, collateralType, debtAmount)
|
||||||
|
|
||||||
_, err := k.auctionKeeper.StartCollateralAuction(
|
_, err := k.auctionKeeper.StartCollateralAuction(
|
||||||
ctx, types.LiquidatorMacc, sdk.NewCoin(collateral.Denom, auctionSize),
|
ctx, types.LiquidatorMacc, sdk.NewCoin(collateral.Denom, auctionSize),
|
||||||
@ -95,7 +95,7 @@ func (k Keeper) CreateAuctionsFromDeposit(
|
|||||||
unallocatedDebt = unallocatedDebt.Sub(sdk.OneInt())
|
unallocatedDebt = unallocatedDebt.Sub(sdk.OneInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
penalty := k.ApplyLiquidationPenalty(ctx, collateral.Denom, lastAuctionDebt)
|
penalty := k.ApplyLiquidationPenalty(ctx, collateralType, lastAuctionDebt)
|
||||||
|
|
||||||
_, err := k.auctionKeeper.StartCollateralAuction(
|
_, err := k.auctionKeeper.StartCollateralAuction(
|
||||||
ctx, types.LiquidatorMacc, sdk.NewCoin(collateral.Denom, lastAuctionCollateral),
|
ctx, types.LiquidatorMacc, sdk.NewCoin(collateral.Denom, lastAuctionCollateral),
|
||||||
|
@ -62,7 +62,7 @@ func (suite *AuctionTestSuite) TestCollateralAuction() {
|
|||||||
err := sk.MintCoins(suite.ctx, types.LiquidatorMacc, cs(c("debt", 21000000000), c("bnb", 190000000000)))
|
err := sk.MintCoins(suite.ctx, types.LiquidatorMacc, cs(c("debt", 21000000000), c("bnb", 190000000000)))
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
testDeposit := types.NewDeposit(1, suite.addrs[0], c("bnb", 190000000000))
|
testDeposit := types.NewDeposit(1, suite.addrs[0], c("bnb", 190000000000))
|
||||||
err = suite.keeper.AuctionCollateral(suite.ctx, types.Deposits{testDeposit}, i(21000000000), "usdx")
|
err = suite.keeper.AuctionCollateral(suite.ctx, types.Deposits{testDeposit}, "bnb-a", i(21000000000), "usdx")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@ -16,13 +15,13 @@ import (
|
|||||||
const BaseDigitFactor = 1000000000000000000
|
const BaseDigitFactor = 1000000000000000000
|
||||||
|
|
||||||
// AddCdp adds a cdp for a specific owner and collateral type
|
// AddCdp adds a cdp for a specific owner and collateral type
|
||||||
func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coin, principal sdk.Coin) error {
|
func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coin, principal sdk.Coin, collateralType string) error {
|
||||||
// validation
|
// validation
|
||||||
err := k.ValidateCollateral(ctx, collateral)
|
err := k.ValidateCollateral(ctx, collateral, collateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, found := k.GetCdpByOwnerAndDenom(ctx, owner, collateral.Denom)
|
_, found := k.GetCdpByOwnerAndCollateralType(ctx, owner, collateralType)
|
||||||
if found {
|
if found {
|
||||||
return sdkerrors.Wrapf(types.ErrCdpAlreadyExists, "owner %s, denom %s", owner, collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrCdpAlreadyExists, "owner %s, denom %s", owner, collateral.Denom)
|
||||||
}
|
}
|
||||||
@ -31,18 +30,18 @@ func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.ValidateDebtLimit(ctx, collateral.Denom, principal)
|
err = k.ValidateDebtLimit(ctx, collateralType, principal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = k.ValidateCollateralizationRatio(ctx, collateral, principal, sdk.NewCoin(principal.Denom, sdk.ZeroInt()))
|
err = k.ValidateCollateralizationRatio(ctx, collateral, collateralType, principal, sdk.NewCoin(principal.Denom, sdk.ZeroInt()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// send coins from the owners account to the cdp module
|
// send coins from the owners account to the cdp module
|
||||||
id := k.GetNextCdpID(ctx)
|
id := k.GetNextCdpID(ctx)
|
||||||
cdp := types.NewCDP(id, owner, collateral, principal, ctx.BlockHeader().Time)
|
cdp := types.NewCDP(id, owner, collateral, collateralType, principal, ctx.BlockHeader().Time)
|
||||||
deposit := types.NewDeposit(cdp.ID, owner, collateral)
|
deposit := types.NewDeposit(cdp.ID, owner, collateral)
|
||||||
err = k.supplyKeeper.SendCoinsFromAccountToModule(ctx, owner, types.ModuleName, sdk.NewCoins(collateral))
|
err = k.supplyKeeper.SendCoinsFromAccountToModule(ctx, owner, types.ModuleName, sdk.NewCoins(collateral))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -66,10 +65,10 @@ func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update total principal for input collateral type
|
// update total principal for input collateral type
|
||||||
k.IncrementTotalPrincipal(ctx, collateral.Denom, principal)
|
k.IncrementTotalPrincipal(ctx, collateralType, principal)
|
||||||
|
|
||||||
// set the cdp, deposit, and indexes in the store
|
// set the cdp, deposit, and indexes in the store
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, collateral, principal)
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, collateral, cdp.Type, principal)
|
||||||
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -109,7 +108,7 @@ func (k Keeper) SetCdpAndCollateralRatioIndex(ctx sdk.Context, cdp types.CDP, ra
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
k.IndexCdpByCollateralRatio(ctx, cdp.Collateral.Denom, cdp.ID, ratio)
|
k.IndexCdpByCollateralRatio(ctx, cdp.Type, cdp.ID, ratio)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,14 +125,14 @@ func (k Keeper) BurnDebtCoins(ctx sdk.Context, moduleAccount string, denom strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCdpID returns the id of the cdp corresponding to a specific owner and collateral denom
|
// GetCdpID returns the id of the cdp corresponding to a specific owner and collateral denom
|
||||||
func (k Keeper) GetCdpID(ctx sdk.Context, owner sdk.AccAddress, denom string) (uint64, bool) {
|
func (k Keeper) GetCdpID(ctx sdk.Context, owner sdk.AccAddress, collateralType string) (uint64, bool) {
|
||||||
|
|
||||||
cdpIDs, found := k.GetCdpIdsByOwner(ctx, owner)
|
cdpIDs, found := k.GetCdpIdsByOwner(ctx, owner)
|
||||||
if !found {
|
if !found {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
for _, id := range cdpIDs {
|
for _, id := range cdpIDs {
|
||||||
_, found = k.GetCDP(ctx, denom, id)
|
_, found = k.GetCDP(ctx, collateralType, id)
|
||||||
if found {
|
if found {
|
||||||
return id, true
|
return id, true
|
||||||
}
|
}
|
||||||
@ -154,14 +153,14 @@ func (k Keeper) GetCdpIdsByOwner(ctx sdk.Context, owner sdk.AccAddress) ([]uint6
|
|||||||
return cdpIDs, true
|
return cdpIDs, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCdpByOwnerAndDenom queries cdps owned by owner and returns the cdp with matching denom
|
// GetCdpByOwnerAndCollateralType queries cdps owned by owner and returns the cdp with matching denom
|
||||||
func (k Keeper) GetCdpByOwnerAndDenom(ctx sdk.Context, owner sdk.AccAddress, denom string) (types.CDP, bool) {
|
func (k Keeper) GetCdpByOwnerAndCollateralType(ctx sdk.Context, owner sdk.AccAddress, collateralType string) (types.CDP, bool) {
|
||||||
cdpIDs, found := k.GetCdpIdsByOwner(ctx, owner)
|
cdpIDs, found := k.GetCdpIdsByOwner(ctx, owner)
|
||||||
if !found {
|
if !found {
|
||||||
return types.CDP{}, false
|
return types.CDP{}, false
|
||||||
}
|
}
|
||||||
for _, id := range cdpIDs {
|
for _, id := range cdpIDs {
|
||||||
cdp, found := k.GetCDP(ctx, denom, id)
|
cdp, found := k.GetCDP(ctx, collateralType, id)
|
||||||
if found {
|
if found {
|
||||||
return cdp, true
|
return cdp, true
|
||||||
}
|
}
|
||||||
@ -170,10 +169,10 @@ func (k Keeper) GetCdpByOwnerAndDenom(ctx sdk.Context, owner sdk.AccAddress, den
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCDP returns the cdp associated with a particular collateral denom and id
|
// GetCDP returns the cdp associated with a particular collateral denom and id
|
||||||
func (k Keeper) GetCDP(ctx sdk.Context, collateralDenom string, cdpID uint64) (types.CDP, bool) {
|
func (k Keeper) GetCDP(ctx sdk.Context, collateralType string, cdpID uint64) (types.CDP, bool) {
|
||||||
// get store
|
// get store
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, collateralDenom)
|
db, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return types.CDP{}, false
|
return types.CDP{}, false
|
||||||
}
|
}
|
||||||
@ -191,7 +190,7 @@ func (k Keeper) GetCDP(ctx sdk.Context, collateralDenom string, cdpID uint64) (t
|
|||||||
// SetCDP sets a cdp in the store
|
// SetCDP sets a cdp in the store
|
||||||
func (k Keeper) SetCDP(ctx sdk.Context, cdp types.CDP) error {
|
func (k Keeper) SetCDP(ctx sdk.Context, cdp types.CDP) error {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, cdp.Collateral.Denom)
|
db, found := k.GetCollateralTypePrefix(ctx, cdp.Type)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrDenomPrefixNotFound, "%s", cdp.Collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrDenomPrefixNotFound, "%s", cdp.Collateral.Denom)
|
||||||
}
|
}
|
||||||
@ -203,7 +202,7 @@ func (k Keeper) SetCDP(ctx sdk.Context, cdp types.CDP) error {
|
|||||||
// DeleteCDP deletes a cdp from the store
|
// DeleteCDP deletes a cdp from the store
|
||||||
func (k Keeper) DeleteCDP(ctx sdk.Context, cdp types.CDP) error {
|
func (k Keeper) DeleteCDP(ctx sdk.Context, cdp types.CDP) error {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, cdp.Collateral.Denom)
|
db, found := k.GetCollateralTypePrefix(ctx, cdp.Type)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrDenomPrefixNotFound, "%s", cdp.Collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrDenomPrefixNotFound, "%s", cdp.Collateral.Denom)
|
||||||
}
|
}
|
||||||
@ -221,18 +220,18 @@ func (k Keeper) GetAllCdps(ctx sdk.Context) (cdps types.CDPs) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllCdpsByDenom returns all cdps of a particular collateral type from the store
|
// GetAllCdpsByCollateralType returns all cdps of a particular collateral type from the store
|
||||||
func (k Keeper) GetAllCdpsByDenom(ctx sdk.Context, denom string) (cdps types.CDPs) {
|
func (k Keeper) GetAllCdpsByCollateralType(ctx sdk.Context, collateralType string) (cdps types.CDPs) {
|
||||||
k.IterateCdpsByDenom(ctx, denom, func(cdp types.CDP) bool {
|
k.IterateCdpsByCollateralType(ctx, collateralType, func(cdp types.CDP) bool {
|
||||||
cdps = append(cdps, cdp)
|
cdps = append(cdps, cdp)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllCdpsByDenomAndRatio returns all cdps of a particular collateral type and below a certain collateralization ratio
|
// GetAllCdpsByCollateralTypeAndRatio returns all cdps of a particular collateral type and below a certain collateralization ratio
|
||||||
func (k Keeper) GetAllCdpsByDenomAndRatio(ctx sdk.Context, denom string, targetRatio sdk.Dec) (cdps types.CDPs) {
|
func (k Keeper) GetAllCdpsByCollateralTypeAndRatio(ctx sdk.Context, collateralType string, targetRatio sdk.Dec) (cdps types.CDPs) {
|
||||||
k.IterateCdpsByCollateralRatio(ctx, denom, targetRatio, func(cdp types.CDP) bool {
|
k.IterateCdpsByCollateralRatio(ctx, collateralType, targetRatio, func(cdp types.CDP) bool {
|
||||||
cdps = append(cdps, cdp)
|
cdps = append(cdps, cdp)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -292,21 +291,21 @@ func (k Keeper) RemoveCdpOwnerIndex(ctx sdk.Context, cdp types.CDP) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IndexCdpByCollateralRatio sets the cdp id in the store, indexed by the collateral type and collateral to debt ratio
|
// IndexCdpByCollateralRatio sets the cdp id in the store, indexed by the collateral type and collateral to debt ratio
|
||||||
func (k Keeper) IndexCdpByCollateralRatio(ctx sdk.Context, denom string, id uint64, collateralRatio sdk.Dec) {
|
func (k Keeper) IndexCdpByCollateralRatio(ctx sdk.Context, collateralType string, id uint64, collateralRatio sdk.Dec) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, denom)
|
db, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("denom %s prefix not found", denom))
|
panic(fmt.Sprintf("denom %s prefix not found", collateralType))
|
||||||
}
|
}
|
||||||
store.Set(types.CollateralRatioKey(db, id, collateralRatio), types.GetCdpIDBytes(id))
|
store.Set(types.CollateralRatioKey(db, id, collateralRatio), types.GetCdpIDBytes(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveCdpCollateralRatioIndex deletes the cdp id from the store's index of cdps by collateral type and collateral to debt ratio
|
// RemoveCdpCollateralRatioIndex deletes the cdp id from the store's index of cdps by collateral type and collateral to debt ratio
|
||||||
func (k Keeper) RemoveCdpCollateralRatioIndex(ctx sdk.Context, denom string, id uint64, collateralRatio sdk.Dec) {
|
func (k Keeper) RemoveCdpCollateralRatioIndex(ctx sdk.Context, collateralType string, id uint64, collateralRatio sdk.Dec) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, denom)
|
db, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("denom %s prefix not found", denom))
|
panic(fmt.Sprintf("denom %s prefix not found", collateralType))
|
||||||
}
|
}
|
||||||
store.Delete(types.CollateralRatioKey(db, id, collateralRatio))
|
store.Delete(types.CollateralRatioKey(db, id, collateralRatio))
|
||||||
}
|
}
|
||||||
@ -346,8 +345,8 @@ func (k Keeper) SetGovDenom(ctx sdk.Context, denom string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateCollateral validates that a collateral is valid for use in cdps
|
// ValidateCollateral validates that a collateral is valid for use in cdps
|
||||||
func (k Keeper) ValidateCollateral(ctx sdk.Context, collateral sdk.Coin) error {
|
func (k Keeper) ValidateCollateral(ctx sdk.Context, collateral sdk.Coin, collateralType string) error {
|
||||||
cp, found := k.GetCollateral(ctx, collateral.Denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrCollateralNotSupported, collateral.Denom)
|
return sdkerrors.Wrap(types.ErrCollateralNotSupported, collateral.Denom)
|
||||||
}
|
}
|
||||||
@ -387,12 +386,12 @@ func (k Keeper) ValidatePrincipalDraw(ctx sdk.Context, principal sdk.Coin, expec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateDebtLimit validates that the input debt amount does not exceed the global debt limit or the debt limit for that collateral
|
// ValidateDebtLimit validates that the input debt amount does not exceed the global debt limit or the debt limit for that collateral
|
||||||
func (k Keeper) ValidateDebtLimit(ctx sdk.Context, collateralDenom string, principal sdk.Coin) error {
|
func (k Keeper) ValidateDebtLimit(ctx sdk.Context, collateralType string, principal sdk.Coin) error {
|
||||||
cp, found := k.GetCollateral(ctx, collateralDenom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrCollateralNotSupported, collateralDenom)
|
return sdkerrors.Wrap(types.ErrCollateralNotSupported, collateralType)
|
||||||
}
|
}
|
||||||
totalPrincipal := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom).Add(principal.Amount)
|
totalPrincipal := k.GetTotalPrincipal(ctx, collateralType, principal.Denom).Add(principal.Amount)
|
||||||
collateralLimit := cp.DebtLimit.Amount
|
collateralLimit := cp.DebtLimit.Amount
|
||||||
if totalPrincipal.GT(collateralLimit) {
|
if totalPrincipal.GT(collateralLimit) {
|
||||||
return sdkerrors.Wrapf(types.ErrExceedsDebtLimit, "debt increase %s > collateral debt limit %s", sdk.NewCoins(sdk.NewCoin(principal.Denom, totalPrincipal)), sdk.NewCoins(sdk.NewCoin(principal.Denom, collateralLimit)))
|
return sdkerrors.Wrapf(types.ErrExceedsDebtLimit, "debt increase %s > collateral debt limit %s", sdk.NewCoins(sdk.NewCoin(principal.Denom, totalPrincipal)), sdk.NewCoins(sdk.NewCoin(principal.Denom, collateralLimit)))
|
||||||
@ -405,12 +404,12 @@ func (k Keeper) ValidateDebtLimit(ctx sdk.Context, collateralDenom string, princ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateCollateralizationRatio validate that adding the input principal doesn't put the cdp below the liquidation ratio
|
// ValidateCollateralizationRatio validate that adding the input principal doesn't put the cdp below the liquidation ratio
|
||||||
func (k Keeper) ValidateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coin, principal sdk.Coin, fees sdk.Coin) error {
|
func (k Keeper) ValidateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coin, collateralType string, principal sdk.Coin, fees sdk.Coin) error {
|
||||||
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, collateral, principal, fees, spot)
|
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, collateral, collateralType, principal, fees, spot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
liquidationRatio := k.getLiquidationRatio(ctx, collateral.Denom)
|
liquidationRatio := k.getLiquidationRatio(ctx, collateralType)
|
||||||
if collateralizationRatio.LT(liquidationRatio) {
|
if collateralizationRatio.LT(liquidationRatio) {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidCollateralRatio, "collateral %s, collateral ratio %s, liquidation ratio %s", collateral.Denom, collateralizationRatio, liquidationRatio)
|
return sdkerrors.Wrapf(types.ErrInvalidCollateralRatio, "collateral %s, collateral ratio %s, liquidation ratio %s", collateral.Denom, collateralizationRatio, liquidationRatio)
|
||||||
}
|
}
|
||||||
@ -418,21 +417,21 @@ func (k Keeper) ValidateCollateralizationRatio(ctx sdk.Context, collateral sdk.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculateCollateralToDebtRatio returns the collateral to debt ratio of the input collateral and debt amounts
|
// CalculateCollateralToDebtRatio returns the collateral to debt ratio of the input collateral and debt amounts
|
||||||
func (k Keeper) CalculateCollateralToDebtRatio(ctx sdk.Context, collateral sdk.Coin, debt sdk.Coin) sdk.Dec {
|
func (k Keeper) CalculateCollateralToDebtRatio(ctx sdk.Context, collateral sdk.Coin, collateralType string, debt sdk.Coin) sdk.Dec {
|
||||||
debtTotal := k.convertDebtToBaseUnits(ctx, debt)
|
debtTotal := k.convertDebtToBaseUnits(ctx, debt)
|
||||||
|
|
||||||
if debtTotal.IsZero() || debtTotal.GTE(types.MaxSortableDec) {
|
if debtTotal.IsZero() || debtTotal.GTE(types.MaxSortableDec) {
|
||||||
return types.MaxSortableDec.Sub(sdk.SmallestDec())
|
return types.MaxSortableDec.Sub(sdk.SmallestDec())
|
||||||
}
|
}
|
||||||
|
|
||||||
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral)
|
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral, collateralType)
|
||||||
return collateralBaseUnits.Quo(debtTotal)
|
return collateralBaseUnits.Quo(debtTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAugmentedCDP creates a new augmented CDP from an existing CDP
|
// LoadAugmentedCDP creates a new augmented CDP from an existing CDP
|
||||||
func (k Keeper) LoadAugmentedCDP(ctx sdk.Context, cdp types.CDP) types.AugmentedCDP {
|
func (k Keeper) LoadAugmentedCDP(ctx sdk.Context, cdp types.CDP) types.AugmentedCDP {
|
||||||
// calculate collateralization ratio
|
// calculate collateralization ratio
|
||||||
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral, cdp.Principal, cdp.AccumulatedFees, liquidation)
|
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral, cdp.Type, cdp.Principal, cdp.AccumulatedFees, liquidation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.AugmentedCDP{CDP: cdp}
|
return types.AugmentedCDP{CDP: cdp}
|
||||||
}
|
}
|
||||||
@ -446,16 +445,16 @@ func (k Keeper) LoadAugmentedCDP(ctx sdk.Context, cdp types.CDP) types.Augmented
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculateCollateralizationRatio returns the collateralization ratio of the input collateral to the input debt plus fees
|
// CalculateCollateralizationRatio returns the collateralization ratio of the input collateral to the input debt plus fees
|
||||||
func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coin, principal sdk.Coin, fees sdk.Coin, pfType pricefeedType) (sdk.Dec, error) {
|
func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coin, collateralType string, principal sdk.Coin, fees sdk.Coin, pfType pricefeedType) (sdk.Dec, error) {
|
||||||
if collateral.IsZero() {
|
if collateral.IsZero() {
|
||||||
return sdk.ZeroDec(), nil
|
return sdk.ZeroDec(), nil
|
||||||
}
|
}
|
||||||
var marketID string
|
var marketID string
|
||||||
switch pfType {
|
switch pfType {
|
||||||
case spot:
|
case spot:
|
||||||
marketID = k.getSpotMarketID(ctx, collateral.Denom)
|
marketID = k.getSpotMarketID(ctx, collateralType)
|
||||||
case liquidation:
|
case liquidation:
|
||||||
marketID = k.getliquidationMarketID(ctx, collateral.Denom)
|
marketID = k.getliquidationMarketID(ctx, collateralType)
|
||||||
default:
|
default:
|
||||||
return sdk.Dec{}, pfType.IsValid()
|
return sdk.Dec{}, pfType.IsValid()
|
||||||
}
|
}
|
||||||
@ -464,7 +463,7 @@ func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return sdk.Dec{}, err
|
return sdk.Dec{}, err
|
||||||
}
|
}
|
||||||
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral)
|
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral, collateralType)
|
||||||
collateralValue := collateralBaseUnits.Mul(price.Price)
|
collateralValue := collateralBaseUnits.Mul(price.Price)
|
||||||
|
|
||||||
prinicpalBaseUnits := k.convertDebtToBaseUnits(ctx, principal)
|
prinicpalBaseUnits := k.convertDebtToBaseUnits(ctx, principal)
|
||||||
@ -477,14 +476,14 @@ func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculateCollateralizationRatioFromAbsoluteRatio takes a coin's denom and an absolute ratio and returns the respective collateralization ratio
|
// CalculateCollateralizationRatioFromAbsoluteRatio takes a coin's denom and an absolute ratio and returns the respective collateralization ratio
|
||||||
func (k Keeper) CalculateCollateralizationRatioFromAbsoluteRatio(ctx sdk.Context, collateralDenom string, absoluteRatio sdk.Dec, pfType pricefeedType) (sdk.Dec, error) {
|
func (k Keeper) CalculateCollateralizationRatioFromAbsoluteRatio(ctx sdk.Context, collateralType string, absoluteRatio sdk.Dec, pfType pricefeedType) (sdk.Dec, error) {
|
||||||
// get price of collateral
|
// get price of collateral
|
||||||
var marketID string
|
var marketID string
|
||||||
switch pfType {
|
switch pfType {
|
||||||
case spot:
|
case spot:
|
||||||
marketID = k.getSpotMarketID(ctx, collateralDenom)
|
marketID = k.getSpotMarketID(ctx, collateralType)
|
||||||
case liquidation:
|
case liquidation:
|
||||||
marketID = k.getliquidationMarketID(ctx, collateralDenom)
|
marketID = k.getliquidationMarketID(ctx, collateralType)
|
||||||
default:
|
default:
|
||||||
return sdk.Dec{}, pfType.IsValid()
|
return sdk.Dec{}, pfType.IsValid()
|
||||||
}
|
}
|
||||||
@ -525,8 +524,8 @@ func (k Keeper) UpdatePricefeedStatus(ctx sdk.Context, marketID string) (ok bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// converts the input collateral to base units (ie multiplies the input by 10^(-ConversionFactor))
|
// converts the input collateral to base units (ie multiplies the input by 10^(-ConversionFactor))
|
||||||
func (k Keeper) convertCollateralToBaseUnits(ctx sdk.Context, collateral sdk.Coin) (baseUnits sdk.Dec) {
|
func (k Keeper) convertCollateralToBaseUnits(ctx sdk.Context, collateral sdk.Coin, collateralType string) (baseUnits sdk.Dec) {
|
||||||
cp, _ := k.GetCollateral(ctx, collateral.Denom)
|
cp, _ := k.GetCollateral(ctx, collateralType)
|
||||||
return sdk.NewDecFromInt(collateral.Amount).Mul(sdk.NewDecFromIntWithPrec(sdk.OneInt(), cp.ConversionFactor.Int64()))
|
return sdk.NewDecFromInt(collateral.Amount).Mul(sdk.NewDecFromIntWithPrec(sdk.OneInt(), cp.ConversionFactor.Int64()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,5 +547,5 @@ func (pft pricefeedType) IsValid() error {
|
|||||||
case spot, liquidation:
|
case spot, liquidation:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New(fmt.Sprintf("invalid pricefeed type: %s", pft))
|
return fmt.Errorf("invalid pricefeed type: %s", pft)
|
||||||
}
|
}
|
||||||
|
@ -47,17 +47,17 @@ func (suite *CdpTestSuite) TestAddCdp() {
|
|||||||
acc := ak.NewAccountWithAddress(suite.ctx, addrs[0])
|
acc := ak.NewAccountWithAddress(suite.ctx, addrs[0])
|
||||||
acc.SetCoins(cs(c("xrp", 200000000), c("btc", 500000000)))
|
acc.SetCoins(cs(c("xrp", 200000000), c("btc", 500000000)))
|
||||||
ak.SetAccount(suite.ctx, acc)
|
ak.SetAccount(suite.ctx, acc)
|
||||||
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("usdx", 26000000))
|
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("usdx", 26000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 500000000), c("usdx", 26000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 500000000), c("usdx", 26000000), "xrp-a")
|
||||||
suite.Error(err) // insufficient balance
|
suite.Error(err) // insufficient balance
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("xusd", 10000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("xusd", 10000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrDebtNotSupported))
|
suite.Require().True(errors.Is(err, types.ErrDebtNotSupported))
|
||||||
|
|
||||||
acc2 := ak.NewAccountWithAddress(suite.ctx, addrs[1])
|
acc2 := ak.NewAccountWithAddress(suite.ctx, addrs[1])
|
||||||
acc2.SetCoins(cs(c("btc", 500000000000)))
|
acc2.SetCoins(cs(c("btc", 500000000000)))
|
||||||
ak.SetAccount(suite.ctx, acc2)
|
ak.SetAccount(suite.ctx, acc2)
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[1], c("btc", 500000000000), c("usdx", 500000000001))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[1], c("btc", 500000000000), c("usdx", 500000000001), "btc-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrExceedsDebtLimit))
|
suite.Require().True(errors.Is(err, types.ErrExceedsDebtLimit))
|
||||||
|
|
||||||
ctx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Hour * 2))
|
ctx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Hour * 2))
|
||||||
@ -66,18 +66,18 @@ func (suite *CdpTestSuite) TestAddCdp() {
|
|||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
ok := suite.keeper.UpdatePricefeedStatus(ctx, "xrp:usd")
|
ok := suite.keeper.UpdatePricefeedStatus(ctx, "xrp:usd")
|
||||||
suite.False(ok)
|
suite.False(ok)
|
||||||
err = suite.keeper.AddCdp(ctx, addrs[0], c("xrp", 100000000), c("usdx", 10000000))
|
err = suite.keeper.AddCdp(ctx, addrs[0], c("xrp", 100000000), c("usdx", 10000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrPricefeedDown))
|
suite.Require().True(errors.Is(err, types.ErrPricefeedDown))
|
||||||
|
|
||||||
err = pk.SetCurrentPrices(suite.ctx, "xrp:usd")
|
err = pk.SetCurrentPrices(suite.ctx, "xrp:usd")
|
||||||
ok = suite.keeper.UpdatePricefeedStatus(suite.ctx, "xrp:usd")
|
ok = suite.keeper.UpdatePricefeedStatus(suite.ctx, "xrp:usd")
|
||||||
suite.True(ok)
|
suite.True(ok)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 100000000), c("usdx", 10000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 100000000), c("usdx", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
id := suite.keeper.GetNextCdpID(suite.ctx)
|
id := suite.keeper.GetNextCdpID(suite.ctx)
|
||||||
suite.Equal(uint64(2), id)
|
suite.Equal(uint64(2), id)
|
||||||
tp := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tp := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
suite.Equal(i(10000000), tp)
|
suite.Equal(i(10000000), tp)
|
||||||
sk := suite.app.GetSupplyKeeper()
|
sk := suite.app.GetSupplyKeeper()
|
||||||
macc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
macc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
@ -85,30 +85,30 @@ func (suite *CdpTestSuite) TestAddCdp() {
|
|||||||
acc = ak.GetAccount(suite.ctx, addrs[0])
|
acc = ak.GetAccount(suite.ctx, addrs[0])
|
||||||
suite.Equal(cs(c("usdx", 10000000), c("xrp", 100000000), c("btc", 500000000)), acc.GetCoins())
|
suite.Equal(cs(c("usdx", 10000000), c("xrp", 100000000), c("btc", 500000000)), acc.GetCoins())
|
||||||
|
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("btc", 500000000), c("usdx", 26667000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("btc", 500000000), c("usdx", 26667000000), "btc-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
|
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("btc", 500000000), c("usdx", 100000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("btc", 500000000), c("usdx", 100000000), "btc-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
id = suite.keeper.GetNextCdpID(suite.ctx)
|
id = suite.keeper.GetNextCdpID(suite.ctx)
|
||||||
suite.Equal(uint64(3), id)
|
suite.Equal(uint64(3), id)
|
||||||
tp = suite.keeper.GetTotalPrincipal(suite.ctx, "btc", "usdx")
|
tp = suite.keeper.GetTotalPrincipal(suite.ctx, "btc-a", "usdx")
|
||||||
suite.Equal(i(100000000), tp)
|
suite.Equal(i(100000000), tp)
|
||||||
macc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
macc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
suite.Equal(cs(c("debt", 110000000), c("xrp", 100000000), c("btc", 500000000)), macc.GetCoins())
|
suite.Equal(cs(c("debt", 110000000), c("xrp", 100000000), c("btc", 500000000)), macc.GetCoins())
|
||||||
acc = ak.GetAccount(suite.ctx, addrs[0])
|
acc = ak.GetAccount(suite.ctx, addrs[0])
|
||||||
suite.Equal(cs(c("usdx", 110000000), c("xrp", 100000000)), acc.GetCoins())
|
suite.Equal(cs(c("usdx", 110000000), c("xrp", 100000000)), acc.GetCoins())
|
||||||
|
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("lol", 100), c("usdx", 10))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("lol", 100), c("usdx", 10), "lol-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCollateralNotSupported))
|
suite.Require().True(errors.Is(err, types.ErrCollateralNotSupported))
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 100), c("usdx", 10))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 100), c("usdx", 10), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpAlreadyExists))
|
suite.Require().True(errors.Is(err, types.ErrCdpAlreadyExists))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestGetSetDenomByte() {
|
func (suite *CdpTestSuite) TestGetSetCollateralTypeByte() {
|
||||||
_, found := suite.keeper.GetDenomPrefix(suite.ctx, "lol")
|
_, found := suite.keeper.GetCollateralTypePrefix(suite.ctx, "lol-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
db, found := suite.keeper.GetDenomPrefix(suite.ctx, "xrp")
|
db, found := suite.keeper.GetCollateralTypePrefix(suite.ctx, "xrp-a")
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(byte(0x20), db)
|
suite.Equal(byte(0x20), db)
|
||||||
}
|
}
|
||||||
@ -129,66 +129,66 @@ func (suite *CdpTestSuite) TestGetNextCdpID() {
|
|||||||
|
|
||||||
func (suite *CdpTestSuite) TestGetSetCdp() {
|
func (suite *CdpTestSuite) TestGetSetCdp() {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
||||||
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), c("usdx", 1), tmtime.Canonical(time.Now()))
|
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), "xrp-a", c("usdx", 1), tmtime.Canonical(time.Now()))
|
||||||
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
t, found := suite.keeper.GetCDP(suite.ctx, "xrp", types.DefaultCdpStartingID)
|
t, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", types.DefaultCdpStartingID)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(cdp, t)
|
suite.Equal(cdp, t)
|
||||||
_, found = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
_, found = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
suite.keeper.DeleteCDP(suite.ctx, cdp)
|
suite.keeper.DeleteCDP(suite.ctx, cdp)
|
||||||
_, found = suite.keeper.GetCDP(suite.ctx, "btc", types.DefaultCdpStartingID)
|
_, found = suite.keeper.GetCDP(suite.ctx, "btc-a", types.DefaultCdpStartingID)
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestGetSetCdpId() {
|
func (suite *CdpTestSuite) TestGetSetCdpId() {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), c("usdx", 1), tmtime.Canonical(time.Now()))
|
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), "xrp-a", c("usdx", 1), tmtime.Canonical(time.Now()))
|
||||||
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, cdp)
|
suite.keeper.IndexCdpByOwner(suite.ctx, cdp)
|
||||||
id, found := suite.keeper.GetCdpID(suite.ctx, addrs[0], "xrp")
|
id, found := suite.keeper.GetCdpID(suite.ctx, addrs[0], "xrp-a")
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(types.DefaultCdpStartingID, id)
|
suite.Equal(types.DefaultCdpStartingID, id)
|
||||||
_, found = suite.keeper.GetCdpID(suite.ctx, addrs[0], "lol")
|
_, found = suite.keeper.GetCdpID(suite.ctx, addrs[0], "lol-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
_, found = suite.keeper.GetCdpID(suite.ctx, addrs[1], "xrp")
|
_, found = suite.keeper.GetCdpID(suite.ctx, addrs[1], "xrp-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestGetSetCdpByOwnerAndDenom() {
|
func (suite *CdpTestSuite) TestGetSetCdpByOwnerAndCollateralType() {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), c("usdx", 1), tmtime.Canonical(time.Now()))
|
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), "xrp-a", c("usdx", 1), tmtime.Canonical(time.Now()))
|
||||||
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
err := suite.keeper.SetCDP(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, cdp)
|
suite.keeper.IndexCdpByOwner(suite.ctx, cdp)
|
||||||
t, found := suite.keeper.GetCdpByOwnerAndDenom(suite.ctx, addrs[0], "xrp")
|
t, found := suite.keeper.GetCdpByOwnerAndCollateralType(suite.ctx, addrs[0], "xrp-a")
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(cdp, t)
|
suite.Equal(cdp, t)
|
||||||
_, found = suite.keeper.GetCdpByOwnerAndDenom(suite.ctx, addrs[0], "lol")
|
_, found = suite.keeper.GetCdpByOwnerAndCollateralType(suite.ctx, addrs[0], "lol-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
_, found = suite.keeper.GetCdpByOwnerAndDenom(suite.ctx, addrs[1], "xrp")
|
_, found = suite.keeper.GetCdpByOwnerAndCollateralType(suite.ctx, addrs[1], "xrp-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
suite.NotPanics(func() { suite.keeper.IndexCdpByOwner(suite.ctx, cdp) })
|
suite.NotPanics(func() { suite.keeper.IndexCdpByOwner(suite.ctx, cdp) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestCalculateCollateralToDebtRatio() {
|
func (suite *CdpTestSuite) TestCalculateCollateralToDebtRatio() {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
||||||
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 3), c("usdx", 1), tmtime.Canonical(time.Now()))
|
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 3), "xrp-a", c("usdx", 1), tmtime.Canonical(time.Now()))
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Type, cdp.Principal)
|
||||||
suite.Equal(sdk.MustNewDecFromStr("3.0"), cr)
|
suite.Equal(sdk.MustNewDecFromStr("3.0"), cr)
|
||||||
cdp = types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), c("usdx", 2), tmtime.Canonical(time.Now()))
|
cdp = types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 1), "xrp-a", c("usdx", 2), tmtime.Canonical(time.Now()))
|
||||||
cr = suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
cr = suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Type, cdp.Principal)
|
||||||
suite.Equal(sdk.MustNewDecFromStr("0.5"), cr)
|
suite.Equal(sdk.MustNewDecFromStr("0.5"), cr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestSetCdpByCollateralRatio() {
|
func (suite *CdpTestSuite) TestSetCdpByCollateralRatio() {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
||||||
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 3), c("usdx", 1), tmtime.Canonical(time.Now()))
|
cdp := types.NewCDP(types.DefaultCdpStartingID, addrs[0], c("xrp", 3), "xrp-a", c("usdx", 1), tmtime.Canonical(time.Now()))
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Type, cdp.Principal)
|
||||||
suite.NotPanics(func() { suite.keeper.IndexCdpByCollateralRatio(suite.ctx, cdp.Collateral.Denom, cdp.ID, cr) })
|
suite.NotPanics(func() { suite.keeper.IndexCdpByCollateralRatio(suite.ctx, cdp.Type, cdp.ID, cr) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestIterateCdps() {
|
func (suite *CdpTestSuite) TestIterateCdps() {
|
||||||
@ -197,29 +197,29 @@ func (suite *CdpTestSuite) TestIterateCdps() {
|
|||||||
err := suite.keeper.SetCDP(suite.ctx, c)
|
err := suite.keeper.SetCDP(suite.ctx, c)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Type, c.Principal)
|
||||||
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Collateral.Denom, c.ID, cr)
|
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Type, c.ID, cr)
|
||||||
}
|
}
|
||||||
t := suite.keeper.GetAllCdps(suite.ctx)
|
t := suite.keeper.GetAllCdps(suite.ctx)
|
||||||
suite.Equal(4, len(t))
|
suite.Equal(4, len(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestIterateCdpsByDenom() {
|
func (suite *CdpTestSuite) TestIterateCdpsByCollateralType() {
|
||||||
cdps := cdps()
|
cdps := cdps()
|
||||||
for _, c := range cdps {
|
for _, c := range cdps {
|
||||||
err := suite.keeper.SetCDP(suite.ctx, c)
|
err := suite.keeper.SetCDP(suite.ctx, c)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Type, c.Principal)
|
||||||
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Collateral.Denom, c.ID, cr)
|
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Type, c.ID, cr)
|
||||||
}
|
}
|
||||||
xrpCdps := suite.keeper.GetAllCdpsByDenom(suite.ctx, "xrp")
|
xrpCdps := suite.keeper.GetAllCdpsByCollateralType(suite.ctx, "xrp-a")
|
||||||
suite.Equal(3, len(xrpCdps))
|
suite.Equal(3, len(xrpCdps))
|
||||||
btcCdps := suite.keeper.GetAllCdpsByDenom(suite.ctx, "btc")
|
btcCdps := suite.keeper.GetAllCdpsByCollateralType(suite.ctx, "btc-a")
|
||||||
suite.Equal(1, len(btcCdps))
|
suite.Equal(1, len(btcCdps))
|
||||||
suite.keeper.DeleteCDP(suite.ctx, cdps[0])
|
suite.keeper.DeleteCDP(suite.ctx, cdps[0])
|
||||||
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[0])
|
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[0])
|
||||||
xrpCdps = suite.keeper.GetAllCdpsByDenom(suite.ctx, "xrp")
|
xrpCdps = suite.keeper.GetAllCdpsByCollateralType(suite.ctx, "xrp-a")
|
||||||
suite.Equal(2, len(xrpCdps))
|
suite.Equal(2, len(xrpCdps))
|
||||||
suite.keeper.DeleteCDP(suite.ctx, cdps[1])
|
suite.keeper.DeleteCDP(suite.ctx, cdps[1])
|
||||||
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[1])
|
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[1])
|
||||||
@ -235,31 +235,31 @@ func (suite *CdpTestSuite) TestIterateCdpsByCollateralRatio() {
|
|||||||
err := suite.keeper.SetCDP(suite.ctx, c)
|
err := suite.keeper.SetCDP(suite.ctx, c)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Type, c.Principal)
|
||||||
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Collateral.Denom, c.ID, cr)
|
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Type, c.ID, cr)
|
||||||
}
|
}
|
||||||
xrpCdps := suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("1.25"))
|
xrpCdps := suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("1.25"))
|
||||||
suite.Equal(0, len(xrpCdps))
|
suite.Equal(0, len(xrpCdps))
|
||||||
xrpCdps = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("1.25").Add(sdk.SmallestDec()))
|
xrpCdps = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("1.25").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(1, len(xrpCdps))
|
suite.Equal(1, len(xrpCdps))
|
||||||
xrpCdps = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("2.0").Add(sdk.SmallestDec()))
|
xrpCdps = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("2.0").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(2, len(xrpCdps))
|
suite.Equal(2, len(xrpCdps))
|
||||||
xrpCdps = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("100.0").Add(sdk.SmallestDec()))
|
xrpCdps = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("100.0").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(3, len(xrpCdps))
|
suite.Equal(3, len(xrpCdps))
|
||||||
suite.keeper.DeleteCDP(suite.ctx, cdps[0])
|
suite.keeper.DeleteCDP(suite.ctx, cdps[0])
|
||||||
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[0])
|
suite.keeper.RemoveCdpOwnerIndex(suite.ctx, cdps[0])
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdps[0].Collateral, cdps[0].Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdps[0].Collateral, cdps[0].Type, cdps[0].Principal)
|
||||||
suite.keeper.RemoveCdpCollateralRatioIndex(suite.ctx, cdps[0].Collateral.Denom, cdps[0].ID, cr)
|
suite.keeper.RemoveCdpCollateralRatioIndex(suite.ctx, cdps[0].Type, cdps[0].ID, cr)
|
||||||
xrpCdps = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("2.0").Add(sdk.SmallestDec()))
|
xrpCdps = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("2.0").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(1, len(xrpCdps))
|
suite.Equal(1, len(xrpCdps))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CdpTestSuite) TestValidateCollateral() {
|
func (suite *CdpTestSuite) TestValidateCollateral() {
|
||||||
c := sdk.NewCoin("xrp", sdk.NewInt(1))
|
c := sdk.NewCoin("xrp", sdk.NewInt(1))
|
||||||
err := suite.keeper.ValidateCollateral(suite.ctx, c)
|
err := suite.keeper.ValidateCollateral(suite.ctx, c, "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
c = sdk.NewCoin("lol", sdk.NewInt(1))
|
c = sdk.NewCoin("lol", sdk.NewInt(1))
|
||||||
err = suite.keeper.ValidateCollateral(suite.ctx, c)
|
err = suite.keeper.ValidateCollateral(suite.ctx, c, "lol-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCollateralNotSupported))
|
suite.Require().True(errors.Is(err, types.ErrCollateralNotSupported))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,10 +271,10 @@ func (suite *CdpTestSuite) TestValidatePrincipal() {
|
|||||||
err = suite.keeper.ValidatePrincipalAdd(suite.ctx, d)
|
err = suite.keeper.ValidatePrincipalAdd(suite.ctx, d)
|
||||||
suite.Require().True(errors.Is(err, types.ErrDebtNotSupported))
|
suite.Require().True(errors.Is(err, types.ErrDebtNotSupported))
|
||||||
d = sdk.NewCoin("usdx", sdk.NewInt(1000000000001))
|
d = sdk.NewCoin("usdx", sdk.NewInt(1000000000001))
|
||||||
err = suite.keeper.ValidateDebtLimit(suite.ctx, "xrp", d)
|
err = suite.keeper.ValidateDebtLimit(suite.ctx, "xrp-a", d)
|
||||||
suite.Require().True(errors.Is(err, types.ErrExceedsDebtLimit))
|
suite.Require().True(errors.Is(err, types.ErrExceedsDebtLimit))
|
||||||
d = sdk.NewCoin("usdx", sdk.NewInt(100000000))
|
d = sdk.NewCoin("usdx", sdk.NewInt(100000000))
|
||||||
err = suite.keeper.ValidateDebtLimit(suite.ctx, "xrp", d)
|
err = suite.keeper.ValidateDebtLimit(suite.ctx, "xrp-a", d)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,13 +283,13 @@ func (suite *CdpTestSuite) TestCalculateCollateralizationRatio() {
|
|||||||
err := suite.keeper.SetCDP(suite.ctx, c)
|
err := suite.keeper.SetCDP(suite.ctx, c)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
suite.keeper.IndexCdpByOwner(suite.ctx, c)
|
||||||
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Principal)
|
cr := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, c.Collateral, c.Type, c.Principal)
|
||||||
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Collateral.Denom, c.ID, cr)
|
suite.keeper.IndexCdpByCollateralRatio(suite.ctx, c.Type, c.ID, cr)
|
||||||
cr, err = suite.keeper.CalculateCollateralizationRatio(suite.ctx, c.Collateral, c.Principal, c.AccumulatedFees, "spot")
|
cr, err = suite.keeper.CalculateCollateralizationRatio(suite.ctx, c.Collateral, c.Type, c.Principal, c.AccumulatedFees, "spot")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.Equal(d("2.5"), cr)
|
suite.Equal(d("2.5"), cr)
|
||||||
c.AccumulatedFees = sdk.NewCoin("usdx", i(10000000))
|
c.AccumulatedFees = sdk.NewCoin("usdx", i(10000000))
|
||||||
cr, err = suite.keeper.CalculateCollateralizationRatio(suite.ctx, c.Collateral, c.Principal, c.AccumulatedFees, "spot")
|
cr, err = suite.keeper.CalculateCollateralizationRatio(suite.ctx, c.Collateral, c.Type, c.Principal, c.AccumulatedFees, "spot")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.Equal(d("1.25"), cr)
|
suite.Equal(d("1.25"), cr)
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// DepositCollateral adds collateral to a cdp
|
// DepositCollateral adds collateral to a cdp
|
||||||
func (k Keeper) DepositCollateral(ctx sdk.Context, owner, depositor sdk.AccAddress, collateral sdk.Coin) error {
|
func (k Keeper) DepositCollateral(ctx sdk.Context, owner, depositor sdk.AccAddress, collateral sdk.Coin, collateralType string) error {
|
||||||
// check that collateral exists and has a functioning pricefeed
|
// check that collateral exists and has a functioning pricefeed
|
||||||
err := k.ValidateCollateral(ctx, collateral)
|
err := k.ValidateCollateral(ctx, collateral, collateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cdp, found := k.GetCdpByOwnerAndDenom(ctx, owner, collateral.Denom)
|
cdp, found := k.GetCdpByOwnerAndCollateralType(ctx, owner, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, collateral %s", owner, collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, collateral %s", owner, collateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
deposit, found := k.GetDeposit(ctx, cdp.ID, depositor)
|
deposit, found := k.GetDeposit(ctx, cdp.ID, depositor)
|
||||||
@ -42,37 +42,37 @@ func (k Keeper) DepositCollateral(ctx sdk.Context, owner, depositor sdk.AccAddre
|
|||||||
|
|
||||||
k.SetDeposit(ctx, deposit)
|
k.SetDeposit(ctx, deposit)
|
||||||
|
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Collateral.Denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
|
|
||||||
cdp.Collateral = cdp.Collateral.Add(collateral)
|
cdp.Collateral = cdp.Collateral.Add(collateral)
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithdrawCollateral removes collateral from a cdp if it does not put the cdp below the liquidation ratio
|
// WithdrawCollateral removes collateral from a cdp if it does not put the cdp below the liquidation ratio
|
||||||
func (k Keeper) WithdrawCollateral(ctx sdk.Context, owner, depositor sdk.AccAddress, collateral sdk.Coin) error {
|
func (k Keeper) WithdrawCollateral(ctx sdk.Context, owner, depositor sdk.AccAddress, collateral sdk.Coin, collateralType string) error {
|
||||||
err := k.ValidateCollateral(ctx, collateral)
|
err := k.ValidateCollateral(ctx, collateral, collateralType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cdp, found := k.GetCdpByOwnerAndDenom(ctx, owner, collateral.Denom)
|
cdp, found := k.GetCdpByOwnerAndCollateralType(ctx, owner, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, collateral %s", owner, collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, collateral %s", owner, collateral.Denom)
|
||||||
}
|
}
|
||||||
deposit, found := k.GetDeposit(ctx, cdp.ID, depositor)
|
deposit, found := k.GetDeposit(ctx, cdp.ID, depositor)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrDepositNotFound, "depositor %s, collateral %s", depositor, collateral.Denom)
|
return sdkerrors.Wrapf(types.ErrDepositNotFound, "depositor %s, collateral %s %s", depositor, collateral.Denom, collateralType)
|
||||||
}
|
}
|
||||||
if collateral.Amount.GT(deposit.Amount.Amount) {
|
if collateral.Amount.GT(deposit.Amount.Amount) {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidWithdrawAmount, "collateral %s, deposit %s", collateral, deposit.Amount)
|
return sdkerrors.Wrapf(types.ErrInvalidWithdrawAmount, "collateral %s, deposit %s", collateral, deposit.Amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral.Sub(collateral), cdp.Principal, cdp.AccumulatedFees, spot)
|
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral.Sub(collateral), cdp.Type, cdp.Principal, cdp.AccumulatedFees, spot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
liquidationRatio := k.getLiquidationRatio(ctx, collateral.Denom)
|
liquidationRatio := k.getLiquidationRatio(ctx, cdp.Type)
|
||||||
if collateralizationRatio.LT(liquidationRatio) {
|
if collateralizationRatio.LT(liquidationRatio) {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidCollateralRatio, "collateral %s, collateral ratio %s, liquidation ration %s", collateral.Denom, collateralizationRatio, liquidationRatio)
|
return sdkerrors.Wrapf(types.ErrInvalidCollateralRatio, "collateral %s, collateral ratio %s, liquidation ration %s", collateral.Denom, collateralizationRatio, liquidationRatio)
|
||||||
}
|
}
|
||||||
@ -88,11 +88,11 @@ func (k Keeper) WithdrawCollateral(ctx sdk.Context, owner, depositor sdk.AccAddr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Collateral.Denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
|
|
||||||
cdp.Collateral = cdp.Collateral.Sub(collateral)
|
cdp.Collateral = cdp.Collateral.Sub(collateral)
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -44,7 +44,7 @@ func (suite *DepositTestSuite) SetupTest() {
|
|||||||
suite.keeper = keeper
|
suite.keeper = keeper
|
||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
suite.addrs = addrs
|
suite.addrs = addrs
|
||||||
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 400000000), c("usdx", 10000000))
|
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 400000000), c("usdx", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ func (suite *DepositTestSuite) TestGetSetDeposit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DepositTestSuite) TestDepositCollateral() {
|
func (suite *DepositTestSuite) TestDepositCollateral() {
|
||||||
err := suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 10000000))
|
err := suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
d, found := suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[0])
|
d, found := suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[0])
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -73,19 +73,19 @@ func (suite *DepositTestSuite) TestDepositCollateral() {
|
|||||||
ds := suite.keeper.GetDeposits(suite.ctx, uint64(1))
|
ds := suite.keeper.GetDeposits(suite.ctx, uint64(1))
|
||||||
suite.Equal(1, len(ds))
|
suite.Equal(1, len(ds))
|
||||||
suite.True(ds[0].Equals(td))
|
suite.True(ds[0].Equals(td))
|
||||||
cd, _ := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(1))
|
cd, _ := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(1))
|
||||||
suite.Equal(c("xrp", 410000000), cd.Collateral)
|
suite.Equal(c("xrp", 410000000), cd.Collateral)
|
||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
||||||
suite.Equal(i(90000000), acc.GetCoins().AmountOf("xrp"))
|
suite.Equal(i(90000000), acc.GetCoins().AmountOf("xrp"))
|
||||||
|
|
||||||
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("btc", 1))
|
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("btc", 1), "btc-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
|
|
||||||
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 1))
|
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 1), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
|
|
||||||
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[1], c("xrp", 10000000))
|
err = suite.keeper.DepositCollateral(suite.ctx, suite.addrs[0], suite.addrs[1], c("xrp", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
d, found = suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[1])
|
d, found = suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[1])
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
@ -97,21 +97,21 @@ func (suite *DepositTestSuite) TestDepositCollateral() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DepositTestSuite) TestWithdrawCollateral() {
|
func (suite *DepositTestSuite) TestWithdrawCollateral() {
|
||||||
err := suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 400000000))
|
err := suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 400000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 321000000))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 321000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 10000000))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 10000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
|
|
||||||
cd, _ := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(1))
|
cd, _ := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(1))
|
||||||
cd.AccumulatedFees = c("usdx", 1)
|
cd.AccumulatedFees = c("usdx", 1)
|
||||||
err = suite.keeper.SetCDP(suite.ctx, cd)
|
err = suite.keeper.SetCDP(suite.ctx, cd)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 320000000))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 320000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
|
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 10000000))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[0], c("xrp", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
dep, _ := suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[0])
|
dep, _ := suite.keeper.GetDeposit(suite.ctx, uint64(1), suite.addrs[0])
|
||||||
td := types.NewDeposit(uint64(1), suite.addrs[0], c("xrp", 390000000))
|
td := types.NewDeposit(uint64(1), suite.addrs[0], c("xrp", 390000000))
|
||||||
@ -120,7 +120,7 @@ func (suite *DepositTestSuite) TestWithdrawCollateral() {
|
|||||||
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
||||||
suite.Equal(i(110000000), acc.GetCoins().AmountOf("xrp"))
|
suite.Equal(i(110000000), acc.GetCoins().AmountOf("xrp"))
|
||||||
|
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[1], c("xrp", 10000000))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[0], suite.addrs[1], c("xrp", 10000000), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrDepositNotFound))
|
suite.Require().True(errors.Is(err, types.ErrDepositNotFound))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,23 +10,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddPrincipal adds debt to a cdp if the additional debt does not put the cdp below the liquidation ratio
|
// AddPrincipal adds debt to a cdp if the additional debt does not put the cdp below the liquidation ratio
|
||||||
func (k Keeper) AddPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom string, principal sdk.Coin) error {
|
func (k Keeper) AddPrincipal(ctx sdk.Context, owner sdk.AccAddress, collateralType string, principal sdk.Coin) error {
|
||||||
// validation
|
// validation
|
||||||
cdp, found := k.GetCdpByOwnerAndDenom(ctx, owner, denom)
|
cdp, found := k.GetCdpByOwnerAndCollateralType(ctx, owner, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", owner, denom)
|
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", owner, collateralType)
|
||||||
}
|
}
|
||||||
err := k.ValidatePrincipalDraw(ctx, principal, cdp.Principal.Denom)
|
err := k.ValidatePrincipalDraw(ctx, principal, cdp.Principal.Denom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.ValidateDebtLimit(ctx, cdp.Collateral.Denom, principal)
|
err = k.ValidateDebtLimit(ctx, cdp.Type, principal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.ValidateCollateralizationRatio(ctx, cdp.Collateral, cdp.Principal.Add(principal), cdp.AccumulatedFees)
|
err = k.ValidateCollateralizationRatio(ctx, cdp.Collateral, cdp.Type, cdp.Principal.Add(principal), cdp.AccumulatedFees)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -57,27 +57,27 @@ func (k Keeper) AddPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom string
|
|||||||
)
|
)
|
||||||
|
|
||||||
// remove old collateral:debt index
|
// remove old collateral:debt index
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
|
|
||||||
// update cdp state
|
// update cdp state
|
||||||
cdp.Principal = cdp.Principal.Add(principal)
|
cdp.Principal = cdp.Principal.Add(principal)
|
||||||
|
|
||||||
// increment total principal for the input collateral type
|
// increment total principal for the input collateral type
|
||||||
k.IncrementTotalPrincipal(ctx, cdp.Collateral.Denom, principal)
|
k.IncrementTotalPrincipal(ctx, cdp.Type, principal)
|
||||||
|
|
||||||
// set cdp state and indexes in the store
|
// set cdp state and indexes in the store
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepayPrincipal removes debt from the cdp
|
// RepayPrincipal removes debt from the cdp
|
||||||
// If all debt is repaid, the collateral is returned to depositors and the cdp is removed from the store
|
// If all debt is repaid, the collateral is returned to depositors and the cdp is removed from the store
|
||||||
func (k Keeper) RepayPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom string, payment sdk.Coin) error {
|
func (k Keeper) RepayPrincipal(ctx sdk.Context, owner sdk.AccAddress, collateralType string, payment sdk.Coin) error {
|
||||||
// validation
|
// validation
|
||||||
cdp, found := k.GetCdpByOwnerAndDenom(ctx, owner, denom)
|
cdp, found := k.GetCdpByOwnerAndCollateralType(ctx, owner, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", owner, denom)
|
return sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", owner, collateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := k.ValidatePaymentCoins(ctx, cdp, payment)
|
err := k.ValidatePaymentCoins(ctx, cdp, payment)
|
||||||
@ -134,8 +134,8 @@ func (k Keeper) RepayPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom stri
|
|||||||
)
|
)
|
||||||
|
|
||||||
// remove the old collateral:debt ratio index
|
// remove the old collateral:debt ratio index
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, totalPrincipal)
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, totalPrincipal)
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
|
|
||||||
// update cdp state
|
// update cdp state
|
||||||
if !principalPayment.IsZero() {
|
if !principalPayment.IsZero() {
|
||||||
@ -144,7 +144,7 @@ func (k Keeper) RepayPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom stri
|
|||||||
cdp.AccumulatedFees = cdp.AccumulatedFees.Sub(feePayment)
|
cdp.AccumulatedFees = cdp.AccumulatedFees.Sub(feePayment)
|
||||||
|
|
||||||
// decrement the total principal for the input collateral type
|
// decrement the total principal for the input collateral type
|
||||||
k.DecrementTotalPrincipal(ctx, denom, feePayment.Add(principalPayment))
|
k.DecrementTotalPrincipal(ctx, cdp.Type, feePayment.Add(principalPayment))
|
||||||
|
|
||||||
// if the debt is fully paid, return collateral to depositors,
|
// if the debt is fully paid, return collateral to depositors,
|
||||||
// and remove the cdp and indexes from the store
|
// and remove the cdp and indexes from the store
|
||||||
@ -167,7 +167,7 @@ func (k Keeper) RepayPrincipal(ctx sdk.Context, owner sdk.AccAddress, denom stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set cdp state and update indexes
|
// set cdp state and update indexes
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
return k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,72 +46,72 @@ func (suite *DrawTestSuite) SetupTest() {
|
|||||||
suite.keeper = keeper
|
suite.keeper = keeper
|
||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
suite.addrs = addrs
|
suite.addrs = addrs
|
||||||
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 400000000), c("usdx", 10000000))
|
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 400000000), c("usdx", 10000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DrawTestSuite) TestAddRepayPrincipal() {
|
func (suite *DrawTestSuite) TestAddRepayPrincipal() {
|
||||||
|
|
||||||
err := suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
err := suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
t, found := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(1))
|
t, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(1))
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(c("usdx", 20000000), t.Principal)
|
suite.Equal(c("usdx", 20000000), t.Principal)
|
||||||
ctd := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, t.Collateral, t.Principal.Add(t.AccumulatedFees))
|
ctd := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, t.Collateral, "xrp-a", t.Principal.Add(t.AccumulatedFees))
|
||||||
suite.Equal(d("20.0"), ctd)
|
suite.Equal(d("20.0"), ctd)
|
||||||
ts := suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("20.0"))
|
ts := suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("20.0"))
|
||||||
suite.Equal(0, len(ts))
|
suite.Equal(0, len(ts))
|
||||||
ts = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("20.0").Add(sdk.SmallestDec()))
|
ts = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("20.0").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(ts[0], t)
|
suite.Equal(ts[0], t)
|
||||||
tp := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tp := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
suite.Equal(i(20000000), tp)
|
suite.Equal(i(20000000), tp)
|
||||||
sk := suite.app.GetSupplyKeeper()
|
sk := suite.app.GetSupplyKeeper()
|
||||||
acc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
acc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
suite.Equal(cs(c("xrp", 400000000), c("debt", 20000000)), acc.GetCoins())
|
suite.Equal(cs(c("xrp", 400000000), c("debt", 20000000)), acc.GetCoins())
|
||||||
|
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp", c("susd", 10000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("susd", 10000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidDebtRequest))
|
suite.Require().True(errors.Is(err, types.ErrInvalidDebtRequest))
|
||||||
|
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[1], "xrp", c("usdx", 10000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[1], "xrp-a", c("usdx", 10000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp", c("xusd", 10000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("xusd", 10000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidDebtRequest))
|
suite.Require().True(errors.Is(err, types.ErrInvalidDebtRequest))
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 311000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 311000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
suite.Require().True(errors.Is(err, types.ErrInvalidCollateralRatio))
|
||||||
|
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
t, found = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(1))
|
t, found = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(1))
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.Equal(c("usdx", 10000000), t.Principal)
|
suite.Equal(c("usdx", 10000000), t.Principal)
|
||||||
|
|
||||||
ctd = suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, t.Collateral, t.Principal.Add(t.AccumulatedFees))
|
ctd = suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, t.Collateral, "xrp-a", t.Principal.Add(t.AccumulatedFees))
|
||||||
suite.Equal(d("40.0"), ctd)
|
suite.Equal(d("40.0"), ctd)
|
||||||
ts = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("40.0"))
|
ts = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("40.0"))
|
||||||
suite.Equal(0, len(ts))
|
suite.Equal(0, len(ts))
|
||||||
ts = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", d("40.0").Add(sdk.SmallestDec()))
|
ts = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", d("40.0").Add(sdk.SmallestDec()))
|
||||||
suite.Equal(ts[0], t)
|
suite.Equal(ts[0], t)
|
||||||
sk = suite.app.GetSupplyKeeper()
|
sk = suite.app.GetSupplyKeeper()
|
||||||
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
suite.Equal(cs(c("xrp", 400000000), c("debt", 10000000)), acc.GetCoins())
|
suite.Equal(cs(c("xrp", 400000000), c("debt", 10000000)), acc.GetCoins())
|
||||||
|
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp", c("xusd", 10000000))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("xusd", 10000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrInvalidPayment))
|
suite.Require().True(errors.Is(err, types.ErrInvalidPayment))
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[1], "xrp", c("xusd", 10000000))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[1], "xrp-a", c("xusd", 10000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
|
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 9000000))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 9000000))
|
||||||
suite.Require().True(errors.Is(err, types.ErrBelowDebtFloor))
|
suite.Require().True(errors.Is(err, types.ErrBelowDebtFloor))
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
_, found = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(1))
|
_, found = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(1))
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
ts = suite.keeper.GetAllCdpsByDenomAndRatio(suite.ctx, "xrp", types.MaxSortableDec)
|
ts = suite.keeper.GetAllCdpsByCollateralTypeAndRatio(suite.ctx, "xrp-a", types.MaxSortableDec)
|
||||||
suite.Equal(0, len(ts))
|
suite.Equal(0, len(ts))
|
||||||
ts = suite.keeper.GetAllCdpsByDenom(suite.ctx, "xrp")
|
ts = suite.keeper.GetAllCdpsByCollateralType(suite.ctx, "xrp-a")
|
||||||
suite.Equal(0, len(ts))
|
suite.Equal(0, len(ts))
|
||||||
sk = suite.app.GetSupplyKeeper()
|
sk = suite.app.GetSupplyKeeper()
|
||||||
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
@ -120,43 +120,43 @@ func (suite *DrawTestSuite) TestAddRepayPrincipal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DrawTestSuite) TestRepayPrincipalOverpay() {
|
func (suite *DrawTestSuite) TestRepayPrincipalOverpay() {
|
||||||
err := suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp", c("usdx", 20000000))
|
err := suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[0], "xrp-a", c("usdx", 20000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
acc := ak.GetAccount(suite.ctx, suite.addrs[0])
|
||||||
suite.Equal(i(10000000000), (acc.GetCoins().AmountOf("usdx")))
|
suite.Equal(i(10000000000), (acc.GetCoins().AmountOf("usdx")))
|
||||||
_, found := suite.keeper.GetCDP(suite.ctx, "xrp", 1)
|
_, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", 1)
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DrawTestSuite) TestAddRepayPrincipalFees() {
|
func (suite *DrawTestSuite) TestAddRepayPrincipalFees() {
|
||||||
err := suite.keeper.AddCdp(suite.ctx, suite.addrs[2], c("xrp", 1000000000000), c("usdx", 100000000000))
|
err := suite.keeper.AddCdp(suite.ctx, suite.addrs[2], c("xrp", 1000000000000), c("usdx", 100000000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Minute * 10))
|
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Minute * 10))
|
||||||
err = suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp")
|
err = suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[2], "xrp", c("usdx", 10000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[2], "xrp-a", c("usdx", 10000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
t, _ := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
t, _ := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.Equal(c("usdx", 92827), t.AccumulatedFees)
|
suite.Equal(c("usdx", 92827), t.AccumulatedFees)
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[2], "xrp", c("usdx", 100))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[2], "xrp-a", c("usdx", 100))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
t, _ = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
t, _ = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.Equal(c("usdx", 92727), t.AccumulatedFees)
|
suite.Equal(c("usdx", 92727), t.AccumulatedFees)
|
||||||
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[2], "xrp", c("usdx", 100010092727))
|
err = suite.keeper.RepayPrincipal(suite.ctx, suite.addrs[2], "xrp-a", c("usdx", 100010092727))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
_, f := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
_, f := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.False(f)
|
suite.False(f)
|
||||||
|
|
||||||
err = suite.keeper.AddCdp(suite.ctx, suite.addrs[2], c("xrp", 1000000000000), c("usdx", 100000000))
|
err = suite.keeper.AddCdp(suite.ctx, suite.addrs[2], c("xrp", 1000000000000), c("usdx", 100000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Second * 31536000)) // move forward one year in time
|
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Second * 31536000)) // move forward one year in time
|
||||||
err = suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp")
|
err = suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[2], "xrp", c("usdx", 100000000))
|
err = suite.keeper.AddPrincipal(suite.ctx, suite.addrs[2], "xrp-a", c("usdx", 100000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
t, _ = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(3))
|
t, _ = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(3))
|
||||||
suite.Equal(c("usdx", 5000000), t.AccumulatedFees)
|
suite.Equal(c("usdx", 5000000), t.AccumulatedFees)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,9 +164,9 @@ func (suite *DrawTestSuite) TestPricefeedFailure() {
|
|||||||
ctx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Hour * 2))
|
ctx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Hour * 2))
|
||||||
pfk := suite.app.GetPriceFeedKeeper()
|
pfk := suite.app.GetPriceFeedKeeper()
|
||||||
pfk.SetCurrentPrices(ctx, "xrp:usd")
|
pfk.SetCurrentPrices(ctx, "xrp:usd")
|
||||||
err := suite.keeper.AddPrincipal(ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
err := suite.keeper.AddPrincipal(ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
err = suite.keeper.RepayPrincipal(ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
err = suite.keeper.RepayPrincipal(ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ func (suite *DrawTestSuite) TestModuleAccountFailure() {
|
|||||||
acc := sk.GetModuleAccount(ctx, types.ModuleName)
|
acc := sk.GetModuleAccount(ctx, types.ModuleName)
|
||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
ak.RemoveAccount(ctx, acc)
|
ak.RemoveAccount(ctx, acc)
|
||||||
suite.keeper.RepayPrincipal(ctx, suite.addrs[0], "xrp", c("usdx", 10000000))
|
suite.keeper.RepayPrincipal(ctx, suite.addrs[0], "xrp-a", c("usdx", 10000000))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
@ -9,11 +11,11 @@ import (
|
|||||||
|
|
||||||
// CalculateFees returns the fees accumulated since fees were last calculated based on
|
// CalculateFees returns the fees accumulated since fees were last calculated based on
|
||||||
// the input amount of outstanding debt (principal) and the number of periods (seconds) that have passed
|
// the input amount of outstanding debt (principal) and the number of periods (seconds) that have passed
|
||||||
func (k Keeper) CalculateFees(ctx sdk.Context, principal sdk.Coin, periods sdk.Int, denom string) sdk.Coin {
|
func (k Keeper) CalculateFees(ctx sdk.Context, principal sdk.Coin, periods sdk.Int, collateralType string) sdk.Coin {
|
||||||
// how fees are calculated:
|
// how fees are calculated:
|
||||||
// feesAccumulated = (outstandingDebt * (feeRate^periods)) - outstandingDebt
|
// feesAccumulated = (outstandingDebt * (feeRate^periods)) - outstandingDebt
|
||||||
// Note that since we can't do x^y using sdk.Decimal, we are converting to int and using RelativePow
|
// Note that since we can't do x^y using sdk.Decimal, we are converting to int and using RelativePow
|
||||||
feePerSecond := k.getFeeRate(ctx, denom)
|
feePerSecond := k.getFeeRate(ctx, collateralType)
|
||||||
scalar := sdk.NewInt(1000000000000000000)
|
scalar := sdk.NewInt(1000000000000000000)
|
||||||
feeRateInt := feePerSecond.Mul(sdk.NewDecFromInt(scalar)).TruncateInt()
|
feeRateInt := feePerSecond.Mul(sdk.NewDecFromInt(scalar)).TruncateInt()
|
||||||
accumulator := sdk.NewDecFromInt(types.RelativePow(feeRateInt, periods, scalar)).Mul(sdk.SmallestDec())
|
accumulator := sdk.NewDecFromInt(types.RelativePow(feeRateInt, periods, scalar)).Mul(sdk.SmallestDec())
|
||||||
@ -23,14 +25,14 @@ func (k Keeper) CalculateFees(ctx sdk.Context, principal sdk.Coin, periods sdk.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFeesForAllCdps updates the fees for each of the CDPs
|
// UpdateFeesForAllCdps updates the fees for each of the CDPs
|
||||||
func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) error {
|
func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralType string) error {
|
||||||
var iterationErr error
|
var iterationErr error
|
||||||
k.IterateCdpsByDenom(ctx, collateralDenom, func(cdp types.CDP) bool {
|
k.IterateCdpsByCollateralType(ctx, collateralType, func(cdp types.CDP) bool {
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
// periods = bblock timestamp - fees updated
|
// periods = bblock timestamp - fees updated
|
||||||
periods := sdk.NewInt(ctx.BlockTime().Unix()).Sub(sdk.NewInt(cdp.FeesUpdated.Unix()))
|
periods := sdk.NewInt(ctx.BlockTime().Unix()).Sub(sdk.NewInt(cdp.FeesUpdated.Unix()))
|
||||||
|
|
||||||
newFees := k.CalculateFees(ctx, cdp.Principal, periods, collateralDenom)
|
newFees := k.CalculateFees(ctx, cdp.Principal, periods, collateralType)
|
||||||
|
|
||||||
// exit without updating fees if amount has rounded down to zero
|
// exit without updating fees if amount has rounded down to zero
|
||||||
// cdp will get updated next block when newFees, newFeesSavings, newFeesSurplus >0
|
// cdp will get updated next block when newFees, newFeesSavings, newFeesSurplus >0
|
||||||
@ -62,9 +64,9 @@ func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) er
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
previousDebt := k.GetTotalPrincipal(ctx, collateralDenom, dp.Denom)
|
previousDebt := k.GetTotalPrincipal(ctx, cdp.Type, dp.Denom)
|
||||||
newDebt := previousDebt.Add(newFees.Amount)
|
newDebt := previousDebt.Add(newFees.Amount)
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, dp.Denom, newDebt)
|
k.SetTotalPrincipal(ctx, cdp.Type, dp.Denom, newDebt)
|
||||||
|
|
||||||
// mint surplus coins divided between the liquidator and savings module accounts.
|
// mint surplus coins divided between the liquidator and savings module accounts.
|
||||||
err = k.supplyKeeper.MintCoins(ctx, types.LiquidatorMacc, sdk.NewCoins(sdk.NewCoin(dp.Denom, newFeesSurplus)))
|
err = k.supplyKeeper.MintCoins(ctx, types.LiquidatorMacc, sdk.NewCoins(sdk.NewCoin(dp.Denom, newFeesSurplus)))
|
||||||
@ -84,8 +86,8 @@ func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) er
|
|||||||
|
|
||||||
// and set the fees updated time to the current block time since we just updated it
|
// and set the fees updated time to the current block time since we just updated it
|
||||||
cdp.FeesUpdated = ctx.BlockTime()
|
cdp.FeesUpdated = ctx.BlockTime()
|
||||||
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
collateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Collateral.Denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
err = k.SetCdpAndCollateralRatioIndex(ctx, cdp, collateralToDebtRatio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
iterationErr = err
|
iterationErr = err
|
||||||
@ -97,27 +99,27 @@ func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IncrementTotalPrincipal increments the total amount of debt that has been drawn with that collateral type
|
// IncrementTotalPrincipal increments the total amount of debt that has been drawn with that collateral type
|
||||||
func (k Keeper) IncrementTotalPrincipal(ctx sdk.Context, collateralDenom string, principal sdk.Coin) {
|
func (k Keeper) IncrementTotalPrincipal(ctx sdk.Context, collateralType string, principal sdk.Coin) {
|
||||||
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
total := k.GetTotalPrincipal(ctx, collateralType, principal.Denom)
|
||||||
total = total.Add(principal.Amount)
|
total = total.Add(principal.Amount)
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
k.SetTotalPrincipal(ctx, collateralType, principal.Denom, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrementTotalPrincipal decrements the total amount of debt that has been drawn for a particular collateral type
|
// DecrementTotalPrincipal decrements the total amount of debt that has been drawn for a particular collateral type
|
||||||
func (k Keeper) DecrementTotalPrincipal(ctx sdk.Context, collateralDenom string, principal sdk.Coin) {
|
func (k Keeper) DecrementTotalPrincipal(ctx sdk.Context, collateralType string, principal sdk.Coin) {
|
||||||
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
total := k.GetTotalPrincipal(ctx, collateralType, principal.Denom)
|
||||||
// NOTE: negative total principal can happen in tests due to rounding errors
|
// NOTE: negative total principal can happen in tests due to rounding errors
|
||||||
// in fee calculation
|
// in fee calculation
|
||||||
total = sdk.MaxInt(total.Sub(principal.Amount), sdk.ZeroInt())
|
total = sdk.MaxInt(total.Sub(principal.Amount), sdk.ZeroInt())
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
k.SetTotalPrincipal(ctx, collateralType, principal.Denom, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTotalPrincipal returns the total amount of principal that has been drawn for a particular collateral
|
// GetTotalPrincipal returns the total amount of principal that has been drawn for a particular collateral
|
||||||
func (k Keeper) GetTotalPrincipal(ctx sdk.Context, collateralDenom string, principalDenom string) (total sdk.Int) {
|
func (k Keeper) GetTotalPrincipal(ctx sdk.Context, collateralType, principalDenom string) (total sdk.Int) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.PrincipalKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.PrincipalKeyPrefix)
|
||||||
bz := store.Get([]byte(collateralDenom + principalDenom))
|
bz := store.Get([]byte(collateralType + principalDenom))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, principalDenom, sdk.ZeroInt())
|
k.SetTotalPrincipal(ctx, collateralType, principalDenom, sdk.ZeroInt())
|
||||||
return sdk.ZeroInt()
|
return sdk.ZeroInt()
|
||||||
}
|
}
|
||||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &total)
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &total)
|
||||||
@ -125,7 +127,11 @@ func (k Keeper) GetTotalPrincipal(ctx sdk.Context, collateralDenom string, princ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetTotalPrincipal sets the total amount of principal that has been drawn for the input collateral
|
// SetTotalPrincipal sets the total amount of principal that has been drawn for the input collateral
|
||||||
func (k Keeper) SetTotalPrincipal(ctx sdk.Context, collateralDenom string, principalDenom string, total sdk.Int) {
|
func (k Keeper) SetTotalPrincipal(ctx sdk.Context, collateralType, principalDenom string, total sdk.Int) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.PrincipalKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.PrincipalKeyPrefix)
|
||||||
store.Set([]byte(collateralDenom+principalDenom), k.cdc.MustMarshalBinaryLengthPrefixed(total))
|
_, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
|
if !found {
|
||||||
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
|
}
|
||||||
|
store.Set([]byte(collateralType+principalDenom), k.cdc.MustMarshalBinaryLengthPrefixed(total))
|
||||||
}
|
}
|
||||||
|
@ -56,12 +56,12 @@ func (suite *FeeTestSuite) createCdps() {
|
|||||||
// use the created account to create a cdp that SHOULD have fees updated
|
// use the created account to create a cdp that SHOULD have fees updated
|
||||||
// to get a ratio between 100 - 110% of liquidation ratio we can use 200xrp ($50) and 24 usdx (208% collateralization with liquidation ratio of 200%)
|
// to get a ratio between 100 - 110% of liquidation ratio we can use 200xrp ($50) and 24 usdx (208% collateralization with liquidation ratio of 200%)
|
||||||
// create CDP for the first address
|
// create CDP for the first address
|
||||||
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("usdx", 24000000))
|
err := suite.keeper.AddCdp(suite.ctx, addrs[0], c("xrp", 200000000), c("usdx", 24000000), "xrp-a")
|
||||||
suite.NoError(err) // check that no error was thrown
|
suite.NoError(err) // check that no error was thrown
|
||||||
|
|
||||||
// use the other account to create a cdp that SHOULD NOT have fees updated - 500% collateralization
|
// use the other account to create a cdp that SHOULD NOT have fees updated - 500% collateralization
|
||||||
// create CDP for the second address
|
// create CDP for the second address
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[1], c("xrp", 200000000), c("usdx", 10000000))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[1], c("xrp", 200000000), c("usdx", 10000000), "xrp-a")
|
||||||
suite.NoError(err) // check that no error was thrown
|
suite.NoError(err) // check that no error was thrown
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -76,11 +76,11 @@ func (suite *FeeTestSuite) TestUpdateFees() {
|
|||||||
// fees to accumulate, in this example 600 seconds
|
// fees to accumulate, in this example 600 seconds
|
||||||
oldtime := suite.ctx.BlockTime()
|
oldtime := suite.ctx.BlockTime()
|
||||||
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Second * 600))
|
suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Second * 600))
|
||||||
err := suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp")
|
err := suite.keeper.UpdateFeesForAllCdps(suite.ctx, "xrp-a")
|
||||||
suite.NoError(err) // check that we don't have any error
|
suite.NoError(err) // check that we don't have any error
|
||||||
|
|
||||||
// cdp we expect fees to accumulate for
|
// cdp we expect fees to accumulate for
|
||||||
cdp1, found := suite.keeper.GetCDP(suite.ctx, "xrp", 1)
|
cdp1, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", 1)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
// check fees are not zero
|
// check fees are not zero
|
||||||
// check that the fees have been updated
|
// check that the fees have been updated
|
||||||
@ -89,7 +89,7 @@ func (suite *FeeTestSuite) TestUpdateFees() {
|
|||||||
suite.Equal(sdk.NewInt(22), cdp1.AccumulatedFees.Amount)
|
suite.Equal(sdk.NewInt(22), cdp1.AccumulatedFees.Amount)
|
||||||
suite.Equal(suite.ctx.BlockTime(), cdp1.FeesUpdated)
|
suite.Equal(suite.ctx.BlockTime(), cdp1.FeesUpdated)
|
||||||
// cdp we expect fees to not accumulate for because of rounding to zero
|
// cdp we expect fees to not accumulate for because of rounding to zero
|
||||||
cdp2, found := suite.keeper.GetCDP(suite.ctx, "xrp", 2)
|
cdp2, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", 2)
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
// check fees are zero
|
// check fees are zero
|
||||||
suite.True(cdp2.AccumulatedFees.IsZero())
|
suite.True(cdp2.AccumulatedFees.IsZero())
|
||||||
|
@ -49,6 +49,7 @@ func NewCDPGenState(asset string, liquidationRatio sdk.Dec) app.GenesisState {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: asset,
|
Denom: asset,
|
||||||
|
Type: asset + "-a",
|
||||||
LiquidationRatio: liquidationRatio,
|
LiquidationRatio: liquidationRatio,
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -121,6 +122,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -133,6 +135,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
|
Type: "btc-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
||||||
@ -145,6 +148,7 @@ func NewCDPGenStateMulti() app.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 500000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -185,6 +189,7 @@ func NewCDPGenStateHighDebtLimit() app.GenesisState {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -197,6 +202,7 @@ func NewCDPGenStateHighDebtLimit() app.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
|
Type: "btc-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"), // %2.5 apr
|
||||||
@ -227,10 +233,10 @@ func NewCDPGenStateHighDebtLimit() app.GenesisState {
|
|||||||
|
|
||||||
func cdps() (cdps cdp.CDPs) {
|
func cdps() (cdps cdp.CDPs) {
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(3)
|
_, addrs := app.GeneratePrivKeyAddressPairs(3)
|
||||||
c1 := cdp.NewCDP(uint64(1), addrs[0], sdk.NewCoin("xrp", sdk.NewInt(10000000)), sdk.NewCoin("usdx", sdk.NewInt(8000000)), tmtime.Canonical(time.Now()))
|
c1 := cdp.NewCDP(uint64(1), addrs[0], sdk.NewCoin("xrp", sdk.NewInt(10000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(8000000)), tmtime.Canonical(time.Now()))
|
||||||
c2 := cdp.NewCDP(uint64(2), addrs[1], sdk.NewCoin("xrp", sdk.NewInt(100000000)), sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
c2 := cdp.NewCDP(uint64(2), addrs[1], sdk.NewCoin("xrp", sdk.NewInt(100000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
||||||
c3 := cdp.NewCDP(uint64(3), addrs[1], sdk.NewCoin("btc", sdk.NewInt(1000000000)), sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
c3 := cdp.NewCDP(uint64(3), addrs[1], sdk.NewCoin("btc", sdk.NewInt(1000000000)), "btc-a", sdk.NewCoin("usdx", sdk.NewInt(10000000)), tmtime.Canonical(time.Now()))
|
||||||
c4 := cdp.NewCDP(uint64(4), addrs[2], sdk.NewCoin("xrp", sdk.NewInt(1000000000)), sdk.NewCoin("usdx", sdk.NewInt(500000000)), tmtime.Canonical(time.Now()))
|
c4 := cdp.NewCDP(uint64(4), addrs[2], sdk.NewCoin("xrp", sdk.NewInt(1000000000)), "xrp-a", sdk.NewCoin("usdx", sdk.NewInt(500000000)), tmtime.Canonical(time.Now()))
|
||||||
cdps = append(cdps, c1, c2, c3, c4)
|
cdps = append(cdps, c1, c2, c3, c4)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -43,22 +43,22 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramstore subspace.Subspace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CdpDenomIndexIterator returns an sdk.Iterator for all cdps with matching collateral denom
|
// CdpDenomIndexIterator returns an sdk.Iterator for all cdps with matching collateral denom
|
||||||
func (k Keeper) CdpDenomIndexIterator(ctx sdk.Context, denom string) sdk.Iterator {
|
func (k Keeper) CdpDenomIndexIterator(ctx sdk.Context, collateralType string) sdk.Iterator {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, denom)
|
db, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("denom %s prefix not found", denom))
|
panic(fmt.Sprintf("denom %s prefix not found", collateralType))
|
||||||
}
|
}
|
||||||
return sdk.KVStorePrefixIterator(store, types.DenomIterKey(db))
|
return sdk.KVStorePrefixIterator(store, types.DenomIterKey(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CdpCollateralRatioIndexIterator returns an sdk.Iterator for all cdps that have collateral denom
|
// CdpCollateralRatioIndexIterator returns an sdk.Iterator for all cdps that have collateral denom
|
||||||
// matching denom and collateral:debt ratio LESS THAN targetRatio
|
// matching denom and collateral:debt ratio LESS THAN targetRatio
|
||||||
func (k Keeper) CdpCollateralRatioIndexIterator(ctx sdk.Context, denom string, targetRatio sdk.Dec) sdk.Iterator {
|
func (k Keeper) CdpCollateralRatioIndexIterator(ctx sdk.Context, collateralType string, targetRatio sdk.Dec) sdk.Iterator {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
||||||
db, found := k.GetDenomPrefix(ctx, denom)
|
db, found := k.GetCollateralTypePrefix(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("denom %s prefix not found", denom))
|
panic(fmt.Sprintf("denom %s prefix not found", collateralType))
|
||||||
}
|
}
|
||||||
return store.Iterator(types.CollateralRatioIterKey(db, sdk.ZeroDec()), types.CollateralRatioIterKey(db, targetRatio))
|
return store.Iterator(types.CollateralRatioIterKey(db, sdk.ZeroDec()), types.CollateralRatioIterKey(db, targetRatio))
|
||||||
}
|
}
|
||||||
@ -78,9 +78,9 @@ func (k Keeper) IterateAllCdps(ctx sdk.Context, cb func(cdp types.CDP) (stop boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateCdpsByDenom iterates over cdps with matching denom and performs a callback function
|
// IterateCdpsByCollateralType iterates over cdps with matching denom and performs a callback function
|
||||||
func (k Keeper) IterateCdpsByDenom(ctx sdk.Context, denom string, cb func(cdp types.CDP) (stop bool)) {
|
func (k Keeper) IterateCdpsByCollateralType(ctx sdk.Context, collateralType string, cb func(cdp types.CDP) (stop bool)) {
|
||||||
iterator := k.CdpDenomIndexIterator(ctx, denom)
|
iterator := k.CdpDenomIndexIterator(ctx, collateralType)
|
||||||
|
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
@ -94,14 +94,13 @@ func (k Keeper) IterateCdpsByDenom(ctx sdk.Context, denom string, cb func(cdp ty
|
|||||||
|
|
||||||
// IterateCdpsByCollateralRatio iterate over cdps with collateral denom equal to denom and
|
// IterateCdpsByCollateralRatio iterate over cdps with collateral denom equal to denom and
|
||||||
// collateral:debt ratio LESS THAN targetRatio and performs a callback function.
|
// collateral:debt ratio LESS THAN targetRatio and performs a callback function.
|
||||||
func (k Keeper) IterateCdpsByCollateralRatio(ctx sdk.Context, denom string, targetRatio sdk.Dec, cb func(cdp types.CDP) (stop bool)) {
|
func (k Keeper) IterateCdpsByCollateralRatio(ctx sdk.Context, collateralType string, targetRatio sdk.Dec, cb func(cdp types.CDP) (stop bool)) {
|
||||||
iterator := k.CdpCollateralRatioIndexIterator(ctx, denom, targetRatio)
|
iterator := k.CdpCollateralRatioIndexIterator(ctx, collateralType, targetRatio)
|
||||||
|
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
db, id, _ := types.SplitCollateralRatioKey(iterator.Key())
|
_, id, _ := types.SplitCollateralRatioKey(iterator.Key())
|
||||||
d := k.getDenomFromByte(ctx, db)
|
cdp, found := k.GetCDP(ctx, collateralType, id)
|
||||||
cdp, found := k.GetCDP(ctx, d, id)
|
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("cdp %d does not exist", id))
|
panic(fmt.Sprintf("cdp %d does not exist", id))
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ func createCdps(n int) (app.TestApp, sdk.Context, keeper.Keeper) {
|
|||||||
)
|
)
|
||||||
cdpKeeper := tApp.GetCDPKeeper()
|
cdpKeeper := tApp.GetCDPKeeper()
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
err := cdpKeeper.AddCdp(ctx, addrs[i], coins[i][0], c("usdx", 100000000))
|
err := cdpKeeper.AddCdp(ctx, addrs[i], coins[i][0], c("usdx", 100000000), "btc-a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to create cdp")
|
panic("failed to create cdp")
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ func BenchmarkCdpCreation(b *testing.B) {
|
|||||||
cdpKeeper := tApp.GetCDPKeeper()
|
cdpKeeper := tApp.GetCDPKeeper()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
err := cdpKeeper.AddCdp(ctx, addrs[i], coins[i][0], c("usdx", 100000000))
|
err := cdpKeeper.AddCdp(ctx, addrs[i], coins[i][0], c("usdx", 100000000), "btc-a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error("unexpected error")
|
b.Error("unexpected error")
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCollateral returns the collateral param with corresponding denom
|
// GetCollateral returns the collateral param with corresponding denom
|
||||||
func (k Keeper) GetCollateral(ctx sdk.Context, denom string) (types.CollateralParam, bool) {
|
func (k Keeper) GetCollateral(ctx sdk.Context, collateralType string) (types.CollateralParam, bool) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
for _, cp := range params.CollateralParams {
|
for _, cp := range params.CollateralParams {
|
||||||
if cp.Denom == denom {
|
if cp.Type == collateralType {
|
||||||
return cp, true
|
return cp, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,11 +40,11 @@ func (k Keeper) GetDebtParam(ctx sdk.Context, denom string) (types.DebtParam, bo
|
|||||||
return types.DebtParam{}, false
|
return types.DebtParam{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDenomPrefix returns the prefix of the matching denom
|
// GetCollateralTypePrefix returns the prefix of the matching denom
|
||||||
func (k Keeper) GetDenomPrefix(ctx sdk.Context, denom string) (byte, bool) {
|
func (k Keeper) GetCollateralTypePrefix(ctx sdk.Context, collateralType string) (byte, bool) {
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
for _, cp := range params.CollateralParams {
|
for _, cp := range params.CollateralParams {
|
||||||
if cp.Denom == denom {
|
if cp.Type == collateralType {
|
||||||
return cp.Prefix, true
|
return cp.Prefix, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,51 +62,51 @@ func (k Keeper) getDenomFromByte(ctx sdk.Context, db byte) string {
|
|||||||
panic(fmt.Sprintf("no collateral denom with prefix %b", db))
|
panic(fmt.Sprintf("no collateral denom with prefix %b", db))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getSpotMarketID(ctx sdk.Context, denom string) string {
|
func (k Keeper) getSpotMarketID(ctx sdk.Context, collateralType string) string {
|
||||||
cp, found := k.GetCollateral(ctx, denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("collateral not found: %s", denom))
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
}
|
}
|
||||||
return cp.SpotMarketID
|
return cp.SpotMarketID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getliquidationMarketID(ctx sdk.Context, denom string) string {
|
func (k Keeper) getliquidationMarketID(ctx sdk.Context, collateralType string) string {
|
||||||
cp, found := k.GetCollateral(ctx, denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("collateral not found: %s", denom))
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
}
|
}
|
||||||
return cp.LiquidationMarketID
|
return cp.LiquidationMarketID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getLiquidationRatio(ctx sdk.Context, denom string) sdk.Dec {
|
func (k Keeper) getLiquidationRatio(ctx sdk.Context, collateralType string) sdk.Dec {
|
||||||
cp, found := k.GetCollateral(ctx, denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("collateral not found: %s", denom))
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
}
|
}
|
||||||
return cp.LiquidationRatio
|
return cp.LiquidationRatio
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getLiquidationPenalty(ctx sdk.Context, denom string) sdk.Dec {
|
func (k Keeper) getLiquidationPenalty(ctx sdk.Context, collateralType string) sdk.Dec {
|
||||||
cp, found := k.GetCollateral(ctx, denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("collateral not found: %s", denom))
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
}
|
}
|
||||||
return cp.LiquidationPenalty
|
return cp.LiquidationPenalty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getAuctionSize(ctx sdk.Context, denom string) sdk.Int {
|
func (k Keeper) getAuctionSize(ctx sdk.Context, collateralType string) sdk.Int {
|
||||||
cp, found := k.GetCollateral(ctx, denom)
|
cp, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("collateral not found: %s", denom))
|
panic(fmt.Sprintf("collateral not found: %s", collateralType))
|
||||||
}
|
}
|
||||||
return cp.AuctionSize
|
return cp.AuctionSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFeeRate returns the per second fee rate for the input denom
|
// GetFeeRate returns the per second fee rate for the input denom
|
||||||
func (k Keeper) getFeeRate(ctx sdk.Context, denom string) (fee sdk.Dec) {
|
func (k Keeper) getFeeRate(ctx sdk.Context, collateralType string) (fee sdk.Dec) {
|
||||||
collalateralParam, found := k.GetCollateral(ctx, denom)
|
collalateralParam, found := k.GetCollateral(ctx, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("could not get fee rate for %s, collateral not found", denom))
|
panic(fmt.Sprintf("could not get fee rate for %s, collateral not found", collateralType))
|
||||||
}
|
}
|
||||||
return collalateralParam.StabilityFee
|
return collalateralParam.StabilityFee
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ func NewQuerier(keeper Keeper) sdk.Querier {
|
|||||||
case types.QueryGetCdp:
|
case types.QueryGetCdp:
|
||||||
return queryGetCdp(ctx, req, keeper)
|
return queryGetCdp(ctx, req, keeper)
|
||||||
case types.QueryGetCdps:
|
case types.QueryGetCdps:
|
||||||
return queryGetCdpsByDenom(ctx, req, keeper)
|
return queryGetCdpsByCollateralType(ctx, req, keeper)
|
||||||
case types.QueryGetCdpsByCollateralization:
|
case types.QueryGetCdpsByCollateralization:
|
||||||
return queryGetCdpsByRatio(ctx, req, keeper)
|
return queryGetCdpsByRatio(ctx, req, keeper)
|
||||||
case types.QueryGetParams:
|
case types.QueryGetParams:
|
||||||
@ -41,14 +41,14 @@ func queryGetCdp(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte,
|
|||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
_, valid := keeper.GetDenomPrefix(ctx, requestParams.CollateralDenom)
|
_, valid := keeper.GetCollateralTypePrefix(ctx, requestParams.CollateralType)
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
cdp, found := keeper.GetCdpByOwnerAndDenom(ctx, requestParams.Owner, requestParams.CollateralDenom)
|
cdp, found := keeper.GetCdpByOwnerAndCollateralType(ctx, requestParams.Owner, requestParams.CollateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", requestParams.Owner, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", requestParams.Owner, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
augmentedCDP := keeper.LoadAugmentedCDP(ctx, cdp)
|
augmentedCDP := keeper.LoadAugmentedCDP(ctx, cdp)
|
||||||
@ -69,14 +69,14 @@ func queryGetDeposits(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]
|
|||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
_, valid := keeper.GetDenomPrefix(ctx, requestParams.CollateralDenom)
|
_, valid := keeper.GetCollateralTypePrefix(ctx, requestParams.CollateralType)
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
cdp, found := keeper.GetCdpByOwnerAndDenom(ctx, requestParams.Owner, requestParams.CollateralDenom)
|
cdp, found := keeper.GetCdpByOwnerAndCollateralType(ctx, requestParams.Owner, requestParams.CollateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", requestParams.Owner, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrapf(types.ErrCdpNotFound, "owner %s, denom %s", requestParams.Owner, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
deposits := keeper.GetDeposits(ctx, cdp.ID)
|
deposits := keeper.GetDeposits(ctx, cdp.ID)
|
||||||
@ -96,17 +96,17 @@ func queryGetCdpsByRatio(ctx sdk.Context, req abci.RequestQuery, keeper Keeper)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
_, valid := keeper.GetDenomPrefix(ctx, requestParams.CollateralDenom)
|
_, valid := keeper.GetCollateralTypePrefix(ctx, requestParams.CollateralType)
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
ratio, err := keeper.CalculateCollateralizationRatioFromAbsoluteRatio(ctx, requestParams.CollateralDenom, requestParams.Ratio, "liquidation")
|
ratio, err := keeper.CalculateCollateralizationRatioFromAbsoluteRatio(ctx, requestParams.CollateralType, requestParams.Ratio, "liquidation")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrap(err, "couldn't get collateralization ratio from absolute ratio")
|
return nil, sdkerrors.Wrap(err, "couldn't get collateralization ratio from absolute ratio")
|
||||||
}
|
}
|
||||||
|
|
||||||
cdps := keeper.GetAllCdpsByDenomAndRatio(ctx, requestParams.CollateralDenom, ratio)
|
cdps := keeper.GetAllCdpsByCollateralTypeAndRatio(ctx, requestParams.CollateralType, ratio)
|
||||||
// augment CDPs by adding collateral value and collateralization ratio
|
// augment CDPs by adding collateral value and collateralization ratio
|
||||||
var augmentedCDPs types.AugmentedCDPs
|
var augmentedCDPs types.AugmentedCDPs
|
||||||
for _, cdp := range cdps {
|
for _, cdp := range cdps {
|
||||||
@ -121,18 +121,18 @@ func queryGetCdpsByRatio(ctx sdk.Context, req abci.RequestQuery, keeper Keeper)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// query all cdps with matching collateral denom
|
// query all cdps with matching collateral denom
|
||||||
func queryGetCdpsByDenom(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
|
func queryGetCdpsByCollateralType(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
|
||||||
var requestParams types.QueryCdpsParams
|
var requestParams types.QueryCdpsParams
|
||||||
err := types.ModuleCdc.UnmarshalJSON(req.Data, &requestParams)
|
err := types.ModuleCdc.UnmarshalJSON(req.Data, &requestParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
_, valid := keeper.GetDenomPrefix(ctx, requestParams.CollateralDenom)
|
_, valid := keeper.GetCollateralTypePrefix(ctx, requestParams.CollateralType)
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralDenom)
|
return nil, sdkerrors.Wrap(types.ErrCollateralNotSupported, requestParams.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
cdps := keeper.GetAllCdpsByDenom(ctx, requestParams.CollateralDenom)
|
cdps := keeper.GetAllCdpsByCollateralType(ctx, requestParams.CollateralType)
|
||||||
// augment CDPs by adding collateral value and collateralization ratio
|
// augment CDPs by adding collateral value and collateralization ratio
|
||||||
var augmentedCDPs types.AugmentedCDPs
|
var augmentedCDPs types.AugmentedCDPs
|
||||||
for _, cdp := range cdps {
|
for _, cdp := range cdps {
|
||||||
|
@ -97,9 +97,9 @@ func (suite *QuerierTestSuite) SetupTest() {
|
|||||||
amount = simulation.RandIntBetween(rand.New(rand.NewSource(int64(j))), 500000000, 5000000000)
|
amount = simulation.RandIntBetween(rand.New(rand.NewSource(int64(j))), 500000000, 5000000000)
|
||||||
debt = simulation.RandIntBetween(rand.New(rand.NewSource(int64(j))), 1000000000, 25000000000)
|
debt = simulation.RandIntBetween(rand.New(rand.NewSource(int64(j))), 1000000000, 25000000000)
|
||||||
}
|
}
|
||||||
err = suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt)))
|
err = suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt)), collateral+"-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
c, f := suite.keeper.GetCDP(suite.ctx, collateral, uint64(j+1))
|
c, f := suite.keeper.GetCDP(suite.ctx, collateral+"-a", uint64(j+1))
|
||||||
suite.True(f)
|
suite.True(f)
|
||||||
cdps[j] = c
|
cdps[j] = c
|
||||||
aCDP := suite.keeper.LoadAugmentedCDP(suite.ctx, c)
|
aCDP := suite.keeper.LoadAugmentedCDP(suite.ctx, c)
|
||||||
@ -116,7 +116,7 @@ func (suite *QuerierTestSuite) TestQueryCdp() {
|
|||||||
ctx := suite.ctx.WithIsCheckTx(false)
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, suite.cdps[0].Collateral.Denom)),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, suite.cdps[0].Collateral.Denom+"-a")),
|
||||||
}
|
}
|
||||||
bz, err := suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
bz, err := suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
@ -128,7 +128,7 @@ func (suite *QuerierTestSuite) TestQueryCdp() {
|
|||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, "lol")),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, "lol-a")),
|
||||||
}
|
}
|
||||||
_, err = suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
_, err = suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
@ -146,18 +146,18 @@ func (suite *QuerierTestSuite) TestQueryCdp() {
|
|||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, "xrp")),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpParams(suite.cdps[0].Owner, "xrp-a")),
|
||||||
}
|
}
|
||||||
_, err = suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
_, err = suite.querier(ctx, []string{types.QueryGetCdp}, query)
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QuerierTestSuite) TestQueryCdpsByDenom() {
|
func (suite *QuerierTestSuite) TestQueryCdpsByCollateralType() {
|
||||||
ctx := suite.ctx.WithIsCheckTx(false)
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdps}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdps}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsParams(suite.cdps[0].Collateral.Denom)),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsParams(suite.cdps[0].Collateral.Denom + "-a")),
|
||||||
}
|
}
|
||||||
bz, err := suite.querier(ctx, []string{types.QueryGetCdps}, query)
|
bz, err := suite.querier(ctx, []string{types.QueryGetCdps}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
@ -169,7 +169,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByDenom() {
|
|||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdps}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdps}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsParams("lol")),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsParams("lol-a")),
|
||||||
}
|
}
|
||||||
_, err = suite.querier(ctx, []string{types.QueryGetCdps}, query)
|
_, err = suite.querier(ctx, []string{types.QueryGetCdps}, query)
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
@ -183,8 +183,8 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
expectedXrpIds := []int{}
|
expectedXrpIds := []int{}
|
||||||
expectedBtcIds := []int{}
|
expectedBtcIds := []int{}
|
||||||
for _, cdp := range suite.cdps {
|
for _, cdp := range suite.cdps {
|
||||||
absoluteRatio := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
absoluteRatio := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Type, cdp.Principal)
|
||||||
collateralizationRatio, err := suite.keeper.CalculateCollateralizationRatioFromAbsoluteRatio(suite.ctx, cdp.Collateral.Denom, absoluteRatio, "liquidation")
|
collateralizationRatio, err := suite.keeper.CalculateCollateralizationRatioFromAbsoluteRatio(suite.ctx, cdp.Type, absoluteRatio, "liquidation")
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
if cdp.Collateral.Denom == "xrp" {
|
if cdp.Collateral.Denom == "xrp" {
|
||||||
if collateralizationRatio.LT(xrpRatio) {
|
if collateralizationRatio.LT(xrpRatio) {
|
||||||
@ -202,7 +202,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
ctx := suite.ctx.WithIsCheckTx(false)
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("xrp", xrpRatio)),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("xrp-a", xrpRatio)),
|
||||||
}
|
}
|
||||||
bz, err := suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
bz, err := suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
@ -219,7 +219,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("btc", btcRatio)),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("btc-a", btcRatio)),
|
||||||
}
|
}
|
||||||
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
@ -236,7 +236,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpsByCollateralization}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("xrp", d("0.003"))),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpsByRatioParams("xrp-a", d("0.003"))),
|
||||||
}
|
}
|
||||||
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
@ -265,7 +265,7 @@ func (suite *QuerierTestSuite) TestQueryDeposits() {
|
|||||||
ctx := suite.ctx.WithIsCheckTx(false)
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
query := abci.RequestQuery{
|
query := abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpDeposits}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdpDeposits}, "/"),
|
||||||
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpDeposits(suite.cdps[0].Owner, suite.cdps[0].Collateral.Denom)),
|
Data: types.ModuleCdc.MustMarshalJSON(types.NewQueryCdpDeposits(suite.cdps[0].Owner, suite.cdps[0].Collateral.Denom+"-a")),
|
||||||
}
|
}
|
||||||
|
|
||||||
bz, err := suite.querier(ctx, []string{types.QueryGetCdpDeposits}, query)
|
bz, err := suite.querier(ctx, []string{types.QueryGetCdpDeposits}, query)
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
// (this is the equivalent of saying that fees are no longer accumulated by a cdp once it gets liquidated)
|
// (this is the equivalent of saying that fees are no longer accumulated by a cdp once it gets liquidated)
|
||||||
func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
||||||
// Calculate the previous collateral ratio
|
// Calculate the previous collateral ratio
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.GetTotalPrincipal())
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Type, cdp.GetTotalPrincipal())
|
||||||
|
|
||||||
// Move debt coins from cdp to liquidator account
|
// Move debt coins from cdp to liquidator account
|
||||||
deposits := k.GetDeposits(ctx, cdp.ID)
|
deposits := k.GetDeposits(ctx, cdp.ID)
|
||||||
@ -48,23 +48,23 @@ func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.AuctionCollateral(ctx, deposits, debt, cdp.Principal.Denom)
|
err = k.AuctionCollateral(ctx, deposits, cdp.Type, debt, cdp.Principal.Denom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement total principal for this collateral type
|
// Decrement total principal for this collateral type
|
||||||
coinsToDecrement := cdp.GetTotalPrincipal()
|
coinsToDecrement := cdp.GetTotalPrincipal()
|
||||||
k.DecrementTotalPrincipal(ctx, cdp.Collateral.Denom, coinsToDecrement)
|
k.DecrementTotalPrincipal(ctx, cdp.Type, coinsToDecrement)
|
||||||
|
|
||||||
// Delete CDP from state
|
// Delete CDP from state
|
||||||
k.RemoveCdpOwnerIndex(ctx, cdp)
|
k.RemoveCdpOwnerIndex(ctx, cdp)
|
||||||
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Collateral.Denom, cdp.ID, oldCollateralToDebtRatio)
|
k.RemoveCdpCollateralRatioIndex(ctx, cdp.Type, cdp.ID, oldCollateralToDebtRatio)
|
||||||
return k.DeleteCDP(ctx, cdp)
|
return k.DeleteCDP(ctx, cdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LiquidateCdps seizes collateral from all CDPs below the input liquidation ratio
|
// LiquidateCdps seizes collateral from all CDPs below the input liquidation ratio
|
||||||
func (k Keeper) LiquidateCdps(ctx sdk.Context, marketID string, denom string, liquidationRatio sdk.Dec) error {
|
func (k Keeper) LiquidateCdps(ctx sdk.Context, marketID string, collateralType string, liquidationRatio sdk.Dec) error {
|
||||||
price, err := k.pricefeedKeeper.GetCurrentPrice(ctx, marketID)
|
price, err := k.pricefeedKeeper.GetCurrentPrice(ctx, marketID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -77,7 +77,7 @@ func (k Keeper) LiquidateCdps(ctx sdk.Context, marketID string, denom string, li
|
|||||||
// liquidation ratio = 1.5
|
// liquidation ratio = 1.5
|
||||||
// normalizedRatio = (1/(0.5/1.5)) = 3
|
// normalizedRatio = (1/(0.5/1.5)) = 3
|
||||||
normalizedRatio := sdk.OneDec().Quo(priceDivLiqRatio)
|
normalizedRatio := sdk.OneDec().Quo(priceDivLiqRatio)
|
||||||
cdpsToLiquidate := k.GetAllCdpsByDenomAndRatio(ctx, denom, normalizedRatio)
|
cdpsToLiquidate := k.GetAllCdpsByCollateralTypeAndRatio(ctx, collateralType, normalizedRatio)
|
||||||
for _, c := range cdpsToLiquidate {
|
for _, c := range cdpsToLiquidate {
|
||||||
err := k.SeizeCollateral(ctx, c)
|
err := k.SeizeCollateral(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -88,8 +88,8 @@ func (k Keeper) LiquidateCdps(ctx sdk.Context, marketID string, denom string, li
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ApplyLiquidationPenalty multiplies the input debt amount by the liquidation penalty
|
// ApplyLiquidationPenalty multiplies the input debt amount by the liquidation penalty
|
||||||
func (k Keeper) ApplyLiquidationPenalty(ctx sdk.Context, denom string, debt sdk.Int) sdk.Int {
|
func (k Keeper) ApplyLiquidationPenalty(ctx sdk.Context, collateralType string, debt sdk.Int) sdk.Int {
|
||||||
penalty := k.getLiquidationPenalty(ctx, denom)
|
penalty := k.getLiquidationPenalty(ctx, collateralType)
|
||||||
return sdk.NewDecFromInt(debt).Mul(penalty).RoundInt()
|
return sdk.NewDecFromInt(debt).Mul(penalty).RoundInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ func (suite *SeizeTestSuite) createCdps() {
|
|||||||
tracker.debt += int64(debt)
|
tracker.debt += int64(debt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt)))
|
err := suite.keeper.AddCdp(suite.ctx, addrs[j], c(collateral, int64(amount)), c("usdx", int64(debt)), collateral+"-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
c, f := suite.keeper.GetCDP(suite.ctx, collateral, uint64(j+1))
|
c, f := suite.keeper.GetCDP(suite.ctx, collateral+"-a", uint64(j+1))
|
||||||
suite.True(f)
|
suite.True(f)
|
||||||
cdps[j] = c
|
cdps[j] = c
|
||||||
}
|
}
|
||||||
@ -131,14 +131,14 @@ func (suite *SeizeTestSuite) setPrice(price sdk.Dec, market string) {
|
|||||||
func (suite *SeizeTestSuite) TestSeizeCollateral() {
|
func (suite *SeizeTestSuite) TestSeizeCollateral() {
|
||||||
suite.createCdps()
|
suite.createCdps()
|
||||||
sk := suite.app.GetSupplyKeeper()
|
sk := suite.app.GetSupplyKeeper()
|
||||||
cdp, found := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
cdp, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
p := cdp.Principal.Amount
|
p := cdp.Principal.Amount
|
||||||
cl := cdp.Collateral.Amount
|
cl := cdp.Collateral.Amount
|
||||||
tpb := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tpb := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
err := suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
err := suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
suite.Equal(tpb.Sub(tpa), p)
|
suite.Equal(tpb.Sub(tpa), p)
|
||||||
auctionKeeper := suite.app.GetAuctionKeeper()
|
auctionKeeper := suite.app.GetAuctionKeeper()
|
||||||
_, found = auctionKeeper.GetAuction(suite.ctx, auction.DefaultNextAuctionID)
|
_, found = auctionKeeper.GetAuction(suite.ctx, auction.DefaultNextAuctionID)
|
||||||
@ -148,34 +148,34 @@ func (suite *SeizeTestSuite) TestSeizeCollateral() {
|
|||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
acc := ak.GetAccount(suite.ctx, suite.addrs[1])
|
acc := ak.GetAccount(suite.ctx, suite.addrs[1])
|
||||||
suite.Equal(p.Int64(), acc.GetCoins().AmountOf("usdx").Int64())
|
suite.Equal(p.Int64(), acc.GetCoins().AmountOf("usdx").Int64())
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[1], c("xrp", 10))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[1], c("xrp", 10), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SeizeTestSuite) TestSeizeCollateralMultiDeposit() {
|
func (suite *SeizeTestSuite) TestSeizeCollateralMultiDeposit() {
|
||||||
suite.createCdps()
|
suite.createCdps()
|
||||||
sk := suite.app.GetSupplyKeeper()
|
sk := suite.app.GetSupplyKeeper()
|
||||||
cdp, found := suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
cdp, found := suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
err := suite.keeper.DepositCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 6999000000))
|
err := suite.keeper.DepositCollateral(suite.ctx, suite.addrs[1], suite.addrs[0], c("xrp", 6999000000), "xrp-a")
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
cdp, found = suite.keeper.GetCDP(suite.ctx, "xrp", uint64(2))
|
cdp, found = suite.keeper.GetCDP(suite.ctx, "xrp-a", uint64(2))
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
deposits := suite.keeper.GetDeposits(suite.ctx, cdp.ID)
|
deposits := suite.keeper.GetDeposits(suite.ctx, cdp.ID)
|
||||||
suite.Equal(2, len(deposits))
|
suite.Equal(2, len(deposits))
|
||||||
p := cdp.Principal.Amount
|
p := cdp.Principal.Amount
|
||||||
cl := cdp.Collateral.Amount
|
cl := cdp.Collateral.Amount
|
||||||
tpb := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tpb := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
err = suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
err = suite.keeper.SeizeCollateral(suite.ctx, cdp)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp", "usdx")
|
tpa := suite.keeper.GetTotalPrincipal(suite.ctx, "xrp-a", "usdx")
|
||||||
suite.Equal(tpb.Sub(tpa), p)
|
suite.Equal(tpb.Sub(tpa), p)
|
||||||
auctionMacc := sk.GetModuleAccount(suite.ctx, auction.ModuleName)
|
auctionMacc := sk.GetModuleAccount(suite.ctx, auction.ModuleName)
|
||||||
suite.Equal(cs(c("debt", p.Int64()), c("xrp", cl.Int64())), auctionMacc.GetCoins())
|
suite.Equal(cs(c("debt", p.Int64()), c("xrp", cl.Int64())), auctionMacc.GetCoins())
|
||||||
ak := suite.app.GetAccountKeeper()
|
ak := suite.app.GetAccountKeeper()
|
||||||
acc := ak.GetAccount(suite.ctx, suite.addrs[1])
|
acc := ak.GetAccount(suite.ctx, suite.addrs[1])
|
||||||
suite.Equal(p.Int64(), acc.GetCoins().AmountOf("usdx").Int64())
|
suite.Equal(p.Int64(), acc.GetCoins().AmountOf("usdx").Int64())
|
||||||
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[1], c("xrp", 10))
|
err = suite.keeper.WithdrawCollateral(suite.ctx, suite.addrs[1], suite.addrs[1], c("xrp", 10), "xrp-a")
|
||||||
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
suite.Require().True(errors.Is(err, types.ErrCdpNotFound))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +185,9 @@ func (suite *SeizeTestSuite) TestLiquidateCdps() {
|
|||||||
acc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
acc := sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
originalXrpCollateral := acc.GetCoins().AmountOf("xrp")
|
originalXrpCollateral := acc.GetCoins().AmountOf("xrp")
|
||||||
suite.setPrice(d("0.2"), "xrp:usd")
|
suite.setPrice(d("0.2"), "xrp:usd")
|
||||||
p, found := suite.keeper.GetCollateral(suite.ctx, "xrp")
|
p, found := suite.keeper.GetCollateral(suite.ctx, "xrp-a")
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
suite.keeper.LiquidateCdps(suite.ctx, "xrp:usd", "xrp", p.LiquidationRatio)
|
suite.keeper.LiquidateCdps(suite.ctx, "xrp:usd", "xrp-a", p.LiquidationRatio)
|
||||||
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
acc = sk.GetModuleAccount(suite.ctx, types.ModuleName)
|
||||||
finalXrpCollateral := acc.GetCoins().AmountOf("xrp")
|
finalXrpCollateral := acc.GetCoins().AmountOf("xrp")
|
||||||
seizedXrpCollateral := originalXrpCollateral.Sub(finalXrpCollateral)
|
seizedXrpCollateral := originalXrpCollateral.Sub(finalXrpCollateral)
|
||||||
@ -196,13 +196,13 @@ func (suite *SeizeTestSuite) TestLiquidateCdps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SeizeTestSuite) TestApplyLiquidationPenalty() {
|
func (suite *SeizeTestSuite) TestApplyLiquidationPenalty() {
|
||||||
penalty := suite.keeper.ApplyLiquidationPenalty(suite.ctx, "xrp", i(1000))
|
penalty := suite.keeper.ApplyLiquidationPenalty(suite.ctx, "xrp-a", i(1000))
|
||||||
suite.Equal(i(50), penalty)
|
suite.Equal(i(50), penalty)
|
||||||
penalty = suite.keeper.ApplyLiquidationPenalty(suite.ctx, "btc", i(1000))
|
penalty = suite.keeper.ApplyLiquidationPenalty(suite.ctx, "btc-a", i(1000))
|
||||||
suite.Equal(i(25), penalty)
|
suite.Equal(i(25), penalty)
|
||||||
penalty = suite.keeper.ApplyLiquidationPenalty(suite.ctx, "xrp", i(675760172))
|
penalty = suite.keeper.ApplyLiquidationPenalty(suite.ctx, "xrp-a", i(675760172))
|
||||||
suite.Equal(i(33788009), penalty)
|
suite.Equal(i(33788009), penalty)
|
||||||
suite.Panics(func() { suite.keeper.ApplyLiquidationPenalty(suite.ctx, "lol", i(1000)) })
|
suite.Panics(func() { suite.keeper.ApplyLiquidationPenalty(suite.ctx, "lol-a", i(1000)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSeizeTestSuite(t *testing.T) {
|
func TestSeizeTestSuite(t *testing.T) {
|
||||||
|
116
x/cdp/legacy/v0_9/types.go
Normal file
116
x/cdp/legacy/v0_9/types.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package v0_9
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
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, principal sdk.Coin, time time.Time) CDP {
|
||||||
|
fees := sdk.NewCoin(principal.Denom, sdk.ZeroInt())
|
||||||
|
return CDP{
|
||||||
|
ID: id,
|
||||||
|
Owner: owner,
|
||||||
|
Collateral: collateral,
|
||||||
|
Principal: principal,
|
||||||
|
AccumulatedFees: fees,
|
||||||
|
FeesUpdated: time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDPs a collection of CDP objects
|
||||||
|
type CDPs []CDP
|
||||||
|
|
||||||
|
// 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}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deposits a collection of Deposit objects
|
||||||
|
type Deposits []Deposit
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollateralParams array of CollateralParam
|
||||||
|
type CollateralParams []CollateralParam
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
@ -79,6 +79,7 @@ func randomCdpGenState(selection int) types.GenesisState {
|
|||||||
CollateralParams: types.CollateralParams{
|
CollateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 20000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 20000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000004431822130"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000004431822130"),
|
||||||
@ -91,6 +92,7 @@ func randomCdpGenState(selection int) types.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
|
Type: "btc-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.25"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.25"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 50000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000000782997609"),
|
||||||
@ -103,6 +105,7 @@ func randomCdpGenState(selection int) types.GenesisState {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 30000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 30000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
|
||||||
@ -140,6 +143,7 @@ func randomCdpGenState(selection int) types.GenesisState {
|
|||||||
CollateralParams: types.CollateralParams{
|
CollateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 100000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 100000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000002293273137"),
|
||||||
|
@ -78,7 +78,7 @@ func SimulateMsgCdp(ak types.AccountKeeper, k keeper.Keeper, pfk types.Pricefeed
|
|||||||
}
|
}
|
||||||
spendableCoins = spendableCoins.Sub(fees)
|
spendableCoins = spendableCoins.Sub(fees)
|
||||||
|
|
||||||
existingCDP, found := k.GetCdpByOwnerAndDenom(ctx, acc.GetAddress(), randCollateralParam.Denom)
|
existingCDP, found := k.GetCdpByOwnerAndCollateralType(ctx, acc.GetAddress(), randCollateralParam.Denom)
|
||||||
if !found {
|
if !found {
|
||||||
// calculate the minimum amount of collateral that is needed to create a cdp with the debt floor amount of debt and the minimum liquidation ratio
|
// calculate the minimum amount of collateral that is needed to create a cdp with the debt floor amount of debt and the minimum liquidation ratio
|
||||||
// (debtFloor * liquidationRatio)/priceShifted
|
// (debtFloor * liquidationRatio)/priceShifted
|
||||||
@ -101,7 +101,7 @@ func SimulateMsgCdp(ak types.AccountKeeper, k keeper.Keeper, pfk types.Pricefeed
|
|||||||
// calculate the max amount of debt that could be drawn for the chosen deposit
|
// calculate the max amount of debt that could be drawn for the chosen deposit
|
||||||
maxDebtDraw := collateralDepositValue.Quo(randCollateralParam.LiquidationRatio).TruncateInt()
|
maxDebtDraw := collateralDepositValue.Quo(randCollateralParam.LiquidationRatio).TruncateInt()
|
||||||
// check that the debt limit hasn't been reached
|
// check that the debt limit hasn't been reached
|
||||||
availableAssetDebt := randCollateralParam.DebtLimit.Amount.Sub(k.GetTotalPrincipal(ctx, randCollateralParam.Denom, debtParam.Denom))
|
availableAssetDebt := randCollateralParam.DebtLimit.Amount.Sub(k.GetTotalPrincipal(ctx, randCollateralParam.Type, debtParam.Denom))
|
||||||
if availableAssetDebt.LTE(debtParam.DebtFloor) {
|
if availableAssetDebt.LTE(debtParam.DebtFloor) {
|
||||||
// debt limit has been reached
|
// debt limit has been reached
|
||||||
return simulation.NewOperationMsgBasic(types.ModuleName, "no-operation", "debt limit reached, cannot open cdp", false, nil), nil, nil
|
return simulation.NewOperationMsgBasic(types.ModuleName, "no-operation", "debt limit reached, cannot open cdp", false, nil), nil, nil
|
||||||
@ -111,7 +111,7 @@ func SimulateMsgCdp(ak types.AccountKeeper, k keeper.Keeper, pfk types.Pricefeed
|
|||||||
// randomly select a debt draw amount
|
// randomly select a debt draw amount
|
||||||
debtDraw := sdk.NewInt(int64(simulation.RandIntBetween(r, int(debtParam.DebtFloor.Int64()), int(maxDebtDraw.Int64()))))
|
debtDraw := sdk.NewInt(int64(simulation.RandIntBetween(r, int(debtParam.DebtFloor.Int64()), int(maxDebtDraw.Int64()))))
|
||||||
|
|
||||||
msg := types.NewMsgCreateCDP(acc.GetAddress(), sdk.NewCoin(randCollateralParam.Denom, collateralDeposit), sdk.NewCoin(debtParam.Denom, debtDraw))
|
msg := types.NewMsgCreateCDP(acc.GetAddress(), sdk.NewCoin(randCollateralParam.Denom, collateralDeposit), sdk.NewCoin(debtParam.Denom, debtDraw), randCollateralParam.Type)
|
||||||
|
|
||||||
tx := helpers.GenTx(
|
tx := helpers.GenTx(
|
||||||
[]sdk.Msg{msg},
|
[]sdk.Msg{msg},
|
||||||
@ -158,7 +158,7 @@ func SimulateMsgCdp(ak types.AccountKeeper, k keeper.Keeper, pfk types.Pricefeed
|
|||||||
// deposit 25% of the time
|
// deposit 25% of the time
|
||||||
if hasCoins(spendableCoins, randCollateralParam.Denom) && shouldDeposit(r) {
|
if hasCoins(spendableCoins, randCollateralParam.Denom) && shouldDeposit(r) {
|
||||||
randDepositAmount := sdk.NewInt(int64(simulation.RandIntBetween(r, 1, int(spendableCoins.AmountOf(randCollateralParam.Denom).Int64()))))
|
randDepositAmount := sdk.NewInt(int64(simulation.RandIntBetween(r, 1, int(spendableCoins.AmountOf(randCollateralParam.Denom).Int64()))))
|
||||||
msg := types.NewMsgDeposit(acc.GetAddress(), acc.GetAddress(), sdk.NewCoin(randCollateralParam.Denom, randDepositAmount))
|
msg := types.NewMsgDeposit(acc.GetAddress(), acc.GetAddress(), sdk.NewCoin(randCollateralParam.Denom, randDepositAmount), randCollateralParam.Type)
|
||||||
|
|
||||||
tx := helpers.GenTx(
|
tx := helpers.GenTx(
|
||||||
[]sdk.Msg{msg},
|
[]sdk.Msg{msg},
|
||||||
|
@ -12,20 +12,22 @@ import (
|
|||||||
|
|
||||||
// CDP is the state of a single collateralized debt position.
|
// CDP is the state of a single collateralized debt position.
|
||||||
type CDP struct {
|
type CDP struct {
|
||||||
ID uint64 `json:"id" yaml:"id"` // unique id for cdp
|
ID uint64 `json:"id" yaml:"id"` // unique id for cdp
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"` // Account that authorizes changes to the CDP
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"` // Account that authorizes changes to the CDP
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"` // Amount of collateral stored in this CDP
|
Type string `json:"type" yaml:"type"` // string representing the unique collateral type of the CDP
|
||||||
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"` // Amount of collateral stored in this CDP
|
||||||
AccumulatedFees sdk.Coin `json:"accumulated_fees" yaml:"accumulated_fees"`
|
Principal sdk.Coin `json:"principal" yaml:"principal"` // Amount of debt drawn using the CDP
|
||||||
FeesUpdated time.Time `json:"fees_updated" yaml:"fees_updated"` // Amount of stable coin drawn from this CDP
|
AccumulatedFees sdk.Coin `json:"accumulated_fees" yaml:"accumulated_fees"` // Fees accumulated since the CDP was opened or debt was last repayed
|
||||||
|
FeesUpdated time.Time `json:"fees_updated" yaml:"fees_updated"` // Amount of stable coin drawn from this CDP
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCDP creates a new CDP object
|
// NewCDP creates a new CDP object
|
||||||
func NewCDP(id uint64, owner sdk.AccAddress, collateral sdk.Coin, principal sdk.Coin, time time.Time) CDP {
|
func NewCDP(id uint64, owner sdk.AccAddress, collateral sdk.Coin, collateralType string, principal sdk.Coin, time time.Time) CDP {
|
||||||
fees := sdk.NewCoin(principal.Denom, sdk.ZeroInt())
|
fees := sdk.NewCoin(principal.Denom, sdk.ZeroInt())
|
||||||
return CDP{
|
return CDP{
|
||||||
ID: id,
|
ID: id,
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
|
Type: collateralType,
|
||||||
Collateral: collateral,
|
Collateral: collateral,
|
||||||
Principal: principal,
|
Principal: principal,
|
||||||
AccumulatedFees: fees,
|
AccumulatedFees: fees,
|
||||||
@ -45,7 +47,7 @@ func (cdp CDP) String() string {
|
|||||||
Fees Last Updated: %s`,
|
Fees Last Updated: %s`,
|
||||||
cdp.Owner,
|
cdp.Owner,
|
||||||
cdp.ID,
|
cdp.ID,
|
||||||
cdp.Collateral.Denom,
|
cdp.Type,
|
||||||
cdp.Collateral,
|
cdp.Collateral,
|
||||||
cdp.Principal,
|
cdp.Principal,
|
||||||
cdp.AccumulatedFees,
|
cdp.AccumulatedFees,
|
||||||
@ -73,10 +75,13 @@ func (cdp CDP) Validate() error {
|
|||||||
if cdp.FeesUpdated.IsZero() {
|
if cdp.FeesUpdated.IsZero() {
|
||||||
return errors.New("cdp updated fee time cannot be zero")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTotalPrinciple returns the total principle for the cdp
|
// GetTotalPrincipal returns the total principle for the cdp
|
||||||
func (cdp CDP) GetTotalPrincipal() sdk.Coin {
|
func (cdp CDP) GetTotalPrincipal() sdk.Coin {
|
||||||
return cdp.Principal.Add(cdp.AccumulatedFees)
|
return cdp.Principal.Add(cdp.AccumulatedFees)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "valid cdp",
|
name: "valid cdp",
|
||||||
cdp: types.NewCDP(1, suite.addrs[0], sdk.NewInt64Coin("bnb", 100000), sdk.NewInt64Coin("usdx", 100000), tmtime.Now()),
|
cdp: types.NewCDP(1, suite.addrs[0], sdk.NewInt64Coin("bnb", 100000), "bnb-a", sdk.NewInt64Coin("usdx", 100000), tmtime.Now()),
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
contains: "",
|
contains: "",
|
||||||
@ -50,7 +50,7 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid cdp id",
|
name: "invalid cdp id",
|
||||||
cdp: types.NewCDP(0, suite.addrs[0], sdk.NewInt64Coin("bnb", 100000), sdk.NewInt64Coin("usdx", 100000), tmtime.Now()),
|
cdp: types.NewCDP(0, suite.addrs[0], sdk.NewInt64Coin("bnb", 100000), "bnb-a", sdk.NewInt64Coin("usdx", 100000), tmtime.Now()),
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "cdp id cannot be 0",
|
contains: "cdp id cannot be 0",
|
||||||
@ -58,7 +58,7 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid collateral",
|
name: "invalid collateral",
|
||||||
cdp: types.CDP{1, suite.addrs[0], sdk.Coin{"", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, tmtime.Now()},
|
cdp: types.CDP{1, suite.addrs[0], "bnb-a", sdk.Coin{"", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, tmtime.Now()},
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "invalid coins: collateral",
|
contains: "invalid coins: collateral",
|
||||||
@ -66,7 +66,7 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid prinicpal",
|
name: "invalid prinicpal",
|
||||||
cdp: types.CDP{1, suite.addrs[0], sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, tmtime.Now()},
|
cdp: types.CDP{1, suite.addrs[0], "xrp-a", sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, tmtime.Now()},
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "invalid coins: principal",
|
contains: "invalid coins: principal",
|
||||||
@ -74,7 +74,7 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid fees",
|
name: "invalid fees",
|
||||||
cdp: types.CDP{1, suite.addrs[0], sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"", sdk.NewInt(0)}, tmtime.Now()},
|
cdp: types.CDP{1, suite.addrs[0], "xrp-a", sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"", sdk.NewInt(0)}, tmtime.Now()},
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "invalid coins: accumulated fees",
|
contains: "invalid coins: accumulated fees",
|
||||||
@ -82,12 +82,20 @@ func (suite *CdpValidationSuite) TestCdpValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid fees updated",
|
name: "invalid fees updated",
|
||||||
cdp: types.CDP{1, suite.addrs[0], sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, time.Time{}},
|
cdp: types.CDP{1, suite.addrs[0], "xrp-a", sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, time.Time{}},
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "cdp updated fee time cannot be zero",
|
contains: "cdp updated fee time cannot be zero",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "invalid type",
|
||||||
|
cdp: types.CDP{1, suite.addrs[0], "", sdk.Coin{"xrp", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(100)}, sdk.Coin{"usdx", sdk.NewInt(0)}, tmtime.Now()},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: false,
|
||||||
|
contains: "cdp type cannot be empty",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@ -161,11 +169,11 @@ func (suite *CdpValidationSuite) TestDepositValidation() {
|
|||||||
|
|
||||||
func (suite *CdpValidationSuite) TestCdpGetTotalPrinciple() {
|
func (suite *CdpValidationSuite) TestCdpGetTotalPrinciple() {
|
||||||
principal := sdk.Coin{"usdx", sdk.NewInt(100500)}
|
principal := sdk.Coin{"usdx", sdk.NewInt(100500)}
|
||||||
acummulatedFees := sdk.Coin{"usdx", sdk.NewInt(25000)}
|
accumulatedFees := sdk.Coin{"usdx", sdk.NewInt(25000)}
|
||||||
|
|
||||||
cdp := types.CDP{Principal: principal, AccumulatedFees: acummulatedFees}
|
cdp := types.CDP{Principal: principal, AccumulatedFees: accumulatedFees}
|
||||||
|
|
||||||
suite.Require().Equal(cdp.GetTotalPrincipal(), principal.Add(acummulatedFees))
|
suite.Require().Equal(cdp.GetTotalPrincipal(), principal.Add(accumulatedFees))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCdpValidationSuite(t *testing.T) {
|
func TestCdpValidationSuite(t *testing.T) {
|
||||||
|
@ -20,17 +20,19 @@ var (
|
|||||||
|
|
||||||
// MsgCreateCDP creates a cdp
|
// MsgCreateCDP creates a cdp
|
||||||
type MsgCreateCDP struct {
|
type MsgCreateCDP struct {
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
||||||
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgCreateCDP returns a new MsgPlaceBid.
|
// NewMsgCreateCDP returns a new MsgPlaceBid.
|
||||||
func NewMsgCreateCDP(sender sdk.AccAddress, collateral sdk.Coin, principal sdk.Coin) MsgCreateCDP {
|
func NewMsgCreateCDP(sender sdk.AccAddress, collateral sdk.Coin, principal sdk.Coin, collateralType string) MsgCreateCDP {
|
||||||
return MsgCreateCDP{
|
return MsgCreateCDP{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
Collateral: collateral,
|
Collateral: collateral,
|
||||||
Principal: principal,
|
Principal: principal,
|
||||||
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +53,9 @@ func (msg MsgCreateCDP) ValidateBasic() error {
|
|||||||
if msg.Principal.IsZero() || !msg.Principal.IsValid() {
|
if msg.Principal.IsZero() || !msg.Principal.IsValid() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "principal amount %s", msg.Principal)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "principal amount %s", msg.Principal)
|
||||||
}
|
}
|
||||||
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be empty")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,17 +81,19 @@ func (msg MsgCreateCDP) String() string {
|
|||||||
|
|
||||||
// MsgDeposit deposit collateral to an existing cdp.
|
// MsgDeposit deposit collateral to an existing cdp.
|
||||||
type MsgDeposit struct {
|
type MsgDeposit struct {
|
||||||
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgDeposit returns a new MsgDeposit
|
// NewMsgDeposit returns a new MsgDeposit
|
||||||
func NewMsgDeposit(owner sdk.AccAddress, depositor sdk.AccAddress, collateral sdk.Coin) MsgDeposit {
|
func NewMsgDeposit(owner sdk.AccAddress, depositor sdk.AccAddress, collateral sdk.Coin, collateralType string) MsgDeposit {
|
||||||
return MsgDeposit{
|
return MsgDeposit{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Depositor: depositor,
|
Depositor: depositor,
|
||||||
Collateral: collateral,
|
Collateral: collateral,
|
||||||
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +114,9 @@ func (msg MsgDeposit) ValidateBasic() error {
|
|||||||
if !msg.Collateral.IsValid() || msg.Collateral.IsZero() {
|
if !msg.Collateral.IsValid() || msg.Collateral.IsZero() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "collateral amount %s", msg.Collateral)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "collateral amount %s", msg.Collateral)
|
||||||
}
|
}
|
||||||
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be empty")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,22 +137,25 @@ func (msg MsgDeposit) String() string {
|
|||||||
Sender: %s
|
Sender: %s
|
||||||
Owner: %s
|
Owner: %s
|
||||||
Collateral: %s
|
Collateral: %s
|
||||||
`, msg.Owner, msg.Owner, msg.Collateral)
|
CollateralType: %s
|
||||||
|
`, msg.Owner, msg.Owner, msg.Collateral, msg.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgWithdraw withdraw collateral from an existing cdp.
|
// MsgWithdraw withdraw collateral from an existing cdp.
|
||||||
type MsgWithdraw struct {
|
type MsgWithdraw struct {
|
||||||
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
Collateral sdk.Coin `json:"collateral" yaml:"collateral"`
|
||||||
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgWithdraw returns a new MsgDeposit
|
// NewMsgWithdraw returns a new MsgDeposit
|
||||||
func NewMsgWithdraw(owner sdk.AccAddress, depositor sdk.AccAddress, collateral sdk.Coin) MsgWithdraw {
|
func NewMsgWithdraw(owner sdk.AccAddress, depositor sdk.AccAddress, collateral sdk.Coin, collateralType string) MsgWithdraw {
|
||||||
return MsgWithdraw{
|
return MsgWithdraw{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Depositor: depositor,
|
Depositor: depositor,
|
||||||
Collateral: collateral,
|
Collateral: collateral,
|
||||||
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +176,9 @@ func (msg MsgWithdraw) ValidateBasic() error {
|
|||||||
if !msg.Collateral.IsValid() || msg.Collateral.IsZero() {
|
if !msg.Collateral.IsValid() || msg.Collateral.IsZero() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "collateral amount %s", msg.Collateral)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "collateral amount %s", msg.Collateral)
|
||||||
}
|
}
|
||||||
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be empty")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,17 +204,17 @@ func (msg MsgWithdraw) String() string {
|
|||||||
|
|
||||||
// MsgDrawDebt draw debt off of collateral in cdp
|
// MsgDrawDebt draw debt off of collateral in cdp
|
||||||
type MsgDrawDebt struct {
|
type MsgDrawDebt struct {
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
CdpDenom string `json:"cdp_denom" yaml:"cdp_denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
Principal sdk.Coin `json:"principal" yaml:"principal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgDrawDebt returns a new MsgDrawDebt
|
// NewMsgDrawDebt returns a new MsgDrawDebt
|
||||||
func NewMsgDrawDebt(sender sdk.AccAddress, denom string, principal sdk.Coin) MsgDrawDebt {
|
func NewMsgDrawDebt(sender sdk.AccAddress, collateralType string, principal sdk.Coin) MsgDrawDebt {
|
||||||
return MsgDrawDebt{
|
return MsgDrawDebt{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
CdpDenom: denom,
|
CollateralType: collateralType,
|
||||||
Principal: principal,
|
Principal: principal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,8 +229,8 @@ func (msg MsgDrawDebt) ValidateBasic() error {
|
|||||||
if msg.Sender.Empty() {
|
if msg.Sender.Empty() {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(msg.CdpDenom) == "" {
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
return errors.New("cdp denom cannot be blank")
|
return errors.New("cdp collateral type cannot be blank")
|
||||||
}
|
}
|
||||||
if msg.Principal.IsZero() || !msg.Principal.IsValid() {
|
if msg.Principal.IsZero() || !msg.Principal.IsValid() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "principal amount %s", msg.Principal)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "principal amount %s", msg.Principal)
|
||||||
@ -237,24 +253,24 @@ func (msg MsgDrawDebt) GetSigners() []sdk.AccAddress {
|
|||||||
func (msg MsgDrawDebt) String() string {
|
func (msg MsgDrawDebt) String() string {
|
||||||
return fmt.Sprintf(`Draw debt from CDP Message:
|
return fmt.Sprintf(`Draw debt from CDP Message:
|
||||||
Sender: %s
|
Sender: %s
|
||||||
CDP Denom: %s
|
Collateral Type: %s
|
||||||
Principal: %s
|
Principal: %s
|
||||||
`, msg.Sender, msg.CdpDenom, msg.Principal)
|
`, msg.Sender, msg.CollateralType, msg.Principal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgRepayDebt repay debt drawn off the collateral in a CDP
|
// MsgRepayDebt repay debt drawn off the collateral in a CDP
|
||||||
type MsgRepayDebt struct {
|
type MsgRepayDebt struct {
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
CdpDenom string `json:"cdp_denom" yaml:"cdp_denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
Payment sdk.Coin `json:"payment" yaml:"payment"`
|
Payment sdk.Coin `json:"payment" yaml:"payment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgRepayDebt returns a new MsgRepayDebt
|
// NewMsgRepayDebt returns a new MsgRepayDebt
|
||||||
func NewMsgRepayDebt(sender sdk.AccAddress, denom string, payment sdk.Coin) MsgRepayDebt {
|
func NewMsgRepayDebt(sender sdk.AccAddress, collateralType string, payment sdk.Coin) MsgRepayDebt {
|
||||||
return MsgRepayDebt{
|
return MsgRepayDebt{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
CdpDenom: denom,
|
CollateralType: collateralType,
|
||||||
Payment: payment,
|
Payment: payment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,8 +285,8 @@ func (msg MsgRepayDebt) ValidateBasic() error {
|
|||||||
if msg.Sender.Empty() {
|
if msg.Sender.Empty() {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(msg.CdpDenom) == "" {
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
return errors.New("cdp denom cannot be blank")
|
return errors.New("cdp collateral type cannot be blank")
|
||||||
}
|
}
|
||||||
if msg.Payment.IsZero() || !msg.Payment.IsValid() {
|
if msg.Payment.IsZero() || !msg.Payment.IsValid() {
|
||||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "payment amount %s", msg.Payment)
|
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "payment amount %s", msg.Payment)
|
||||||
@ -293,7 +309,7 @@ func (msg MsgRepayDebt) GetSigners() []sdk.AccAddress {
|
|||||||
func (msg MsgRepayDebt) String() string {
|
func (msg MsgRepayDebt) String() string {
|
||||||
return fmt.Sprintf(`Draw debt from CDP Message:
|
return fmt.Sprintf(`Draw debt from CDP Message:
|
||||||
Sender: %s
|
Sender: %s
|
||||||
CDP Denom: %s
|
Collateral Type: %s
|
||||||
Payment: %s
|
Payment: %s
|
||||||
`, msg.Sender, msg.CdpDenom, msg.Payment)
|
`, msg.Sender, msg.CollateralType, msg.Payment)
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,18 @@ var (
|
|||||||
|
|
||||||
func TestMsgCreateCDP(t *testing.T) {
|
func TestMsgCreateCDP(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
description string
|
description string
|
||||||
sender sdk.AccAddress
|
sender sdk.AccAddress
|
||||||
collateral sdk.Coin
|
collateral sdk.Coin
|
||||||
principal sdk.Coin
|
principal sdk.Coin
|
||||||
expectPass bool
|
collateralType string
|
||||||
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"create cdp", addrs[0], coinsSingle, coinsSingle, true},
|
{"create cdp", addrs[0], coinsSingle, coinsSingle, "type-a", true},
|
||||||
{"create cdp no collateral", addrs[0], coinsZero, coinsSingle, false},
|
{"create cdp no collateral", addrs[0], coinsZero, coinsSingle, "type-a", false},
|
||||||
{"create cdp no debt", addrs[0], coinsSingle, coinsZero, false},
|
{"create cdp no debt", addrs[0], coinsSingle, coinsZero, "type-a", false},
|
||||||
{"create cdp empty owner", sdk.AccAddress{}, coinsSingle, coinsSingle, false},
|
{"create cdp empty owner", sdk.AccAddress{}, coinsSingle, coinsSingle, "type-a", false},
|
||||||
|
{"create cdp empty type", addrs[0], coinsSingle, coinsSingle, "", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@ -36,6 +38,7 @@ func TestMsgCreateCDP(t *testing.T) {
|
|||||||
tc.sender,
|
tc.sender,
|
||||||
tc.collateral,
|
tc.collateral,
|
||||||
tc.principal,
|
tc.principal,
|
||||||
|
tc.collateralType,
|
||||||
)
|
)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
||||||
@ -47,17 +50,19 @@ func TestMsgCreateCDP(t *testing.T) {
|
|||||||
|
|
||||||
func TestMsgDeposit(t *testing.T) {
|
func TestMsgDeposit(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
description string
|
description string
|
||||||
sender sdk.AccAddress
|
sender sdk.AccAddress
|
||||||
depositor sdk.AccAddress
|
depositor sdk.AccAddress
|
||||||
collateral sdk.Coin
|
collateral sdk.Coin
|
||||||
expectPass bool
|
collateralType string
|
||||||
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"deposit", addrs[0], addrs[1], coinsSingle, true},
|
{"deposit", addrs[0], addrs[1], coinsSingle, "type-a", true},
|
||||||
{"deposit", addrs[0], addrs[0], coinsSingle, true},
|
{"deposit same owner", addrs[0], addrs[0], coinsSingle, "type-a", true},
|
||||||
{"deposit no collateral", addrs[0], addrs[1], coinsZero, false},
|
{"deposit no collateral", addrs[0], addrs[1], coinsZero, "type-a", false},
|
||||||
{"deposit empty owner", sdk.AccAddress{}, addrs[1], coinsSingle, false},
|
{"deposit empty owner", sdk.AccAddress{}, addrs[1], coinsSingle, "type-a", false},
|
||||||
{"deposit empty depositor", addrs[0], sdk.AccAddress{}, coinsSingle, false},
|
{"deposit empty depositor", addrs[0], sdk.AccAddress{}, coinsSingle, "type-a", false},
|
||||||
|
{"deposit empty type", addrs[0], addrs[0], coinsSingle, "", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@ -65,6 +70,7 @@ func TestMsgDeposit(t *testing.T) {
|
|||||||
tc.sender,
|
tc.sender,
|
||||||
tc.depositor,
|
tc.depositor,
|
||||||
tc.collateral,
|
tc.collateral,
|
||||||
|
tc.collateralType,
|
||||||
)
|
)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
||||||
@ -76,17 +82,19 @@ func TestMsgDeposit(t *testing.T) {
|
|||||||
|
|
||||||
func TestMsgWithdraw(t *testing.T) {
|
func TestMsgWithdraw(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
description string
|
description string
|
||||||
sender sdk.AccAddress
|
sender sdk.AccAddress
|
||||||
depositor sdk.AccAddress
|
depositor sdk.AccAddress
|
||||||
collateral sdk.Coin
|
collateral sdk.Coin
|
||||||
expectPass bool
|
collateralType string
|
||||||
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"withdraw", addrs[0], addrs[1], coinsSingle, true},
|
{"withdraw", addrs[0], addrs[1], coinsSingle, "type-a", true},
|
||||||
{"withdraw", addrs[0], addrs[0], coinsSingle, true},
|
{"withdraw", addrs[0], addrs[0], coinsSingle, "type-a", true},
|
||||||
{"withdraw no collateral", addrs[0], addrs[1], coinsZero, false},
|
{"withdraw no collateral", addrs[0], addrs[1], coinsZero, "type-a", false},
|
||||||
{"withdraw empty owner", sdk.AccAddress{}, addrs[1], coinsSingle, false},
|
{"withdraw empty owner", sdk.AccAddress{}, addrs[1], coinsSingle, "type-a", false},
|
||||||
{"withdraw empty depositor", addrs[0], sdk.AccAddress{}, coinsSingle, false},
|
{"withdraw empty depositor", addrs[0], sdk.AccAddress{}, coinsSingle, "type-a", false},
|
||||||
|
{"withdraw empty type", addrs[0], addrs[0], coinsSingle, "", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@ -94,6 +102,7 @@ func TestMsgWithdraw(t *testing.T) {
|
|||||||
tc.sender,
|
tc.sender,
|
||||||
tc.depositor,
|
tc.depositor,
|
||||||
tc.collateral,
|
tc.collateral,
|
||||||
|
tc.collateralType,
|
||||||
)
|
)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
require.NoError(t, msg.ValidateBasic(), "test: %v", tc.description)
|
||||||
@ -105,11 +114,11 @@ func TestMsgWithdraw(t *testing.T) {
|
|||||||
|
|
||||||
func TestMsgDrawDebt(t *testing.T) {
|
func TestMsgDrawDebt(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
description string
|
description string
|
||||||
sender sdk.AccAddress
|
sender sdk.AccAddress
|
||||||
denom string
|
collateralType string
|
||||||
principal sdk.Coin
|
principal sdk.Coin
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}{
|
}{
|
||||||
{"draw debt", addrs[0], sdk.DefaultBondDenom, coinsSingle, true},
|
{"draw debt", addrs[0], sdk.DefaultBondDenom, coinsSingle, true},
|
||||||
{"draw debt no debt", addrs[0], sdk.DefaultBondDenom, coinsZero, false},
|
{"draw debt no debt", addrs[0], sdk.DefaultBondDenom, coinsZero, false},
|
||||||
@ -120,7 +129,7 @@ func TestMsgDrawDebt(t *testing.T) {
|
|||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
msg := NewMsgDrawDebt(
|
msg := NewMsgDrawDebt(
|
||||||
tc.sender,
|
tc.sender,
|
||||||
tc.denom,
|
tc.collateralType,
|
||||||
tc.principal,
|
tc.principal,
|
||||||
)
|
)
|
||||||
if tc.expectPass {
|
if tc.expectPass {
|
||||||
|
@ -107,7 +107,8 @@ func DefaultParams() Params {
|
|||||||
|
|
||||||
// CollateralParam governance parameters for each collateral type within the cdp module
|
// CollateralParam governance parameters for each collateral type within the cdp module
|
||||||
type CollateralParam struct {
|
type CollateralParam struct {
|
||||||
Denom string `json:"denom" yaml:"denom"` // Coin name of collateral type
|
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
|
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
|
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
|
StabilityFee sdk.Dec `json:"stability_fee" yaml:"stability_fee"` // per second stability fee for loans opened using this collateral
|
||||||
@ -123,6 +124,7 @@ type CollateralParam struct {
|
|||||||
func (cp CollateralParam) String() string {
|
func (cp CollateralParam) String() string {
|
||||||
return fmt.Sprintf(`Collateral:
|
return fmt.Sprintf(`Collateral:
|
||||||
Denom: %s
|
Denom: %s
|
||||||
|
Type: %s
|
||||||
Liquidation Ratio: %s
|
Liquidation Ratio: %s
|
||||||
Stability Fee: %s
|
Stability Fee: %s
|
||||||
Liquidation Penalty: %s
|
Liquidation Penalty: %s
|
||||||
@ -132,7 +134,7 @@ func (cp CollateralParam) String() string {
|
|||||||
Spot Market ID: %s
|
Spot Market ID: %s
|
||||||
Liquidation Market ID: %s
|
Liquidation Market ID: %s
|
||||||
Conversion Factor: %s`,
|
Conversion Factor: %s`,
|
||||||
cp.Denom, cp.LiquidationRatio, cp.StabilityFee, cp.LiquidationPenalty, cp.DebtLimit, cp.AuctionSize, cp.Prefix, cp.SpotMarketID, cp.LiquidationMarketID, cp.ConversionFactor)
|
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
|
// CollateralParams array of CollateralParam
|
||||||
@ -299,8 +301,8 @@ func validateCollateralParams(i interface{}) error {
|
|||||||
return fmt.Errorf("invalid parameter type: %T", i)
|
return fmt.Errorf("invalid parameter type: %T", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
collateralDupMap := make(map[string]bool)
|
|
||||||
prefixDupMap := make(map[int]bool)
|
prefixDupMap := make(map[int]bool)
|
||||||
|
typeDupMap := make(map[string]bool)
|
||||||
for _, cp := range collateralParams {
|
for _, cp := range collateralParams {
|
||||||
if err := sdk.ValidateDenom(cp.Denom); err != nil {
|
if err := sdk.ValidateDenom(cp.Denom); err != nil {
|
||||||
return fmt.Errorf("collateral denom invalid %s", cp.Denom)
|
return fmt.Errorf("collateral denom invalid %s", cp.Denom)
|
||||||
@ -310,6 +312,10 @@ func validateCollateralParams(i interface{}) error {
|
|||||||
return fmt.Errorf("spot market id cannot be blank %s", cp)
|
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) == "" {
|
if strings.TrimSpace(cp.LiquidationMarketID) == "" {
|
||||||
return fmt.Errorf("liquidation market id cannot be blank %s", cp)
|
return fmt.Errorf("liquidation market id cannot be blank %s", cp)
|
||||||
}
|
}
|
||||||
@ -326,12 +332,11 @@ func validateCollateralParams(i interface{}) error {
|
|||||||
|
|
||||||
prefixDupMap[prefix] = true
|
prefixDupMap[prefix] = true
|
||||||
|
|
||||||
_, found = collateralDupMap[cp.Denom]
|
_, found = typeDupMap[cp.Type]
|
||||||
if found {
|
if found {
|
||||||
return fmt.Errorf("duplicate collateral denom: %s", cp.Denom)
|
return fmt.Errorf("duplicate cdp collateral type: %s", cp.Type)
|
||||||
}
|
}
|
||||||
|
typeDupMap[cp.Type] = true
|
||||||
collateralDupMap[cp.Denom] = true
|
|
||||||
|
|
||||||
if !cp.DebtLimit.IsValid() {
|
if !cp.DebtLimit.IsValid() {
|
||||||
return fmt.Errorf("debt limit for all collaterals should be positive, is %s for %s", cp.DebtLimit, cp.Denom)
|
return fmt.Errorf("debt limit for all collaterals should be positive, is %s for %s", cp.DebtLimit, cp.Denom)
|
||||||
|
@ -66,6 +66,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -103,6 +104,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -140,6 +142,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -177,6 +180,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -189,6 +193,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -226,6 +231,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -238,6 +244,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -275,6 +282,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -287,6 +295,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("susd", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("susd", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -361,6 +370,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -392,12 +402,13 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid collateral params duplicate denom",
|
name: "invalid collateral params duplicate denom + type",
|
||||||
args: args{
|
args: args{
|
||||||
globalDebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
globalDebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -410,6 +421,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -437,7 +449,58 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
errArgs: errArgs{
|
errArgs: errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "duplicate collateral denom",
|
contains: "duplicate cdp collateral type",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid collateral params duplicate denom + different type",
|
||||||
|
args: args{
|
||||||
|
globalDebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
|
collateralParams: types.CollateralParams{
|
||||||
|
{
|
||||||
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
|
LiquidationPenalty: sdk.MustNewDecFromStr("0.05"),
|
||||||
|
AuctionSize: sdk.NewInt(50000000000),
|
||||||
|
Prefix: 0x20,
|
||||||
|
SpotMarketID: "bnb:usd",
|
||||||
|
LiquidationMarketID: "bnb:usd",
|
||||||
|
ConversionFactor: sdk.NewInt(8),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Denom: "bnb",
|
||||||
|
Type: "bnb-b",
|
||||||
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
|
LiquidationPenalty: sdk.MustNewDecFromStr("0.05"),
|
||||||
|
AuctionSize: sdk.NewInt(50000000000),
|
||||||
|
Prefix: 0x21,
|
||||||
|
SpotMarketID: "bnb:usd",
|
||||||
|
LiquidationMarketID: "bnb:usd",
|
||||||
|
ConversionFactor: sdk.NewInt(8),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
debtParam: types.DebtParam{
|
||||||
|
Denom: "usdx",
|
||||||
|
ReferenceAsset: "usd",
|
||||||
|
ConversionFactor: sdk.NewInt(6),
|
||||||
|
DebtFloor: sdk.NewInt(10000000),
|
||||||
|
SavingsRate: sdk.MustNewDecFromStr("0.95"),
|
||||||
|
},
|
||||||
|
surplusThreshold: types.DefaultSurplusThreshold,
|
||||||
|
surplusLot: types.DefaultSurplusLot,
|
||||||
|
debtThreshold: types.DefaultDebtThreshold,
|
||||||
|
debtLot: types.DefaultDebtLot,
|
||||||
|
distributionFreq: types.DefaultSavingsDistributionFrequency,
|
||||||
|
breaker: types.DefaultCircuitBreaker,
|
||||||
|
},
|
||||||
|
errArgs: errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
contains: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -447,6 +510,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -459,6 +523,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "xrp",
|
Denom: "xrp",
|
||||||
|
Type: "xrp-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -496,6 +561,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.Coin{},
|
DebtLimit: sdk.Coin{},
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -533,6 +599,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -570,6 +637,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -607,6 +675,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.1"),
|
StabilityFee: sdk.MustNewDecFromStr("1.1"),
|
||||||
@ -644,6 +713,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
@ -681,6 +751,7 @@ func (suite *ParamsTestSuite) TestParamValidation() {
|
|||||||
collateralParams: types.CollateralParams{
|
collateralParams: types.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
LiquidationRatio: sdk.MustNewDecFromStr("1.5"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 2000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"),
|
||||||
|
@ -13,60 +13,60 @@ const (
|
|||||||
QueryGetParams = "params"
|
QueryGetParams = "params"
|
||||||
QueryGetAccounts = "accounts"
|
QueryGetAccounts = "accounts"
|
||||||
RestOwner = "owner"
|
RestOwner = "owner"
|
||||||
RestCollateralDenom = "collateral-denom"
|
RestCollateralType = "collateral-type"
|
||||||
RestRatio = "ratio"
|
RestRatio = "ratio"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QueryCdpsParams params for query /cdp/cdps
|
// QueryCdpsParams params for query /cdp/cdps
|
||||||
type QueryCdpsParams struct {
|
type QueryCdpsParams struct {
|
||||||
CollateralDenom string // get CDPs with this collateral denom
|
CollateralType string // get CDPs with this collateral type
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryCdpsParams returns QueryCdpsParams
|
// NewQueryCdpsParams returns QueryCdpsParams
|
||||||
func NewQueryCdpsParams(denom string) QueryCdpsParams {
|
func NewQueryCdpsParams(collateralType string) QueryCdpsParams {
|
||||||
return QueryCdpsParams{
|
return QueryCdpsParams{
|
||||||
CollateralDenom: denom,
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryCdpParams params for query /cdp/cdp
|
// QueryCdpParams params for query /cdp/cdp
|
||||||
type QueryCdpParams struct {
|
type QueryCdpParams struct {
|
||||||
CollateralDenom string // get CDPs with this collateral denom
|
CollateralType string // get CDPs with this collateral type
|
||||||
Owner sdk.AccAddress // get CDPs belonging to this owner
|
Owner sdk.AccAddress // get CDPs belonging to this owner
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryCdpParams returns QueryCdpParams
|
// NewQueryCdpParams returns QueryCdpParams
|
||||||
func NewQueryCdpParams(owner sdk.AccAddress, denom string) QueryCdpParams {
|
func NewQueryCdpParams(owner sdk.AccAddress, collateralType string) QueryCdpParams {
|
||||||
return QueryCdpParams{
|
return QueryCdpParams{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
CollateralDenom: denom,
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryCdpDeposits params for query /cdp/deposits
|
// QueryCdpDeposits params for query /cdp/deposits
|
||||||
type QueryCdpDeposits struct {
|
type QueryCdpDeposits struct {
|
||||||
CollateralDenom string // get CDPs with this collateral denom
|
CollateralType string // get CDPs with this collateral type
|
||||||
Owner sdk.AccAddress // get CDPs belonging to this owner
|
Owner sdk.AccAddress // get CDPs belonging to this owner
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryCdpDeposits returns QueryCdpDeposits
|
// NewQueryCdpDeposits returns QueryCdpDeposits
|
||||||
func NewQueryCdpDeposits(owner sdk.AccAddress, denom string) QueryCdpDeposits {
|
func NewQueryCdpDeposits(owner sdk.AccAddress, collateralType string) QueryCdpDeposits {
|
||||||
return QueryCdpDeposits{
|
return QueryCdpDeposits{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
CollateralDenom: denom,
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryCdpsByRatioParams params for query /cdp/cdps/ratio
|
// QueryCdpsByRatioParams params for query /cdp/cdps/ratio
|
||||||
type QueryCdpsByRatioParams struct {
|
type QueryCdpsByRatioParams struct {
|
||||||
CollateralDenom string // get CDPs with this collateral denom
|
CollateralType string
|
||||||
Ratio sdk.Dec // get CDPs below this collateral:debt ratio
|
Ratio sdk.Dec // get CDPs below this collateral:debt ratio
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryCdpsByRatioParams returns QueryCdpsByRatioParams
|
// NewQueryCdpsByRatioParams returns QueryCdpsByRatioParams
|
||||||
func NewQueryCdpsByRatioParams(denom string, ratio sdk.Dec) QueryCdpsByRatioParams {
|
func NewQueryCdpsByRatioParams(collateralType string, ratio sdk.Dec) QueryCdpsByRatioParams {
|
||||||
return QueryCdpsByRatioParams{
|
return QueryCdpsByRatioParams{
|
||||||
CollateralDenom: denom,
|
CollateralType: collateralType,
|
||||||
Ratio: ratio,
|
Ratio: ratio,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
testCPs := cdptypes.CollateralParams{
|
testCPs := cdptypes.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: d("2.0"),
|
LiquidationRatio: d("2.0"),
|
||||||
DebtLimit: c("usdx", 1000000000000),
|
DebtLimit: c("usdx", 1000000000000),
|
||||||
StabilityFee: d("1.000000001547125958"),
|
StabilityFee: d("1.000000001547125958"),
|
||||||
@ -44,6 +45,7 @@ func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Denom: "btc",
|
Denom: "btc",
|
||||||
|
Type: "btc-a",
|
||||||
LiquidationRatio: d("1.5"),
|
LiquidationRatio: d("1.5"),
|
||||||
DebtLimit: c("usdx", 1000000000),
|
DebtLimit: c("usdx", 1000000000),
|
||||||
StabilityFee: d("1.000000001547125958"),
|
StabilityFee: d("1.000000001547125958"),
|
||||||
|
@ -87,6 +87,7 @@ func (suite *KeeperTestSuite) TestSubmitProposal() {
|
|||||||
|
|
||||||
testCP := cdptypes.CollateralParams{{
|
testCP := cdptypes.CollateralParams{{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: d("1.5"),
|
LiquidationRatio: d("1.5"),
|
||||||
DebtLimit: c("usdx", 1000000000000),
|
DebtLimit: c("usdx", 1000000000000),
|
||||||
StabilityFee: d("1.000000001547125958"), // %5 apr
|
StabilityFee: d("1.000000001547125958"), // %5 apr
|
||||||
|
@ -28,7 +28,7 @@ const (
|
|||||||
QuerierRoute = types.QuerierRoute
|
QuerierRoute = types.QuerierRoute
|
||||||
QueryGetClaims = types.QueryGetClaims
|
QueryGetClaims = types.QueryGetClaims
|
||||||
RestClaimOwner = types.RestClaimOwner
|
RestClaimOwner = types.RestClaimOwner
|
||||||
RestClaimDenom = types.RestClaimDenom
|
RestClaimCollateralType = types.RestClaimCollateralType
|
||||||
QueryGetParams = types.QueryGetParams
|
QueryGetParams = types.QueryGetParams
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ func queryClaimsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bz, err := cdc.MarshalJSON(types.QueryClaimsParams{
|
bz, err := cdc.MarshalJSON(types.QueryClaimsParams{
|
||||||
Owner: ownerAddress,
|
Owner: ownerAddress,
|
||||||
Denom: args[1],
|
CollateralType: args[1],
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -34,7 +34,7 @@ func queryClaimsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
ownerBech32 := vars[types.RestClaimOwner]
|
ownerBech32 := vars[types.RestClaimOwner]
|
||||||
denom := vars[types.RestClaimDenom]
|
denom := vars[types.RestClaimCollateralType]
|
||||||
|
|
||||||
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
owner, err := sdk.AccAddressFromBech32(ownerBech32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -42,7 +42,7 @@ func postClaimHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := types.NewMsgClaimReward(requestBody.Sender, requestBody.Denom)
|
msg := types.NewMsgClaimReward(requestBody.Sender, requestBody.CollateralType)
|
||||||
if err := msg.ValidateBasic(); err != nil {
|
if err := msg.ValidateBasic(); err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -25,7 +25,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
|
|||||||
k.SetParams(ctx, gs.Params)
|
k.SetParams(ctx, gs.Params)
|
||||||
|
|
||||||
for _, r := range gs.Params.Rewards {
|
for _, r := range gs.Params.Rewards {
|
||||||
k.SetNextClaimPeriodID(ctx, r.Denom, 1)
|
k.SetNextClaimPeriodID(ctx, r.CollateralType, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// only set the previous block time if it's different than default
|
// only set the previous block time if it's different than default
|
||||||
@ -47,7 +47,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, id := range gs.NextClaimPeriodIDs {
|
for _, id := range gs.NextClaimPeriodIDs {
|
||||||
k.SetNextClaimPeriodID(ctx, id.Denom, id.ID)
|
k.SetNextClaimPeriodID(ctx, id.CollateralType, id.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,13 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
|||||||
|
|
||||||
func handleMsgClaimReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimReward) (*sdk.Result, error) {
|
func handleMsgClaimReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimReward) (*sdk.Result, error) {
|
||||||
|
|
||||||
claims, found := k.GetClaimsByAddressAndDenom(ctx, msg.Sender, msg.Denom)
|
claims, found := k.GetClaimsByAddressAndCollateralType(ctx, msg.Sender, msg.CollateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, sdkerrors.Wrapf(types.ErrNoClaimsFound, "address: %s, denom: %s", msg.Sender, msg.Denom)
|
return nil, sdkerrors.Wrapf(types.ErrNoClaimsFound, "address: %s, collateral type: %s", msg.Sender, msg.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, claim := range claims {
|
for _, claim := range claims {
|
||||||
err := k.PayoutClaim(ctx, claim.Owner, claim.Denom, claim.ClaimPeriodID)
|
err := k.PayoutClaim(ctx, claim.Owner, claim.CollateralType, claim.ClaimPeriodID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,10 @@ func NewKeeper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRewardPeriod returns the reward period from the store for the input denom and a boolean for if it was found
|
// GetRewardPeriod returns the reward period from the store for the input collateral type and a boolean for if it was found
|
||||||
func (k Keeper) GetRewardPeriod(ctx sdk.Context, denom string) (types.RewardPeriod, bool) {
|
func (k Keeper) GetRewardPeriod(ctx sdk.Context, collateralType string) (types.RewardPeriod, bool) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
||||||
bz := store.Get([]byte(denom))
|
bz := store.Get([]byte(collateralType))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return types.RewardPeriod{}, false
|
return types.RewardPeriod{}, false
|
||||||
}
|
}
|
||||||
@ -53,13 +53,13 @@ func (k Keeper) GetRewardPeriod(ctx sdk.Context, denom string) (types.RewardPeri
|
|||||||
func (k Keeper) SetRewardPeriod(ctx sdk.Context, rp types.RewardPeriod) {
|
func (k Keeper) SetRewardPeriod(ctx sdk.Context, rp types.RewardPeriod) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
||||||
bz := k.cdc.MustMarshalBinaryBare(rp)
|
bz := k.cdc.MustMarshalBinaryBare(rp)
|
||||||
store.Set([]byte(rp.Denom), bz)
|
store.Set([]byte(rp.CollateralType), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRewardPeriod deletes the reward period in the store for the input denom,
|
// DeleteRewardPeriod deletes the reward period in the store for the input collateral type,
|
||||||
func (k Keeper) DeleteRewardPeriod(ctx sdk.Context, denom string) {
|
func (k Keeper) DeleteRewardPeriod(ctx sdk.Context, collateralType string) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
||||||
store.Delete([]byte(denom))
|
store.Delete([]byte(collateralType))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateRewardPeriods iterates over all reward period objects in the store and preforms a callback function
|
// IterateRewardPeriods iterates over all reward period objects in the store and preforms a callback function
|
||||||
@ -86,44 +86,44 @@ func (k Keeper) GetAllRewardPeriods(ctx sdk.Context) types.RewardPeriods {
|
|||||||
return rps
|
return rps
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNextClaimPeriodID returns the highest claim period id in the store for the input denom
|
// GetNextClaimPeriodID returns the highest claim period id in the store for the input collateral type
|
||||||
func (k Keeper) GetNextClaimPeriodID(ctx sdk.Context, denom string) uint64 {
|
func (k Keeper) GetNextClaimPeriodID(ctx sdk.Context, collateralType string) uint64 {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
||||||
bz := store.Get([]byte(denom))
|
bz := store.Get([]byte(collateralType))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
k.SetNextClaimPeriodID(ctx, denom, 1)
|
k.SetNextClaimPeriodID(ctx, collateralType, 1)
|
||||||
return uint64(1)
|
return uint64(1)
|
||||||
}
|
}
|
||||||
return types.BytesToUint64(bz)
|
return types.BytesToUint64(bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNextClaimPeriodID sets the highest claim period id in the store for the input denom
|
// SetNextClaimPeriodID sets the highest claim period id in the store for the input collateral type
|
||||||
func (k Keeper) SetNextClaimPeriodID(ctx sdk.Context, denom string, id uint64) {
|
func (k Keeper) SetNextClaimPeriodID(ctx sdk.Context, collateralType string, id uint64) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
||||||
store.Set([]byte(denom), sdk.Uint64ToBigEndian(id))
|
store.Set([]byte(collateralType), sdk.Uint64ToBigEndian(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateClaimPeriodIDKeysAndValues iterates over the claim period id (value) and denom (key) of each claim period id in the store and performs a callback function
|
// IterateClaimPeriodIDKeysAndValues iterates over the claim period id (value) and collateral type (key) of each claim period id in the store and performs a callback function
|
||||||
func (k Keeper) IterateClaimPeriodIDKeysAndValues(ctx sdk.Context, cb func(denom string, id uint64) (stop bool)) {
|
func (k Keeper) IterateClaimPeriodIDKeysAndValues(ctx sdk.Context, cb func(collateralType string, id uint64) (stop bool)) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.NextClaimPeriodIDPrefix)
|
||||||
iterator := sdk.KVStorePrefixIterator(store, []byte{})
|
iterator := sdk.KVStorePrefixIterator(store, []byte{})
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
id := types.BytesToUint64(iterator.Value())
|
id := types.BytesToUint64(iterator.Value())
|
||||||
denom := string(iterator.Key())
|
collateralType := string(iterator.Key())
|
||||||
if cb(denom, id) {
|
if cb(collateralType, id) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllClaimPeriodIDPairs returns all denom:nextClaimPeriodID pairs in the store
|
// GetAllClaimPeriodIDPairs returns all collateralType:nextClaimPeriodID pairs in the store
|
||||||
func (k Keeper) GetAllClaimPeriodIDPairs(ctx sdk.Context) types.GenesisClaimPeriodIDs {
|
func (k Keeper) GetAllClaimPeriodIDPairs(ctx sdk.Context) types.GenesisClaimPeriodIDs {
|
||||||
ids := types.GenesisClaimPeriodIDs{}
|
ids := types.GenesisClaimPeriodIDs{}
|
||||||
k.IterateClaimPeriodIDKeysAndValues(ctx, func(denom string, id uint64) (stop bool) {
|
k.IterateClaimPeriodIDKeysAndValues(ctx, func(collateralType string, id uint64) (stop bool) {
|
||||||
genID := types.GenesisClaimPeriodID{
|
genID := types.GenesisClaimPeriodID{
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
||||||
ids = append(ids, genID)
|
ids = append(ids, genID)
|
||||||
return false
|
return false
|
||||||
@ -131,11 +131,11 @@ func (k Keeper) GetAllClaimPeriodIDPairs(ctx sdk.Context) types.GenesisClaimPeri
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClaimPeriod returns claim period in the store for the input ID and denom and a boolean for if it was found
|
// GetClaimPeriod returns claim period in the store for the input ID and collateral type and a boolean for if it was found
|
||||||
func (k Keeper) GetClaimPeriod(ctx sdk.Context, id uint64, denom string) (types.ClaimPeriod, bool) {
|
func (k Keeper) GetClaimPeriod(ctx sdk.Context, id uint64, collateralType string) (types.ClaimPeriod, bool) {
|
||||||
var cp types.ClaimPeriod
|
var cp types.ClaimPeriod
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
||||||
bz := store.Get(types.GetClaimPeriodPrefix(denom, id))
|
bz := store.Get(types.GetClaimPeriodPrefix(collateralType, id))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return types.ClaimPeriod{}, false
|
return types.ClaimPeriod{}, false
|
||||||
}
|
}
|
||||||
@ -143,17 +143,17 @@ func (k Keeper) GetClaimPeriod(ctx sdk.Context, id uint64, denom string) (types.
|
|||||||
return cp, true
|
return cp, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClaimPeriod sets the claim period in the store for the input ID and denom
|
// SetClaimPeriod sets the claim period in the store for the input ID and collateral type
|
||||||
func (k Keeper) SetClaimPeriod(ctx sdk.Context, cp types.ClaimPeriod) {
|
func (k Keeper) SetClaimPeriod(ctx sdk.Context, cp types.ClaimPeriod) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
||||||
bz := k.cdc.MustMarshalBinaryBare(cp)
|
bz := k.cdc.MustMarshalBinaryBare(cp)
|
||||||
store.Set(types.GetClaimPeriodPrefix(cp.Denom, cp.ID), bz)
|
store.Set(types.GetClaimPeriodPrefix(cp.CollateralType, cp.ID), bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteClaimPeriod deletes the claim period in the store for the input ID and denom
|
// DeleteClaimPeriod deletes the claim period in the store for the input ID and collateral type
|
||||||
func (k Keeper) DeleteClaimPeriod(ctx sdk.Context, id uint64, denom string) {
|
func (k Keeper) DeleteClaimPeriod(ctx sdk.Context, id uint64, collateralType string) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimPeriodKeyPrefix)
|
||||||
store.Delete(types.GetClaimPeriodPrefix(denom, id))
|
store.Delete(types.GetClaimPeriodPrefix(collateralType, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateClaimPeriods iterates over all claim period objects in the store and preforms a callback function
|
// IterateClaimPeriods iterates over all claim period objects in the store and preforms a callback function
|
||||||
@ -180,10 +180,10 @@ func (k Keeper) GetAllClaimPeriods(ctx sdk.Context) types.ClaimPeriods {
|
|||||||
return cps
|
return cps
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClaim returns the claim in the store corresponding the the input address denom and id and a boolean for if the claim was found
|
// GetClaim returns the claim in the store corresponding the the input address collateral type and id and a boolean for if the claim was found
|
||||||
func (k Keeper) GetClaim(ctx sdk.Context, addr sdk.AccAddress, denom string, id uint64) (types.Claim, bool) {
|
func (k Keeper) GetClaim(ctx sdk.Context, addr sdk.AccAddress, collateralType string, id uint64) (types.Claim, bool) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
||||||
bz := store.Get(types.GetClaimPrefix(addr, denom, id))
|
bz := store.Get(types.GetClaimPrefix(addr, collateralType, id))
|
||||||
if bz == nil {
|
if bz == nil {
|
||||||
return types.Claim{}, false
|
return types.Claim{}, false
|
||||||
}
|
}
|
||||||
@ -192,18 +192,18 @@ func (k Keeper) GetClaim(ctx sdk.Context, addr sdk.AccAddress, denom string, id
|
|||||||
return c, true
|
return c, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClaim sets the claim in the store corresponding to the input address, denom, and id
|
// SetClaim sets the claim in the store corresponding to the input address, collateral type, and id
|
||||||
func (k Keeper) SetClaim(ctx sdk.Context, c types.Claim) {
|
func (k Keeper) SetClaim(ctx sdk.Context, c types.Claim) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
||||||
bz := k.cdc.MustMarshalBinaryBare(c)
|
bz := k.cdc.MustMarshalBinaryBare(c)
|
||||||
store.Set(types.GetClaimPrefix(c.Owner, c.Denom, c.ClaimPeriodID), bz)
|
store.Set(types.GetClaimPrefix(c.Owner, c.CollateralType, c.ClaimPeriodID), bz)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteClaim deletes the claim in the store corresponding to the input address, denom, and id
|
// DeleteClaim deletes the claim in the store corresponding to the input address, collateral type, and id
|
||||||
func (k Keeper) DeleteClaim(ctx sdk.Context, owner sdk.AccAddress, denom string, id uint64) {
|
func (k Keeper) DeleteClaim(ctx sdk.Context, owner sdk.AccAddress, collateralType string, id uint64) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.ClaimKeyPrefix)
|
||||||
store.Delete(types.GetClaimPrefix(owner, denom, id))
|
store.Delete(types.GetClaimPrefix(owner, collateralType, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateClaims iterates over all claim objects in the store and preforms a callback function
|
// IterateClaims iterates over all claim objects in the store and preforms a callback function
|
||||||
|
@ -140,8 +140,8 @@ func (suite *KeeperTestSuite) TestIterateMethods() {
|
|||||||
suite.Equal(2, len(claims))
|
suite.Equal(2, len(claims))
|
||||||
|
|
||||||
var genIDs types.GenesisClaimPeriodIDs
|
var genIDs types.GenesisClaimPeriodIDs
|
||||||
suite.keeper.IterateClaimPeriodIDKeysAndValues(suite.ctx, func(denom string, id uint64) (stop bool) {
|
suite.keeper.IterateClaimPeriodIDKeysAndValues(suite.ctx, func(collateralType string, id uint64) (stop bool) {
|
||||||
genID := types.GenesisClaimPeriodID{Denom: denom, ID: id}
|
genID := types.GenesisClaimPeriodID{CollateralType: collateralType, ID: id}
|
||||||
genIDs = append(genIDs, genID)
|
genIDs = append(genIDs, genID)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
@ -13,21 +13,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// PayoutClaim sends the timelocked claim coins to the input address
|
// PayoutClaim sends the timelocked claim coins to the input address
|
||||||
func (k Keeper) PayoutClaim(ctx sdk.Context, addr sdk.AccAddress, denom string, id uint64) error {
|
func (k Keeper) PayoutClaim(ctx sdk.Context, addr sdk.AccAddress, collateralType string, id uint64) error {
|
||||||
claim, found := k.GetClaim(ctx, addr, denom, id)
|
claim, found := k.GetClaim(ctx, addr, collateralType, id)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrClaimNotFound, "id: %d, denom %s, address: %s", id, denom, addr)
|
return sdkerrors.Wrapf(types.ErrClaimNotFound, "id: %d, collateral type %s, address: %s", id, collateralType, addr)
|
||||||
}
|
}
|
||||||
claimPeriod, found := k.GetClaimPeriod(ctx, id, denom)
|
claimPeriod, found := k.GetClaimPeriod(ctx, id, collateralType)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrClaimPeriodNotFound, "id: %d, denom: %s", id, denom)
|
return sdkerrors.Wrapf(types.ErrClaimPeriodNotFound, "id: %d, collateral type: %s", id, collateralType)
|
||||||
}
|
}
|
||||||
err := k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, sdk.NewCoins(claim.Reward), int64(claimPeriod.TimeLock.Seconds()))
|
err := k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, sdk.NewCoins(claim.Reward), int64(claimPeriod.TimeLock.Seconds()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
k.DeleteClaim(ctx, addr, denom, id)
|
k.DeleteClaim(ctx, addr, collateralType, id)
|
||||||
|
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
@ -97,13 +97,13 @@ func (k Keeper) DeleteExpiredClaimsAndClaimPeriods(ctx sdk.Context) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
k.IterateClaims(ctx, func(c types.Claim) (stop bool) {
|
k.IterateClaims(ctx, func(c types.Claim) (stop bool) {
|
||||||
if !(c.Denom == cp.Denom && c.ClaimPeriodID == cp.ID) {
|
if !(c.CollateralType == cp.CollateralType && c.ClaimPeriodID == cp.ID) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
k.DeleteClaim(ctx, c.Owner, c.Denom, c.ClaimPeriodID)
|
k.DeleteClaim(ctx, c.Owner, c.CollateralType, c.ClaimPeriodID)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
k.DeleteClaimPeriod(ctx, cp.ID, cp.Denom)
|
k.DeleteClaimPeriod(ctx, cp.ID, cp.CollateralType)
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
types.EventTypeClaimPeriodExpiry,
|
types.EventTypeClaimPeriodExpiry,
|
||||||
@ -115,14 +115,14 @@ func (k Keeper) DeleteExpiredClaimsAndClaimPeriods(ctx sdk.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClaimsByAddressAndDenom returns all claims for a specific user and address and a bool for if any were found
|
// GetClaimsByAddressAndCollateralType returns all claims for a specific user and address and a bool for if any were found
|
||||||
func (k Keeper) GetClaimsByAddressAndDenom(ctx sdk.Context, addr sdk.AccAddress, denom string) (claims types.Claims, found bool) {
|
func (k Keeper) GetClaimsByAddressAndCollateralType(ctx sdk.Context, addr sdk.AccAddress, collateralType string) (claims types.Claims, found bool) {
|
||||||
found = false
|
found = false
|
||||||
k.IterateClaimPeriods(ctx, func(cp types.ClaimPeriod) (stop bool) {
|
k.IterateClaimPeriods(ctx, func(cp types.ClaimPeriod) (stop bool) {
|
||||||
if cp.Denom != denom {
|
if cp.CollateralType != collateralType {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
c, hasClaim := k.GetClaim(ctx, addr, cp.Denom, cp.ID)
|
c, hasClaim := k.GetClaim(ctx, addr, cp.CollateralType, cp.ID)
|
||||||
if !hasClaim {
|
if !hasClaim {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func queryGetClaims(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||||
}
|
}
|
||||||
claims, _ := k.GetClaimsByAddressAndDenom(ctx, requestParams.Owner, requestParams.Denom)
|
claims, _ := k.GetClaimsByAddressAndCollateralType(ctx, requestParams.Owner, requestParams.CollateralType)
|
||||||
|
|
||||||
bz, err := codec.MarshalJSONIndent(k.cdc, claims)
|
bz, err := codec.MarshalJSONIndent(k.cdc, claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -12,9 +12,9 @@ import (
|
|||||||
|
|
||||||
// HandleRewardPeriodExpiry deletes expired RewardPeriods from the store and creates a ClaimPeriod in the store for each expired RewardPeriod
|
// HandleRewardPeriodExpiry deletes expired RewardPeriods from the store and creates a ClaimPeriod in the store for each expired RewardPeriod
|
||||||
func (k Keeper) HandleRewardPeriodExpiry(ctx sdk.Context, rp types.RewardPeriod) {
|
func (k Keeper) HandleRewardPeriodExpiry(ctx sdk.Context, rp types.RewardPeriod) {
|
||||||
k.CreateUniqueClaimPeriod(ctx, rp.Denom, rp.ClaimEnd, rp.ClaimTimeLock)
|
k.CreateUniqueClaimPeriod(ctx, rp.CollateralType, rp.ClaimEnd, rp.ClaimTimeLock)
|
||||||
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.key), types.RewardPeriodKeyPrefix)
|
||||||
store.Delete([]byte(rp.Denom))
|
store.Delete([]byte(rp.CollateralType))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +36,10 @@ func (k Keeper) CreateAndDeleteRewardPeriods(ctx sdk.Context) {
|
|||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
|
|
||||||
for _, r := range params.Rewards {
|
for _, r := range params.Rewards {
|
||||||
_, found := k.GetRewardPeriod(ctx, r.Denom)
|
_, found := k.GetRewardPeriod(ctx, r.CollateralType)
|
||||||
// if governance has made a reward inactive, delete the current period
|
// if governance has made a reward inactive, delete the current period
|
||||||
if found && !r.Active {
|
if found && !r.Active {
|
||||||
k.DeleteRewardPeriod(ctx, r.Denom)
|
k.DeleteRewardPeriod(ctx, r.CollateralType)
|
||||||
}
|
}
|
||||||
// if a reward period for an active reward is not found, create one
|
// if a reward period for an active reward is not found, create one
|
||||||
if !found && r.Active {
|
if !found && r.Active {
|
||||||
@ -61,7 +61,7 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
k.IterateRewardPeriods(ctx, func(rp types.RewardPeriod) bool {
|
k.IterateRewardPeriods(ctx, func(rp types.RewardPeriod) bool {
|
||||||
expired := false
|
expired := false
|
||||||
// the total amount of usdx created with the collateral type being incentivized
|
// the total amount of usdx created with the collateral type being incentivized
|
||||||
totalPrincipal := k.cdpKeeper.GetTotalPrincipal(ctx, rp.Denom, types.PrincipalDenom)
|
totalPrincipal := k.cdpKeeper.GetTotalPrincipal(ctx, rp.CollateralType, types.PrincipalDenom)
|
||||||
// the number of seconds since last payout
|
// the number of seconds since last payout
|
||||||
timeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousBlockTime.Unix())
|
timeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousBlockTime.Unix())
|
||||||
if rp.End.Before(ctx.BlockTime()) {
|
if rp.End.Before(ctx.BlockTime()) {
|
||||||
@ -71,15 +71,15 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
|
|
||||||
// the amount of rewards to pay (rewardAmount * timeElapsed)
|
// the amount of rewards to pay (rewardAmount * timeElapsed)
|
||||||
rewardsThisPeriod := rp.Reward.Amount.Mul(timeElapsed)
|
rewardsThisPeriod := rp.Reward.Amount.Mul(timeElapsed)
|
||||||
id := k.GetNextClaimPeriodID(ctx, rp.Denom)
|
id := k.GetNextClaimPeriodID(ctx, rp.CollateralType)
|
||||||
k.cdpKeeper.IterateCdpsByDenom(ctx, rp.Denom, func(cdp cdptypes.CDP) bool {
|
k.cdpKeeper.IterateCdpsByCollateralType(ctx, rp.CollateralType, func(cdp cdptypes.CDP) bool {
|
||||||
rewardsShare := sdk.NewDecFromInt(cdp.GetTotalPrincipal().Amount).Quo(sdk.NewDecFromInt(totalPrincipal))
|
rewardsShare := sdk.NewDecFromInt(cdp.GetTotalPrincipal().Amount).Quo(sdk.NewDecFromInt(totalPrincipal))
|
||||||
// sanity check - don't create zero claims
|
// sanity check - don't create zero claims
|
||||||
if rewardsShare.IsZero() {
|
if rewardsShare.IsZero() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
rewardsEarned := rewardsShare.Mul(sdk.NewDecFromInt(rewardsThisPeriod)).RoundInt()
|
rewardsEarned := rewardsShare.Mul(sdk.NewDecFromInt(rewardsThisPeriod)).RoundInt()
|
||||||
k.AddToClaim(ctx, cdp.Owner, rp.Denom, id, sdk.NewCoin(types.GovDenom, rewardsEarned))
|
k.AddToClaim(ctx, cdp.Owner, rp.CollateralType, id, sdk.NewCoin(types.GovDenom, rewardsEarned))
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
if !expired {
|
if !expired {
|
||||||
@ -93,9 +93,9 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateUniqueClaimPeriod creates a new claim period in the store and updates the highest claim period id
|
// CreateUniqueClaimPeriod creates a new claim period in the store and updates the highest claim period id
|
||||||
func (k Keeper) CreateUniqueClaimPeriod(ctx sdk.Context, denom string, end time.Time, timeLock time.Duration) {
|
func (k Keeper) CreateUniqueClaimPeriod(ctx sdk.Context, collateralType string, end time.Time, timeLock time.Duration) {
|
||||||
id := k.GetNextClaimPeriodID(ctx, denom)
|
id := k.GetNextClaimPeriodID(ctx, collateralType)
|
||||||
claimPeriod := types.NewClaimPeriod(denom, id, end, timeLock)
|
claimPeriod := types.NewClaimPeriod(collateralType, id, end, timeLock)
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
types.EventTypeClaimPeriod,
|
types.EventTypeClaimPeriod,
|
||||||
@ -103,16 +103,16 @@ func (k Keeper) CreateUniqueClaimPeriod(ctx sdk.Context, denom string, end time.
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
k.SetClaimPeriod(ctx, claimPeriod)
|
k.SetClaimPeriod(ctx, claimPeriod)
|
||||||
k.SetNextClaimPeriodID(ctx, denom, id+1)
|
k.SetNextClaimPeriodID(ctx, collateralType, id+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddToClaim adds the amount to an existing claim or creates a new one for that amount
|
// AddToClaim adds the amount to an existing claim or creates a new one for that amount
|
||||||
func (k Keeper) AddToClaim(ctx sdk.Context, addr sdk.AccAddress, denom string, id uint64, amount sdk.Coin) {
|
func (k Keeper) AddToClaim(ctx sdk.Context, addr sdk.AccAddress, collateralType string, id uint64, amount sdk.Coin) {
|
||||||
claim, found := k.GetClaim(ctx, addr, denom, id)
|
claim, found := k.GetClaim(ctx, addr, collateralType, id)
|
||||||
if found {
|
if found {
|
||||||
claim.Reward = claim.Reward.Add(amount)
|
claim.Reward = claim.Reward.Add(amount)
|
||||||
} else {
|
} else {
|
||||||
claim = types.NewClaim(addr, amount, denom, id)
|
claim = types.NewClaim(addr, amount, collateralType, id)
|
||||||
}
|
}
|
||||||
k.SetClaim(ctx, claim)
|
k.SetClaim(ctx, claim)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ func (suite *KeeperTestSuite) TestApplyRewardsToCdps() {
|
|||||||
})
|
})
|
||||||
suite.Equal(3, len(claims))
|
suite.Equal(3, len(claims))
|
||||||
// there should be no associated claim period, because the reward period has not ended yet
|
// there should be no associated claim period, because the reward period has not ended yet
|
||||||
_, found := suite.keeper.GetClaimPeriod(suite.ctx, 1, "bnb")
|
_, found := suite.keeper.GetClaimPeriod(suite.ctx, 1, "bnb-a")
|
||||||
suite.False(found)
|
suite.False(found)
|
||||||
|
|
||||||
// move ctx to the reward period expiry and check that the claim period has been created and the next claim period id has increased
|
// move ctx to the reward period expiry and check that the claim period has been created and the next claim period id has increased
|
||||||
@ -128,9 +128,9 @@ func (suite *KeeperTestSuite) TestApplyRewardsToCdps() {
|
|||||||
// delete the old reward period amd create a new one
|
// delete the old reward period amd create a new one
|
||||||
suite.keeper.CreateAndDeleteRewardPeriods(suite.ctx)
|
suite.keeper.CreateAndDeleteRewardPeriods(suite.ctx)
|
||||||
})
|
})
|
||||||
_, found = suite.keeper.GetClaimPeriod(suite.ctx, 1, "bnb")
|
_, found = suite.keeper.GetClaimPeriod(suite.ctx, 1, "bnb-a")
|
||||||
suite.True(found)
|
suite.True(found)
|
||||||
testID := suite.keeper.GetNextClaimPeriodID(suite.ctx, "bnb")
|
testID := suite.keeper.GetNextClaimPeriodID(suite.ctx, "bnb-a")
|
||||||
suite.Equal(uint64(2), testID)
|
suite.Equal(uint64(2), testID)
|
||||||
|
|
||||||
// move the context forward by 100 periods
|
// move the context forward by 100 periods
|
||||||
@ -186,6 +186,7 @@ func (suite *KeeperTestSuite) setupCdpChain() {
|
|||||||
CollateralParams: cdp.CollateralParams{
|
CollateralParams: cdp.CollateralParams{
|
||||||
{
|
{
|
||||||
Denom: "bnb",
|
Denom: "bnb",
|
||||||
|
Type: "bnb-a",
|
||||||
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
LiquidationRatio: sdk.MustNewDecFromStr("2.0"),
|
||||||
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
DebtLimit: sdk.NewInt64Coin("usdx", 1000000000000),
|
||||||
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
StabilityFee: sdk.MustNewDecFromStr("1.000000001547125958"), // %5 apr
|
||||||
@ -213,10 +214,10 @@ func (suite *KeeperTestSuite) setupCdpChain() {
|
|||||||
}
|
}
|
||||||
incentiveGS := types.NewGenesisState(
|
incentiveGS := types.NewGenesisState(
|
||||||
types.NewParams(
|
types.NewParams(
|
||||||
true, types.Rewards{types.NewReward(true, "bnb", c("ukava", 1000000000), time.Hour*7*24, time.Hour*24*365, time.Hour*7*24)},
|
true, types.Rewards{types.NewReward(true, "bnb-a", c("ukava", 1000000000), time.Hour*7*24, time.Hour*24*365, time.Hour*7*24)},
|
||||||
),
|
),
|
||||||
types.DefaultPreviousBlockTime,
|
types.DefaultPreviousBlockTime,
|
||||||
types.RewardPeriods{types.NewRewardPeriod("bnb", ctx.BlockTime(), ctx.BlockTime().Add(time.Hour*7*24), c("ukava", 1000), ctx.BlockTime().Add(time.Hour*7*24*2), time.Hour*365*24)},
|
types.RewardPeriods{types.NewRewardPeriod("bnb-a", ctx.BlockTime(), ctx.BlockTime().Add(time.Hour*7*24), c("ukava", 1000), ctx.BlockTime().Add(time.Hour*7*24*2), time.Hour*365*24)},
|
||||||
types.ClaimPeriods{},
|
types.ClaimPeriods{},
|
||||||
types.Claims{},
|
types.Claims{},
|
||||||
types.GenesisClaimPeriodIDs{})
|
types.GenesisClaimPeriodIDs{})
|
||||||
@ -242,11 +243,11 @@ func (suite *KeeperTestSuite) setupCdpChain() {
|
|||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
// create 3 cdps
|
// create 3 cdps
|
||||||
cdpKeeper := tApp.GetCDPKeeper()
|
cdpKeeper := tApp.GetCDPKeeper()
|
||||||
err := cdpKeeper.AddCdp(suite.ctx, addrs[0], c("bnb", 10000000000), c("usdx", 10000000))
|
err := cdpKeeper.AddCdp(suite.ctx, addrs[0], c("bnb", 10000000000), c("usdx", 10000000), "bnb-a")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
err = cdpKeeper.AddCdp(suite.ctx, addrs[1], c("bnb", 100000000000), c("usdx", 100000000))
|
err = cdpKeeper.AddCdp(suite.ctx, addrs[1], c("bnb", 100000000000), c("usdx", 100000000), "bnb-a")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
err = cdpKeeper.AddCdp(suite.ctx, addrs[2], c("bnb", 1000000000000), c("usdx", 1000000000))
|
err = cdpKeeper.AddCdp(suite.ctx, addrs[2], c("bnb", 1000000000000), c("usdx", 1000000000), "bnb-a")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
// total usd is 1110
|
// total usd is 1110
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ func RandomizedGenState(simState *module.SimulationState) {
|
|||||||
simState.Cdc.MustUnmarshalJSON(simState.GenState[cdp.ModuleName], &cdpGenesis)
|
simState.Cdc.MustUnmarshalJSON(simState.GenState[cdp.ModuleName], &cdpGenesis)
|
||||||
if len(CollateralDenoms) == 0 {
|
if len(CollateralDenoms) == 0 {
|
||||||
for _, collateral := range cdpGenesis.Params.CollateralParams {
|
for _, collateral := range cdpGenesis.Params.CollateralParams {
|
||||||
CollateralDenoms = append(CollateralDenoms, collateral.Denom)
|
CollateralDenoms = append(CollateralDenoms, collateral.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +88,11 @@ func genRewardPeriods(r *rand.Rand, timestamp time.Time, rewards types.Rewards)
|
|||||||
end := start.Add(reward.Duration).UTC()
|
end := start.Add(reward.Duration).UTC()
|
||||||
baseRewardAmount := reward.AvailableRewards.Amount.Quo(sdk.NewInt(100)) // base period reward is 1/100 total reward
|
baseRewardAmount := reward.AvailableRewards.Amount.Quo(sdk.NewInt(100)) // base period reward is 1/100 total reward
|
||||||
// Earlier periods have larger rewards
|
// Earlier periods have larger rewards
|
||||||
amount := sdk.NewCoin(reward.Denom, baseRewardAmount.Mul(sdk.NewInt(int64(i))))
|
amount := sdk.NewCoin("ukava", baseRewardAmount.Mul(sdk.NewInt(int64(i))))
|
||||||
claimEnd := end.Add(reward.ClaimDuration)
|
claimEnd := end.Add(reward.ClaimDuration)
|
||||||
claimTimeLock := reward.TimeLock
|
claimTimeLock := reward.TimeLock
|
||||||
// Create reward period and append to array
|
// Create reward period and append to array
|
||||||
rewardPeriods[i] = types.NewRewardPeriod(reward.Denom, start, end, amount, claimEnd, claimTimeLock)
|
rewardPeriods[i] = types.NewRewardPeriod(reward.CollateralType, start, end, amount, claimEnd, claimTimeLock)
|
||||||
// Update start time of next reward period
|
// Update start time of next reward period
|
||||||
rewardPeriodStart = end
|
rewardPeriodStart = end
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ func genClaimPeriods(rewardPeriods types.RewardPeriods) types.ClaimPeriods {
|
|||||||
claimPeriods := make(types.ClaimPeriods, len(rewardPeriods))
|
claimPeriods := make(types.ClaimPeriods, len(rewardPeriods))
|
||||||
for i, rewardPeriod := range rewardPeriods {
|
for i, rewardPeriod := range rewardPeriods {
|
||||||
// Increment reward period count for this denom (this is our claim period's ID)
|
// Increment reward period count for this denom (this is our claim period's ID)
|
||||||
denom := rewardPeriod.Denom
|
denom := rewardPeriod.CollateralType
|
||||||
numbRewardPeriods := denomRewardPeriodsCount[denom] + 1
|
numbRewardPeriods := denomRewardPeriodsCount[denom] + 1
|
||||||
denomRewardPeriodsCount[denom] = numbRewardPeriods
|
denomRewardPeriodsCount[denom] = numbRewardPeriods
|
||||||
// Set end and timelock from the associated reward period
|
// Set end and timelock from the associated reward period
|
||||||
@ -123,11 +123,11 @@ func genNextClaimPeriodIds(cps types.ClaimPeriods) types.GenesisClaimPeriodIDs {
|
|||||||
mostRecentClaimPeriodByDenom := make(map[string]uint64)
|
mostRecentClaimPeriodByDenom := make(map[string]uint64)
|
||||||
var claimPeriodIDs types.GenesisClaimPeriodIDs
|
var claimPeriodIDs types.GenesisClaimPeriodIDs
|
||||||
for _, cp := range cps {
|
for _, cp := range cps {
|
||||||
if cp.ID <= mostRecentClaimPeriodByDenom[cp.Denom] {
|
if cp.ID <= mostRecentClaimPeriodByDenom[cp.CollateralType] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
claimPeriodIDs = append(claimPeriodIDs, types.GenesisClaimPeriodID{Denom: cp.Denom, ID: cp.ID})
|
claimPeriodIDs = append(claimPeriodIDs, types.GenesisClaimPeriodID{CollateralType: cp.CollateralType, ID: cp.ID})
|
||||||
mostRecentClaimPeriodByDenom[cp.Denom] = cp.ID
|
mostRecentClaimPeriodByDenom[cp.CollateralType] = cp.ID
|
||||||
|
|
||||||
}
|
}
|
||||||
return claimPeriodIDs
|
return claimPeriodIDs
|
||||||
|
@ -78,7 +78,7 @@ func SimulateMsgClaimReward(ak auth.AccountKeeper, sk types.SupplyKeeper, k keep
|
|||||||
claimer, claim, found := findValidAccountClaimPair(accs, openClaims, func(acc simulation.Account, claim types.Claim) bool {
|
claimer, claim, found := findValidAccountClaimPair(accs, openClaims, func(acc simulation.Account, claim types.Claim) bool {
|
||||||
if validAccounts[acc.Address.String()] { // Address must be valid type
|
if validAccounts[acc.Address.String()] { // Address must be valid type
|
||||||
if claim.Owner.Equals(acc.Address) { // Account must be claim owner
|
if claim.Owner.Equals(acc.Address) { // Account must be claim owner
|
||||||
allClaims, found := k.GetClaimsByAddressAndDenom(ctx, claim.Owner, claim.Denom)
|
allClaims, found := k.GetClaimsByAddressAndCollateralType(ctx, claim.Owner, claim.CollateralType)
|
||||||
if found { // found should always be true
|
if found { // found should always be true
|
||||||
var rewards sdk.Coins
|
var rewards sdk.Coins
|
||||||
for _, individualClaim := range allClaims {
|
for _, individualClaim := range allClaims {
|
||||||
@ -105,7 +105,7 @@ func SimulateMsgClaimReward(ak auth.AccountKeeper, sk types.SupplyKeeper, k keep
|
|||||||
return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("couldn't find account %s", claimer.Address)
|
return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("couldn't find account %s", claimer.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := types.NewMsgClaimReward(claimer.Address, claim.Denom)
|
msg := types.NewMsgClaimReward(claimer.Address, claim.CollateralType)
|
||||||
|
|
||||||
tx := helpers.GenTx(
|
tx := helpers.GenTx(
|
||||||
[]sdk.Msg{msg},
|
[]sdk.Msg{msg},
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
// DONTCOVER
|
// DONTCOVER
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrClaimNotFound = sdkerrors.Register(ModuleName, 1, "no claim with input id found for owner and denom")
|
ErrClaimNotFound = sdkerrors.Register(ModuleName, 1, "no claim with input id found for owner and collateral type")
|
||||||
ErrClaimPeriodNotFound = sdkerrors.Register(ModuleName, 2, "no claim period found for id and denom")
|
ErrClaimPeriodNotFound = sdkerrors.Register(ModuleName, 2, "no claim period found for id and collateral type")
|
||||||
ErrInvalidAccountType = sdkerrors.Register(ModuleName, 3, "account type not supported")
|
ErrInvalidAccountType = sdkerrors.Register(ModuleName, 3, "account type not supported")
|
||||||
ErrNoClaimsFound = sdkerrors.Register(ModuleName, 4, "no claims with denom found for address")
|
ErrNoClaimsFound = sdkerrors.Register(ModuleName, 4, "no claims with collateral type found for address")
|
||||||
ErrInsufficientModAccountBalance = sdkerrors.Register(ModuleName, 5, "module account has insufficient balance to pay claim")
|
ErrInsufficientModAccountBalance = sdkerrors.Register(ModuleName, 5, "module account has insufficient balance to pay claim")
|
||||||
)
|
)
|
||||||
|
@ -17,8 +17,8 @@ type SupplyKeeper interface {
|
|||||||
|
|
||||||
// CdpKeeper defines the expected cdp keeper for interacting with cdps
|
// CdpKeeper defines the expected cdp keeper for interacting with cdps
|
||||||
type CdpKeeper interface {
|
type CdpKeeper interface {
|
||||||
IterateCdpsByDenom(ctx sdk.Context, denom string, cb func(cdp cdptypes.CDP) (stop bool))
|
IterateCdpsByCollateralType(ctx sdk.Context, collateralType string, cb func(cdp cdptypes.CDP) (stop bool))
|
||||||
GetTotalPrincipal(ctx sdk.Context, collateralDenom string, principalDenom string) (total sdk.Int)
|
GetTotalPrincipal(ctx sdk.Context, collateralType string, principalDenom string) (total sdk.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountKeeper defines the expected keeper interface for interacting with account
|
// AccountKeeper defines the expected keeper interface for interacting with account
|
||||||
|
@ -4,15 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenesisClaimPeriodID stores the next claim id and its corresponding denom
|
// GenesisClaimPeriodID stores the next claim id and its corresponding collateral type
|
||||||
type GenesisClaimPeriodID struct {
|
type GenesisClaimPeriodID struct {
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
ID uint64 `json:"id" yaml:"id"`
|
ID uint64 `json:"id" yaml:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs a basic check of a GenesisClaimPeriodID fields.
|
// Validate performs a basic check of a GenesisClaimPeriodID fields.
|
||||||
@ -20,7 +19,10 @@ func (gcp GenesisClaimPeriodID) Validate() error {
|
|||||||
if gcp.ID == 0 {
|
if gcp.ID == 0 {
|
||||||
return errors.New("genesis claim period id cannot be 0")
|
return errors.New("genesis claim period id cannot be 0")
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(gcp.Denom)
|
if strings.TrimSpace(gcp.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be blank: %v", gcp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenesisClaimPeriodIDs array of GenesisClaimPeriodID
|
// GenesisClaimPeriodIDs array of GenesisClaimPeriodID
|
||||||
@ -32,9 +34,9 @@ func (gcps GenesisClaimPeriodIDs) Validate() error {
|
|||||||
seenIDS := make(map[string]bool)
|
seenIDS := make(map[string]bool)
|
||||||
var key string
|
var key string
|
||||||
for _, gcp := range gcps {
|
for _, gcp := range gcps {
|
||||||
key = gcp.Denom + string(gcp.ID)
|
key = gcp.CollateralType + string(gcp.ID)
|
||||||
if seenIDS[key] {
|
if seenIDS[key] {
|
||||||
return fmt.Errorf("duplicated genesis claim period with id %d and denom %s", gcp.ID, gcp.Denom)
|
return fmt.Errorf("duplicated genesis claim period with id %d and collateral type %s", gcp.ID, gcp.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gcp.Validate(); err != nil {
|
if err := gcp.Validate(); err != nil {
|
||||||
|
@ -20,29 +20,29 @@ func TestGenesisClaimPeriodIDsValidate(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"valid",
|
"valid",
|
||||||
GenesisClaimPeriodIDs{
|
GenesisClaimPeriodIDs{
|
||||||
{Denom: "bnb", ID: 1},
|
{CollateralType: "bnb", ID: 1},
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid denom",
|
"invalid collateral type",
|
||||||
GenesisClaimPeriodIDs{
|
GenesisClaimPeriodIDs{
|
||||||
{Denom: "", ID: 1},
|
{CollateralType: "", ID: 1},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid ID",
|
"invalid ID",
|
||||||
GenesisClaimPeriodIDs{
|
GenesisClaimPeriodIDs{
|
||||||
{Denom: "bnb", ID: 0},
|
{CollateralType: "bnb", ID: 0},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"duplicate",
|
"duplicate",
|
||||||
GenesisClaimPeriodIDs{
|
GenesisClaimPeriodIDs{
|
||||||
{Denom: "bnb", ID: 1},
|
{CollateralType: "bnb", ID: 1},
|
||||||
{Denom: "bnb", ID: 1},
|
{CollateralType: "bnb", ID: 1},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@ -74,7 +74,7 @@ func TestGenesisStateValidate(t *testing.T) {
|
|||||||
rewardPeriods := RewardPeriods{NewRewardPeriod("bnb", now, now.Add(time.Hour), sdk.NewCoin("bnb", sdk.OneInt()), now, 10)}
|
rewardPeriods := RewardPeriods{NewRewardPeriod("bnb", now, now.Add(time.Hour), sdk.NewCoin("bnb", sdk.OneInt()), now, 10)}
|
||||||
claimPeriods := ClaimPeriods{NewClaimPeriod("bnb", 10, now, 100)}
|
claimPeriods := ClaimPeriods{NewClaimPeriod("bnb", 10, now, 100)}
|
||||||
claims := Claims{NewClaim(owner, sdk.NewCoin("bnb", sdk.OneInt()), "bnb", 10)}
|
claims := Claims{NewClaim(owner, sdk.NewCoin("bnb", sdk.OneInt()), "bnb", 10)}
|
||||||
gcps := GenesisClaimPeriodIDs{{Denom: "bnb", ID: 1}}
|
gcps := GenesisClaimPeriodIDs{{CollateralType: "bnb", ID: 1}}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
msg string
|
msg string
|
||||||
|
@ -33,24 +33,24 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Keys
|
// Keys
|
||||||
// 0x00:Denom <> RewardPeriod the current active reward period (max 1 reward period per denom)
|
// 0x00:CollateralType <> RewardPeriod the current active reward period (max 1 reward period per collateral type)
|
||||||
// 0x01:Denom:ID <> ClaimPeriod object for that ID, indexed by denom and ID
|
// 0x01:CollateralType:ID <> ClaimPeriod object for that ID, indexed by collateral type and ID
|
||||||
// 0x02:Denom:ID:Owner <> Claim object, indexed by Denom, ID and owner
|
// 0x02:CollateralType:ID:Owner <> Claim object, indexed by collateral type, ID and owner
|
||||||
// 0x03:Denom <> NextClaimPeriodIDPrefix the ID of the next claim period, indexed by denom
|
// 0x03:CollateralType <> NextClaimPeriodIDPrefix the ID of the next claim period, indexed by collateral type
|
||||||
|
|
||||||
// BytesToUint64 returns uint64 format from a byte array
|
// BytesToUint64 returns uint64 format from a byte array
|
||||||
func BytesToUint64(bz []byte) uint64 {
|
func BytesToUint64(bz []byte) uint64 {
|
||||||
return binary.BigEndian.Uint64(bz)
|
return binary.BigEndian.Uint64(bz)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClaimPeriodPrefix returns the key (denom + id) for a claim prefix
|
// GetClaimPeriodPrefix returns the key (collateral type + id) for a claim prefix
|
||||||
func GetClaimPeriodPrefix(denom string, id uint64) []byte {
|
func GetClaimPeriodPrefix(collateralType string, id uint64) []byte {
|
||||||
return createKey([]byte(denom), sdk.Uint64ToBigEndian(id))
|
return createKey([]byte(collateralType), sdk.Uint64ToBigEndian(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClaimPrefix returns the key (denom + id + address) for a claim
|
// GetClaimPrefix returns the key (collateral type + id + address) for a claim
|
||||||
func GetClaimPrefix(addr sdk.AccAddress, denom string, id uint64) []byte {
|
func GetClaimPrefix(addr sdk.AccAddress, collateralType string, id uint64) []byte {
|
||||||
return createKey([]byte(denom), sdk.Uint64ToBigEndian(id), addr)
|
return createKey([]byte(collateralType), sdk.Uint64ToBigEndian(id), addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createKey(bytes ...[]byte) (r []byte) {
|
func createKey(bytes ...[]byte) (r []byte) {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
)
|
)
|
||||||
@ -10,15 +13,15 @@ var _ sdk.Msg = &MsgClaimReward{}
|
|||||||
|
|
||||||
// MsgClaimReward message type used to claim rewards
|
// MsgClaimReward message type used to claim rewards
|
||||||
type MsgClaimReward struct {
|
type MsgClaimReward struct {
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgClaimReward returns a new MsgClaimReward.
|
// NewMsgClaimReward returns a new MsgClaimReward.
|
||||||
func NewMsgClaimReward(sender sdk.AccAddress, denom string) MsgClaimReward {
|
func NewMsgClaimReward(sender sdk.AccAddress, collateralType string) MsgClaimReward {
|
||||||
return MsgClaimReward{
|
return MsgClaimReward{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +36,10 @@ func (msg MsgClaimReward) ValidateBasic() error {
|
|||||||
if msg.Sender.Empty() {
|
if msg.Sender.Empty() {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty")
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(msg.Denom)
|
if strings.TrimSpace(msg.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be blank")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSignBytes gets the canonical byte representation of the Msg.
|
// GetSignBytes gets the canonical byte representation of the Msg.
|
||||||
|
@ -13,9 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type msgTest struct {
|
type msgTest struct {
|
||||||
from sdk.AccAddress
|
from sdk.AccAddress
|
||||||
denom string
|
collateralType string
|
||||||
expectPass bool
|
expectPass bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type MsgTestSuite struct {
|
type MsgTestSuite struct {
|
||||||
@ -27,19 +27,19 @@ type MsgTestSuite struct {
|
|||||||
func (suite *MsgTestSuite) SetupTest() {
|
func (suite *MsgTestSuite) SetupTest() {
|
||||||
tests := []msgTest{
|
tests := []msgTest{
|
||||||
{
|
{
|
||||||
from: sdk.AccAddress(crypto.AddressHash([]byte("KavaTest1"))),
|
from: sdk.AccAddress(crypto.AddressHash([]byte("KavaTest1"))),
|
||||||
denom: "bnb",
|
collateralType: "bnb",
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: sdk.AccAddress(crypto.AddressHash([]byte("KavaTest1"))),
|
from: sdk.AccAddress(crypto.AddressHash([]byte("KavaTest1"))),
|
||||||
denom: "",
|
collateralType: "",
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: sdk.AccAddress{},
|
from: sdk.AccAddress{},
|
||||||
denom: "bnb",
|
collateralType: "bnb",
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
suite.tests = tests
|
suite.tests = tests
|
||||||
@ -47,7 +47,7 @@ func (suite *MsgTestSuite) SetupTest() {
|
|||||||
|
|
||||||
func (suite *MsgTestSuite) TestMsgValidation() {
|
func (suite *MsgTestSuite) TestMsgValidation() {
|
||||||
for _, t := range suite.tests {
|
for _, t := range suite.tests {
|
||||||
msg := types.NewMsgClaimReward(t.from, t.denom)
|
msg := types.NewMsgClaimReward(t.from, t.collateralType)
|
||||||
err := msg.ValidateBasic()
|
err := msg.ValidateBasic()
|
||||||
if t.expectPass {
|
if t.expectPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
@ -2,6 +2,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -93,7 +94,7 @@ func validateRewardsParam(i interface{}) error {
|
|||||||
// Reward stores the specified state for a single reward period.
|
// Reward stores the specified state for a single reward period.
|
||||||
type Reward struct {
|
type Reward struct {
|
||||||
Active bool `json:"active" yaml:"active"` // governance switch to disable a period
|
Active bool `json:"active" yaml:"active"` // governance switch to disable a period
|
||||||
Denom string `json:"denom" yaml:"denom"` // the collateral denom rewards apply to, must be found in the cdp collaterals
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"` // the collateral type rewards apply to, must be found in the cdp collaterals
|
||||||
AvailableRewards sdk.Coin `json:"available_rewards" yaml:"available_rewards"` // the total amount of coins distributed per period
|
AvailableRewards sdk.Coin `json:"available_rewards" yaml:"available_rewards"` // the total amount of coins distributed per period
|
||||||
Duration time.Duration `json:"duration" yaml:"duration"` // the duration of the period
|
Duration time.Duration `json:"duration" yaml:"duration"` // the duration of the period
|
||||||
TimeLock time.Duration `json:"time_lock" yaml:"time_lock"` // how long rewards for this period are timelocked
|
TimeLock time.Duration `json:"time_lock" yaml:"time_lock"` // how long rewards for this period are timelocked
|
||||||
@ -101,10 +102,10 @@ type Reward struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewReward returns a new Reward
|
// NewReward returns a new Reward
|
||||||
func NewReward(active bool, denom string, reward sdk.Coin, duration time.Duration, timelock time.Duration, claimDuration time.Duration) Reward {
|
func NewReward(active bool, collateralType string, reward sdk.Coin, duration time.Duration, timelock time.Duration, claimDuration time.Duration) Reward {
|
||||||
return Reward{
|
return Reward{
|
||||||
Active: active,
|
Active: active,
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
AvailableRewards: reward,
|
AvailableRewards: reward,
|
||||||
Duration: duration,
|
Duration: duration,
|
||||||
TimeLock: timelock,
|
TimeLock: timelock,
|
||||||
@ -116,32 +117,35 @@ func NewReward(active bool, denom string, reward sdk.Coin, duration time.Duratio
|
|||||||
func (r Reward) String() string {
|
func (r Reward) String() string {
|
||||||
return fmt.Sprintf(`Reward:
|
return fmt.Sprintf(`Reward:
|
||||||
Active: %t,
|
Active: %t,
|
||||||
Denom: %s,
|
CollateralType: %s,
|
||||||
Available Rewards: %s,
|
Available Rewards: %s,
|
||||||
Duration: %s,
|
Duration: %s,
|
||||||
Time Lock: %s,
|
Time Lock: %s,
|
||||||
Claim Duration: %s`,
|
Claim Duration: %s`,
|
||||||
r.Active, r.Denom, r.AvailableRewards, r.Duration, r.TimeLock, r.ClaimDuration)
|
r.Active, r.CollateralType, r.AvailableRewards, r.Duration, r.TimeLock, r.ClaimDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs a basic check of a reward fields.
|
// Validate performs a basic check of a reward fields.
|
||||||
func (r Reward) Validate() error {
|
func (r Reward) Validate() error {
|
||||||
if !r.AvailableRewards.IsValid() {
|
if !r.AvailableRewards.IsValid() {
|
||||||
return fmt.Errorf("invalid reward coins %s for %s", r.AvailableRewards, r.Denom)
|
return fmt.Errorf("invalid reward coins %s for %s", r.AvailableRewards, r.CollateralType)
|
||||||
}
|
}
|
||||||
if !r.AvailableRewards.IsPositive() {
|
if !r.AvailableRewards.IsPositive() {
|
||||||
return fmt.Errorf("reward amount must be positive, is %s for %s", r.AvailableRewards, r.Denom)
|
return fmt.Errorf("reward amount must be positive, is %s for %s", r.AvailableRewards, r.CollateralType)
|
||||||
}
|
}
|
||||||
if r.Duration <= 0 {
|
if r.Duration <= 0 {
|
||||||
return fmt.Errorf("reward duration must be positive, is %s for %s", r.Duration, r.Denom)
|
return fmt.Errorf("reward duration must be positive, is %s for %s", r.Duration, r.CollateralType)
|
||||||
}
|
}
|
||||||
if r.TimeLock < 0 {
|
if r.TimeLock < 0 {
|
||||||
return fmt.Errorf("reward timelock must be non-negative, is %s for %s", r.TimeLock, r.Denom)
|
return fmt.Errorf("reward timelock must be non-negative, is %s for %s", r.TimeLock, r.CollateralType)
|
||||||
}
|
}
|
||||||
if r.ClaimDuration <= 0 {
|
if r.ClaimDuration <= 0 {
|
||||||
return fmt.Errorf("claim duration must be positive, is %s for %s", r.ClaimDuration, r.Denom)
|
return fmt.Errorf("claim duration must be positive, is %s for %s", r.ClaimDuration, r.CollateralType)
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(r.Denom)
|
if strings.TrimSpace(r.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("collateral type cannot be blank: %s", r)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewards array of Reward
|
// Rewards array of Reward
|
||||||
@ -150,17 +154,17 @@ type Rewards []Reward
|
|||||||
// Validate checks if all the rewards are valid and there are no duplicated
|
// Validate checks if all the rewards are valid and there are no duplicated
|
||||||
// entries.
|
// entries.
|
||||||
func (rs Rewards) Validate() error {
|
func (rs Rewards) Validate() error {
|
||||||
rewardDenoms := make(map[string]bool)
|
rewardCollateralTypes := make(map[string]bool)
|
||||||
for _, r := range rs {
|
for _, r := range rs {
|
||||||
if rewardDenoms[r.Denom] {
|
if rewardCollateralTypes[r.CollateralType] {
|
||||||
return fmt.Errorf("cannot have duplicate reward denoms: %s", r.Denom)
|
return fmt.Errorf("cannot have duplicate reward collateral types: %s", r.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Validate(); err != nil {
|
if err := r.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
rewardDenoms[r.Denom] = true
|
rewardCollateralTypes[r.CollateralType] = true
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -58,7 +58,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -78,7 +78,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -86,7 +86,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
},
|
},
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -96,7 +96,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
},
|
},
|
||||||
errResult: errResult{
|
errResult: errResult{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "cannot have duplicate reward denoms",
|
contains: "cannot have duplicate reward collateral type",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * -24 * 7,
|
Duration: time.Hour * -24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -126,7 +126,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * -8766,
|
TimeLock: time.Hour * -8766,
|
||||||
@ -146,7 +146,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(10000000000)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -166,7 +166,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "bnb",
|
CollateralType: "bnb-a",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(0)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(0)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -180,13 +180,13 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty reward denom",
|
name: "empty reward collateral type",
|
||||||
params: types.Params{
|
params: types.Params{
|
||||||
Active: true,
|
Active: true,
|
||||||
Rewards: types.Rewards{
|
Rewards: types.Rewards{
|
||||||
types.Reward{
|
types.Reward{
|
||||||
Active: true,
|
Active: true,
|
||||||
Denom: "",
|
CollateralType: "",
|
||||||
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(1)),
|
AvailableRewards: sdk.NewCoin("ukava", sdk.NewInt(1)),
|
||||||
Duration: time.Hour * 24 * 7,
|
Duration: time.Hour * 24 * 7,
|
||||||
TimeLock: time.Hour * 8766,
|
TimeLock: time.Hour * 8766,
|
||||||
@ -196,7 +196,7 @@ func (suite *ParamTestSuite) SetupTest() {
|
|||||||
},
|
},
|
||||||
errResult: errResult{
|
errResult: errResult{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
contains: "invalid denom",
|
contains: "collateral type cannot be blank",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,31 +7,31 @@ import (
|
|||||||
|
|
||||||
// Querier routes for the incentive module
|
// Querier routes for the incentive module
|
||||||
const (
|
const (
|
||||||
QueryGetClaims = "claims"
|
QueryGetClaims = "claims"
|
||||||
RestClaimOwner = "owner"
|
RestClaimOwner = "owner"
|
||||||
RestClaimDenom = "denom"
|
RestClaimCollateralType = "collateral_type"
|
||||||
QueryGetParams = "parameters"
|
QueryGetParams = "parameters"
|
||||||
QueryGetRewardPeriods = "reward-periods"
|
QueryGetRewardPeriods = "reward-periods"
|
||||||
QueryGetClaimPeriods = "claim-periods"
|
QueryGetClaimPeriods = "claim-periods"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QueryClaimsParams params for query /incentive/claims
|
// QueryClaimsParams params for query /incentive/claims
|
||||||
type QueryClaimsParams struct {
|
type QueryClaimsParams struct {
|
||||||
Owner sdk.AccAddress
|
Owner sdk.AccAddress
|
||||||
Denom string
|
CollateralType string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueryClaimsParams returns QueryClaimsParams
|
// NewQueryClaimsParams returns QueryClaimsParams
|
||||||
func NewQueryClaimsParams(owner sdk.AccAddress, denom string) QueryClaimsParams {
|
func NewQueryClaimsParams(owner sdk.AccAddress, collateralType string) QueryClaimsParams {
|
||||||
return QueryClaimsParams{
|
return QueryClaimsParams{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostClaimReq defines the properties of claim transaction's request body.
|
// PostClaimReq defines the properties of claim transaction's request body.
|
||||||
type PostClaimReq struct {
|
type PostClaimReq struct {
|
||||||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
|
||||||
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package types
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -10,35 +11,35 @@ import (
|
|||||||
|
|
||||||
// RewardPeriod stores the state of an ongoing reward
|
// RewardPeriod stores the state of an ongoing reward
|
||||||
type RewardPeriod struct {
|
type RewardPeriod struct {
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
Start time.Time `json:"start" yaml:"start"`
|
Start time.Time `json:"start" yaml:"start"`
|
||||||
End time.Time `json:"end" yaml:"end"`
|
End time.Time `json:"end" yaml:"end"`
|
||||||
Reward sdk.Coin `json:"reward" yaml:"reward"` // per second reward payouts
|
Reward sdk.Coin `json:"reward" yaml:"reward"` // per second reward payouts
|
||||||
ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"`
|
ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"`
|
||||||
ClaimTimeLock time.Duration `json:"claim_time_lock" yaml:"claim_time_lock"` // the amount of time rewards are timelocked once they are sent to users
|
ClaimTimeLock time.Duration `json:"claim_time_lock" yaml:"claim_time_lock"` // the amount of time rewards are timelocked once they are sent to users
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
func (rp RewardPeriod) String() string {
|
func (rp RewardPeriod) String() string {
|
||||||
return fmt.Sprintf(`Reward Period:
|
return fmt.Sprintf(`Reward Period:
|
||||||
Denom: %s,
|
Collateral Type: %s,
|
||||||
Start: %s,
|
Start: %s,
|
||||||
End: %s,
|
End: %s,
|
||||||
Reward: %s,
|
Reward: %s,
|
||||||
Claim End: %s,
|
Claim End: %s,
|
||||||
Claim Time Lock: %s
|
Claim Time Lock: %s
|
||||||
`, rp.Denom, rp.Start, rp.End, rp.Reward, rp.ClaimEnd, rp.ClaimTimeLock)
|
`, rp.CollateralType, rp.Start, rp.End, rp.Reward, rp.ClaimEnd, rp.ClaimTimeLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRewardPeriod returns a new RewardPeriod
|
// NewRewardPeriod returns a new RewardPeriod
|
||||||
func NewRewardPeriod(denom string, start time.Time, end time.Time, reward sdk.Coin, claimEnd time.Time, claimTimeLock time.Duration) RewardPeriod {
|
func NewRewardPeriod(collateralType string, start time.Time, end time.Time, reward sdk.Coin, claimEnd time.Time, claimTimeLock time.Duration) RewardPeriod {
|
||||||
return RewardPeriod{
|
return RewardPeriod{
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: end,
|
End: end,
|
||||||
Reward: reward,
|
Reward: reward,
|
||||||
ClaimEnd: claimEnd,
|
ClaimEnd: claimEnd,
|
||||||
ClaimTimeLock: claimTimeLock,
|
ClaimTimeLock: claimTimeLock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +63,10 @@ func (rp RewardPeriod) Validate() error {
|
|||||||
if rp.ClaimTimeLock == 0 {
|
if rp.ClaimTimeLock == 0 {
|
||||||
return errors.New("reward claim time lock cannot be 0")
|
return errors.New("reward claim time lock cannot be 0")
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(rp.Denom)
|
if strings.TrimSpace(rp.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("reward period collateral type cannot be blank: %s", rp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RewardPeriods array of RewardPeriod
|
// RewardPeriods array of RewardPeriod
|
||||||
@ -73,14 +77,14 @@ type RewardPeriods []RewardPeriod
|
|||||||
func (rps RewardPeriods) Validate() error {
|
func (rps RewardPeriods) Validate() error {
|
||||||
seenPeriods := make(map[string]bool)
|
seenPeriods := make(map[string]bool)
|
||||||
for _, rp := range rps {
|
for _, rp := range rps {
|
||||||
if seenPeriods[rp.Denom] {
|
if seenPeriods[rp.CollateralType] {
|
||||||
return fmt.Errorf("duplicated reward period with denom %s", rp.Denom)
|
return fmt.Errorf("duplicated reward period with collateral type %s", rp.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rp.Validate(); err != nil {
|
if err := rp.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
seenPeriods[rp.Denom] = true
|
seenPeriods[rp.CollateralType] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -88,19 +92,19 @@ func (rps RewardPeriods) Validate() error {
|
|||||||
|
|
||||||
// ClaimPeriod stores the state of an ongoing claim period
|
// ClaimPeriod stores the state of an ongoing claim period
|
||||||
type ClaimPeriod struct {
|
type ClaimPeriod struct {
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
ID uint64 `json:"id" yaml:"id"`
|
ID uint64 `json:"id" yaml:"id"`
|
||||||
End time.Time `json:"end" yaml:"end"`
|
End time.Time `json:"end" yaml:"end"`
|
||||||
TimeLock time.Duration `json:"time_lock" yaml:"time_lock"`
|
TimeLock time.Duration `json:"time_lock" yaml:"time_lock"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClaimPeriod returns a new ClaimPeriod
|
// NewClaimPeriod returns a new ClaimPeriod
|
||||||
func NewClaimPeriod(denom string, id uint64, end time.Time, timeLock time.Duration) ClaimPeriod {
|
func NewClaimPeriod(collateralType string, id uint64, end time.Time, timeLock time.Duration) ClaimPeriod {
|
||||||
return ClaimPeriod{
|
return ClaimPeriod{
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
ID: id,
|
ID: id,
|
||||||
End: end,
|
End: end,
|
||||||
TimeLock: timeLock,
|
TimeLock: timeLock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,17 +119,20 @@ func (cp ClaimPeriod) Validate() error {
|
|||||||
if cp.TimeLock == 0 {
|
if cp.TimeLock == 0 {
|
||||||
return errors.New("claim period time lock cannot be 0")
|
return errors.New("claim period time lock cannot be 0")
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(cp.Denom)
|
if strings.TrimSpace(cp.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("claim period collateral type cannot be blank: %s", cp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
func (cp ClaimPeriod) String() string {
|
func (cp ClaimPeriod) String() string {
|
||||||
return fmt.Sprintf(`Claim Period:
|
return fmt.Sprintf(`Claim Period:
|
||||||
Denom: %s,
|
Collateral Type: %s,
|
||||||
ID: %d,
|
ID: %d,
|
||||||
End: %s,
|
End: %s,
|
||||||
Claim Time Lock: %s
|
Claim Time Lock: %s
|
||||||
`, cp.Denom, cp.ID, cp.End, cp.TimeLock)
|
`, cp.CollateralType, cp.ID, cp.End, cp.TimeLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClaimPeriods array of ClaimPeriod
|
// ClaimPeriods array of ClaimPeriod
|
||||||
@ -137,9 +144,9 @@ func (cps ClaimPeriods) Validate() error {
|
|||||||
seenPeriods := make(map[string]bool)
|
seenPeriods := make(map[string]bool)
|
||||||
var key string
|
var key string
|
||||||
for _, cp := range cps {
|
for _, cp := range cps {
|
||||||
key = cp.Denom + string(cp.ID)
|
key = cp.CollateralType + string(cp.ID)
|
||||||
if seenPeriods[key] {
|
if seenPeriods[key] {
|
||||||
return fmt.Errorf("duplicated claim period with id %d and denom %s", cp.ID, cp.Denom)
|
return fmt.Errorf("duplicated claim period with id %d and collateral type %s", cp.ID, cp.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cp.Validate(); err != nil {
|
if err := cp.Validate(); err != nil {
|
||||||
@ -153,19 +160,19 @@ func (cps ClaimPeriods) Validate() error {
|
|||||||
|
|
||||||
// Claim stores the rewards that can be claimed by owner
|
// Claim stores the rewards that can be claimed by owner
|
||||||
type Claim struct {
|
type Claim struct {
|
||||||
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
|
||||||
Reward sdk.Coin `json:"reward" yaml:"reward"`
|
Reward sdk.Coin `json:"reward" yaml:"reward"`
|
||||||
Denom string `json:"denom" yaml:"denom"`
|
CollateralType string `json:"collateral_type" yaml:"collateral_type"`
|
||||||
ClaimPeriodID uint64 `json:"claim_period_id" yaml:"claim_period_id"`
|
ClaimPeriodID uint64 `json:"claim_period_id" yaml:"claim_period_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClaim returns a new Claim
|
// NewClaim returns a new Claim
|
||||||
func NewClaim(owner sdk.AccAddress, reward sdk.Coin, denom string, claimPeriodID uint64) Claim {
|
func NewClaim(owner sdk.AccAddress, reward sdk.Coin, collateralType string, claimPeriodID uint64) Claim {
|
||||||
return Claim{
|
return Claim{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Reward: reward,
|
Reward: reward,
|
||||||
Denom: denom,
|
CollateralType: collateralType,
|
||||||
ClaimPeriodID: claimPeriodID,
|
ClaimPeriodID: claimPeriodID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,17 +187,20 @@ func (c Claim) Validate() error {
|
|||||||
if c.ClaimPeriodID == 0 {
|
if c.ClaimPeriodID == 0 {
|
||||||
return errors.New("claim period id cannot be 0")
|
return errors.New("claim period id cannot be 0")
|
||||||
}
|
}
|
||||||
return sdk.ValidateDenom(c.Denom)
|
if strings.TrimSpace(c.CollateralType) == "" {
|
||||||
|
return fmt.Errorf("claim collateral type cannot be blank: %s", c)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer
|
// String implements fmt.Stringer
|
||||||
func (c Claim) String() string {
|
func (c Claim) String() string {
|
||||||
return fmt.Sprintf(`Claim:
|
return fmt.Sprintf(`Claim:
|
||||||
Owner: %s,
|
Owner: %s,
|
||||||
Denom: %s,
|
Collateral Type: %s,
|
||||||
Reward: %s,
|
Reward: %s,
|
||||||
Claim Period ID: %d,
|
Claim Period ID: %d,
|
||||||
`, c.Owner, c.Denom, c.Reward, c.ClaimPeriodID)
|
`, c.Owner, c.CollateralType, c.Reward, c.ClaimPeriodID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claims array of Claim
|
// Claims array of Claim
|
||||||
@ -202,9 +212,9 @@ func (cs Claims) Validate() error {
|
|||||||
seemClaims := make(map[string]bool)
|
seemClaims := make(map[string]bool)
|
||||||
var key string
|
var key string
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
key = c.Denom + string(c.ClaimPeriodID) + c.Owner.String()
|
key = c.CollateralType + string(c.ClaimPeriodID) + c.Owner.String()
|
||||||
if c.Owner != nil && seemClaims[key] {
|
if c.Owner != nil && seemClaims[key] {
|
||||||
return fmt.Errorf("duplicated claim from owner %s and denom %s", c.Owner, c.Denom)
|
return fmt.Errorf("duplicated claim from owner %s and collateral type %s", c.Owner, c.CollateralType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Validate(); err != nil {
|
if err := c.Validate(); err != nil {
|
||||||
@ -222,11 +232,11 @@ func NewRewardPeriodFromReward(reward Reward, blockTime time.Time) RewardPeriod
|
|||||||
rewardsPerSecond := sdk.NewDecFromInt(reward.AvailableRewards.Amount).Quo(sdk.NewDecFromInt(sdk.NewInt(int64(reward.Duration.Seconds())))).TruncateInt()
|
rewardsPerSecond := sdk.NewDecFromInt(reward.AvailableRewards.Amount).Quo(sdk.NewDecFromInt(sdk.NewInt(int64(reward.Duration.Seconds())))).TruncateInt()
|
||||||
rewardCoinPerSecond := sdk.NewCoin(reward.AvailableRewards.Denom, rewardsPerSecond)
|
rewardCoinPerSecond := sdk.NewCoin(reward.AvailableRewards.Denom, rewardsPerSecond)
|
||||||
return RewardPeriod{
|
return RewardPeriod{
|
||||||
Denom: reward.Denom,
|
CollateralType: reward.CollateralType,
|
||||||
Start: blockTime,
|
Start: blockTime,
|
||||||
End: blockTime.Add(reward.Duration),
|
End: blockTime.Add(reward.Duration),
|
||||||
Reward: rewardCoinPerSecond,
|
Reward: rewardCoinPerSecond,
|
||||||
ClaimEnd: blockTime.Add(reward.Duration).Add(reward.ClaimDuration),
|
ClaimEnd: blockTime.Add(reward.Duration).Add(reward.ClaimDuration),
|
||||||
ClaimTimeLock: reward.TimeLock,
|
ClaimTimeLock: reward.TimeLock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,15 +93,15 @@ func TestRewardPeriodsValidate(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid denom",
|
"invalid collateral type",
|
||||||
RewardPeriods{
|
RewardPeriods{
|
||||||
{
|
{
|
||||||
Start: now,
|
Start: now,
|
||||||
End: now.Add(time.Hour),
|
End: now.Add(time.Hour),
|
||||||
Reward: sdk.NewCoin("bnb", sdk.OneInt()),
|
Reward: sdk.NewCoin("bnb", sdk.OneInt()),
|
||||||
ClaimEnd: now,
|
ClaimEnd: now,
|
||||||
ClaimTimeLock: 10,
|
ClaimTimeLock: 10,
|
||||||
Denom: "",
|
CollateralType: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@ -170,9 +170,9 @@ func TestClaimPeriodsValidate(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid denom",
|
"invalid collateral type",
|
||||||
ClaimPeriods{
|
ClaimPeriods{
|
||||||
{ID: 10, End: now, TimeLock: 100, Denom: ""},
|
{ID: 10, End: now, TimeLock: 100, CollateralType: ""},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@ -243,13 +243,13 @@ func TestClaimsValidate(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid denom",
|
"invalid collateral type",
|
||||||
Claims{
|
Claims{
|
||||||
{
|
{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Reward: sdk.NewCoin("bnb", sdk.OneInt()),
|
Reward: sdk.NewCoin("bnb", sdk.OneInt()),
|
||||||
ClaimPeriodID: 10,
|
ClaimPeriodID: 10,
|
||||||
Denom: "",
|
CollateralType: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
Loading…
Reference in New Issue
Block a user