update spec, add money market deprecation steps (#841)

This commit is contained in:
Denali Marsh 2021-02-22 21:52:17 +01:00 committed by GitHub
parent 1499a89ce5
commit 99fb79a1ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 112 additions and 129 deletions

View File

@ -4,7 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
// BeginBlocker updates interest rates and attempts liquidations // BeginBlocker updates interest rates
func BeginBlocker(ctx sdk.Context, k Keeper) { func BeginBlocker(ctx sdk.Context, k Keeper) {
k.ApplyInterestRateUpdates(ctx) k.ApplyInterestRateUpdates(ctx)
} }

View File

@ -8,38 +8,33 @@ import (
) )
const ( const (
AttributeKeyBlockHeight = types.AttributeKeyBlockHeight AttributeKeyBorrow = types.AttributeKeyBorrow
AttributeKeyBorrow = types.AttributeKeyBorrow AttributeKeyBorrowCoins = types.AttributeKeyBorrowCoins
AttributeKeyBorrowCoins = types.AttributeKeyBorrowCoins AttributeKeyBorrower = types.AttributeKeyBorrower
AttributeKeyBorrower = types.AttributeKeyBorrower AttributeKeyDeposit = types.AttributeKeyDeposit
AttributeKeyDeposit = types.AttributeKeyDeposit AttributeKeyDepositCoins = types.AttributeKeyDepositCoins
AttributeKeyDepositCoins = types.AttributeKeyDepositCoins AttributeKeyDepositDenom = types.AttributeKeyDepositDenom
AttributeKeyDepositDenom = types.AttributeKeyDepositDenom AttributeKeyDepositor = types.AttributeKeyDepositor
AttributeKeyDepositor = types.AttributeKeyDepositor AttributeKeyRepayCoins = types.AttributeKeyRepayCoins
AttributeKeyRepayCoins = types.AttributeKeyRepayCoins AttributeKeySender = types.AttributeKeySender
AttributeKeyRewardsDistribution = types.AttributeKeyRewardsDistribution AttributeValueCategory = types.AttributeValueCategory
AttributeKeySender = types.AttributeKeySender DefaultParamspace = types.DefaultParamspace
AttributeValueCategory = types.AttributeValueCategory EventTypeHardLiquidation = types.EventTypeHardLiquidation
DefaultParamspace = types.DefaultParamspace EventTypeHardBorrow = types.EventTypeHardBorrow
EventTypeDeleteHardDeposit = types.EventTypeDeleteHardDeposit EventTypeHardDeposit = types.EventTypeHardDeposit
EventTypeHardLiquidation = types.EventTypeHardLiquidation EventTypeHardRepay = types.EventTypeHardRepay
EventTypeHardBorrow = types.EventTypeHardBorrow EventTypeHardWithdrawal = types.EventTypeHardWithdrawal
EventTypeHardDelegatorDistribution = types.EventTypeHardDelegatorDistribution ModuleAccountName = types.ModuleAccountName
EventTypeHardDeposit = types.EventTypeHardDeposit ModuleName = types.ModuleName
EventTypeHardLPDistribution = types.EventTypeHardLPDistribution QuerierRoute = types.QuerierRoute
EventTypeHardRepay = types.EventTypeHardRepay QueryGetBorrows = types.QueryGetBorrows
EventTypeHardWithdrawal = types.EventTypeHardWithdrawal QueryGetDeposits = types.QueryGetDeposits
ModuleAccountName = types.ModuleAccountName QueryGetModuleAccounts = types.QueryGetModuleAccounts
ModuleName = types.ModuleName QueryGetParams = types.QueryGetParams
QuerierRoute = types.QuerierRoute QueryGetTotalBorrowed = types.QueryGetTotalBorrowed
QueryGetBorrows = types.QueryGetBorrows QueryGetTotalDeposited = types.QueryGetTotalDeposited
QueryGetDeposits = types.QueryGetDeposits RouterKey = types.RouterKey
QueryGetModuleAccounts = types.QueryGetModuleAccounts StoreKey = types.StoreKey
QueryGetParams = types.QueryGetParams
QueryGetTotalBorrowed = types.QueryGetTotalBorrowed
QueryGetTotalDeposited = types.QueryGetTotalDeposited
RouterKey = types.RouterKey
StoreKey = types.StoreKey
) )
var ( var (

View File

@ -6,9 +6,8 @@ order: 1
## Automated, Cross-Chain Money Markets ## Automated, Cross-Chain Money Markets
The hard module provides for functionality and governance of a two-sided money market protocol with autonomous interest rates and partially autonomous liquidations. The main state transitions in the hard module are composed of deposit, withdraw, borrow and repay actions. Additionally, borrow positions can be liquidated by the autonomous liquidation engine or by an external party called a "keeper". Keepers receive a fee in exchange for liquidating risk positions, and the fee rate is determined by governance. Internally, all funds are stored in a module account (the cosmos-sdk equivalent of the `address` portion of a smart contract), and can be accessed via the above actions. Each money market has governance parameters which are controlled by token-holder governance. Of particular note are the interest rate model, which determines (using a static formula) what the prevailing rate of interest will be for each block, and the loan-to-value (LTV), which determines how much borrowing power each unit of deposited collateral will count for. Initial parameterization of the hard module will stipulate that all markets are over-collateralized and that overall borrow limits for each collateral will start small and rise gradually. The hard module provides for functionality and governance of a two-sided money market protocol with autonomous interest rates. The main state transitions in the hard module are composed of deposit, withdraw, borrow and repay actions. Borrow positions can be liquidated by an external party called a "keeper". Keepers receive a fee in exchange for liquidating risk positions, and the fee rate is determined by governance. Internally, all funds are stored in a module account (the cosmos-sdk equivalent of the `address` portion of a smart contract), and can be accessed via the above actions. Each money market has governance parameters which are controlled by token-holder governance. Of particular note are the interest rate model, which determines (using a static formula) what the prevailing rate of interest will be for each block, and the loan-to-value (LTV), which determines how much borrowing power each unit of deposited collateral will count for. Initial parameterization of the hard module will stipulate that all markets are over-collateralized and that overall borrow limits for each collateral will start small and rise gradually.
## HARD Token distribution ## HARD Token distribution
[See Incentive Module](../../incentive/spec/01_concepts.md) [See Incentive Module](../../incentive/spec/01_concepts.md)

View File

@ -6,13 +6,19 @@ order: 2
## Parameters and Genesis State ## Parameters and Genesis State
`Parameters` define the governance parameters and default behavior of each money market. `Parameters` define the governance parameters and default behavior of each money market. **Money markets should not be removed from params without careful procedures** as it will disable withdraws and liquidations. To deprecate a money market, the following steps should be observed:
1. Borrowing: prevent new borrows by setting param MoneyMarket.BorrowLimit.MaximumLimit to 0.
2. Interest: turn off interest accumulation by setting params MoneyMarket.InterestRateModel.BaseRateAPY and MoneyMarket.InterestRateModel.Kink to 0.
3. Rewards: turn off supply side and/or borrow side rewards by removing any coins in the relevant RewardsPerSecond param in the Incentive module.
Without financial incentives, borrowers and suppliers will withdraw their funds from the money market over time. Once the balances have reached an acceptable level the money market can be deprecated and removed from params, with any additional lingering user funds reimbursed/reallocated as appropriate via a chain upgrade.
```go ```go
// Params governance parameters for hard module // Params governance parameters for hard module
type Params struct { type Params struct {
MoneyMarkets MoneyMarkets `json:"money_markets" yaml:"money_markets"` // defines the parameters for each money market MoneyMarkets MoneyMarkets `json:"money_markets" yaml:"money_markets"`
CheckLtvIndexCount int `json:"check_ltv_index_count" yaml:"check_ltv_index_count"` // defines the number of positions that are checked for liquidation at the beginning of each block MinimumBorrowUSDValue sdk.Dec `json:"minimum_borrow_usd_value" yaml:"minimum_borrow_usd_value"`
} }
// MoneyMarket is a money market for an individual asset // MoneyMarket is a money market for an individual asset
@ -23,7 +29,6 @@ type MoneyMarket struct {
ConversionFactor sdk.Int `json:"conversion_factor" yaml:"conversion_factor"` //the internal conversion factor for going from the smallest unit of a token to a whole unit (ie. 8 for BTC, 6 for KAVA, 18 for ETH) ConversionFactor sdk.Int `json:"conversion_factor" yaml:"conversion_factor"` //the internal conversion factor for going from the smallest unit of a token to a whole unit (ie. 8 for BTC, 6 for KAVA, 18 for ETH)
InterestRateModel InterestRateModel `json:"interest_rate_model" yaml:"interest_rate_model"` // the model that determines the prevailing interest rate at each block InterestRateModel InterestRateModel `json:"interest_rate_model" yaml:"interest_rate_model"` // the model that determines the prevailing interest rate at each block
ReserveFactor sdk.Dec `json:"reserve_factor" yaml:"reserve_factor"` // the percentage of interest that is accumulated by the protocol as reserves ReserveFactor sdk.Dec `json:"reserve_factor" yaml:"reserve_factor"` // the percentage of interest that is accumulated by the protocol as reserves
AuctionSize sdk.Int `json:"auction_size" yaml:"auction_size"` // the maximum size of auction for this money market. Liquidations larger than this will be broken down into multiple auctions
KeeperRewardPercentage sdk.Dec `json:"keeper_reward_percentage" yaml:"keeper_reward_percentages"` // the percentage of a liquidation that is given to the keeper that liquidated the position KeeperRewardPercentage sdk.Dec `json:"keeper_reward_percentage" yaml:"keeper_reward_percentages"` // the percentage of a liquidation that is given to the keeper that liquidated the position
} }

View File

@ -39,12 +39,13 @@ This message creates a `Borrow` object is one does not exist, or updates an exis
```go ```go
// MsgRepay repays funds to the hard module. // MsgRepay repays funds to the hard module.
type MsgRepay struct { type MsgRepay struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"` Sender sdk.AccAddress `json:"sender" yaml:"sender"`
Amount sdk.Coins `json:"amount" yaml:"amount"` Owner sdk.AccAddress `json:"owner" yaml:"owner"`
Amount sdk.Coins `json:"amount" yaml:"amount"`
} }
``` ```
This message decrements a `Borrow` object, or deletes one if the `Amount` specified is greater than or equal to the total borrowed amount, as well as creating/updating the necessary indexes and synchronizing any outstanding interest. For example, a message which requests to repay 100xyz tokens, if `Sender` has only deposited 50xyz tokens, will repay the full 50xyz tokens. The `Amount` of coins, or the current borrow amount, is transferred from `Sender`. The global variable for `TotalBorrowed` is updated. This message decrements a `Borrow` object, or deletes one if the `Amount` specified is greater than or equal to the total borrowed amount, as well as creating/updating the necessary indexes and synchronizing any outstanding interest. For example, a message which requests to repay 100xyz tokens, if `Owner` has only deposited 50xyz tokens, the `Sender` will repay the full 50xyz tokens. The `Amount` of coins, or the current borrow amount, is transferred from `Sender`. The global variable for `TotalBorrowed` is updated.
```go ```go
// MsgLiquidate attempts to liquidate a borrower's borrow // MsgLiquidate attempts to liquidate a borrower's borrow
@ -54,4 +55,4 @@ type MsgLiquidate struct {
} }
``` ```
This message deletes `Borrower's` `Deposit` and `Borrow` objects if they are below the required LTV ratio. The keeper (the sender of the message) is rewarded a portion of the borrow position, according to the `KeeperReward` governance parameter. The coins from the `Deposit` are then sold at auction (see [auction module](../../auction/spec/README.md)), which any remaining tokens returned to `Borrower`. After being liquidated, `Borrower` no longer must repay the borrow amount. The global variables for `TotalSupplied` and `TotalBorrowed` are updated. This message deletes `Borrower's` `Deposit` and `Borrow` objects if they are below the required LTV ratio. The keeper (the sender of the message) is rewarded a portion of the borrow position, according to the `KeeperReward` governance parameter. The coins from the `Deposit` are then sold at auction (see [auction module](../../auction/spec/README.md)), which any remaining tokens returned to `Borrower`. After being liquidated, `Borrower` no longer must repay the borrow amount. The global variables for `TotalSupplied` and `TotalBorrowed` are updated.

View File

@ -19,38 +19,28 @@ The hard module emits the following events:
### MsgWithdraw ### MsgWithdraw
| Type | Attribute Key | Attribute Value | | Type | Attribute Key | Attribute Value |
| ------------------- | ------------- | --------------------- | | --------------- | ------------- | --------------------- |
| message | module | hard | | message | module | hard |
| message | sender | `{sender address}` | | message | sender | `{sender address}` |
| hard_withdrawal | amount | `{amount}` | | hard_withdrawal | amount | `{amount}` |
| hard_withdrawal | depositor | `{depositor address}` | | hard_withdrawal | depositor | `{depositor address}` |
### MsgBorrow ### MsgBorrow
| Type | Attribute Key | Attribute Value | | Type | Attribute Key | Attribute Value |
| -------------- | ------------- | --------------------- | | --------------- | ------------- | -------------------- |
| message | module | hard | | message | module | hard |
| message | sender | `{sender address}` | | message | sender | `{sender address}` |
| hard_borrow | borrow_coins | `{amount}` | | hard_borrow | borrow_coins | `{amount}` |
| hard_withdrawal| borrower | `{borrower address}` | | hard_withdrawal | borrower | `{borrower address}` |
### MsgRepay ### MsgRepay
| Type | Attribute Key | Attribute Value | | Type | Attribute Key | Attribute Value |
| -------------- | ------------- | --------------------- | | ---------- | ------------- | -------------------- |
| message | module | hard | | message | module | hard |
| message | sender | `{sender address}` | | message | sender | `{sender address}` |
| hard_repay | repay_coins | `{amount}` | | message | owner | `{owner address}` |
| hard_repay | sender | `{borrower address}` | | hard_repay | repay_coins | `{amount}` |
| hard_repay | sender | `{borrower address}` |
## BeginBlock
| Type | Attribute Key | Attribute Value |
| --------------------------- | ------------------- | ----------------------- |
| hard_lp_distribution | block_height | `{block height}` |
| hard_lp_distribution | rewards_distributed | `{rewards distributed}` |
| hard_lp_distribution | deposit_denom | `{deposit denom}` |
| hard_delegator_distribution | block_height | `{block height}` |
| hard_delegator_distribution | rewards_distributed | `{rewards distributed}` |
| hard_delegator_distribution | deposit_denom | `{deposit denom}` |

View File

@ -4,39 +4,38 @@ order: 5
# Parameters # Parameters
The hard module has the following parameters: Example parameters for the Hard module:
| Key | Type | Example | Description | | Key | Type | Example | Description |
| ------------------------------ | ------------------------------------- | ------------- | ----------------------------------------------------------------------------| | --------------------- | ------------------- | ------------- | -------------------------------------------- |
| MoneyMarkets | array (MoneyMarket) | [{see below}] | array of params for each supported market | | MoneyMarkets | array (MoneyMarket) | [{see below}] | Array of params for each supported market |
| CheckLtvIndexCount | int | 6 | Number of borrow positions to check for liquidation in each begin blocker | | MinimumBorrowUSDValue | sdk.Dec | 10.0 | Minimum amount an individual user can borrow |
Each `MoneyMarket` has the following parameters Example parameters for `MoneyMarket`:
| Key | Type | Example | Description | | Key | Type | Example | Description |
| ------------------------- | ------------------ | ---------------------- | --------------------------------------------------------------------- | | ---------------------- | ----------------- | ------------- | --------------------------------------------------------------------- |
| Denom | string | "bnb" | coin denom of the asset which can be deposited and borrowed | | Denom | string | "bnb" | Coin denom of the asset which can be deposited and borrowed |
| BorrowLimit | BorrowLimit | [{see below}] | borrow limits applied to this money market | | BorrowLimit | BorrowLimit | [{see below}] | Borrow limits applied to this money market |
| SpotMarketID | string | "bnb:usd" | the market id which determines the price of the asset | | SpotMarketID | string | "bnb:usd" | The market id which determines the price of the asset |
| ConversionFactor | Int | "6" | conversion factor for one unit (ie BNB) to the smallest internal unit | | ConversionFactor | Int | "6" | Conversion factor for one unit (ie BNB) to the smallest internal unit |
| InterestRateModel | InterestRateModel | [{see below}] | Model which determines the prevailing interest rate per block | | InterestRateModel | InterestRateModel | [{see below}] | Model which determines the prevailing interest rate per block |
| ReserveFactor | Dec | "0.01" | Percentage of interest that is kept as protocol reserves | | ReserveFactor | Dec | "0.01" | Percentage of interest that is kept as protocol reserves |
| AuctionSize | Int | "1000000000" | The maximum size of an individual auction | | KeeperRewardPercentage | Dec | "0.02" | Percentage of deposit rewarded to keeper who liquidates a position |
| KeeperRewardPercentage | Dec | "0.02" | Percentage of deposit rewarded to keeper who liquidates a position |
Each `BorrowLimit` has the following parameters Example parameters for `BorrowLimit`:
| Key | Type | Example | Description | | Key | Type | Example | Description |
| --------------------- | ------------------ | ---------------------- | ------------------------------------------------------------------------ | | ------------ | ---- | ------------ | ----------------------------------------------------------------------- |
| HasMaxLimit | bool | "true" | boolean for if a maximum limit is in effect | | HasMaxLimit | bool | "true" | Boolean for if a maximum limit is in effect |
| MaximumLimit | Dec | "10000000.0" | global maximum amount of coins that can be borrowed | | MaximumLimit | Dec | "10000000.0" | Global maximum amount of coins that can be borrowed |
| LoanToValue | Dec | "0.5" | the percentage amount of borrow power each unit of deposit accounts for | | LoanToValue | Dec | "0.5" | The percentage amount of borrow power each unit of deposit accounts for |
Each `InterestRateModel` has the following parameters Example parameters for `InterestRateModel`:
| Key | Type | Example | Description | | Key | Type | Example | Description |
| ---------------- | ------ | ------- | ---------------------------------------------------------------------------------------------------------------- | | -------------- | ---- | ------- | --------------------------------------------------------------------------------------------------------------- |
| BaseRateAPY | Dec | "0.0" | the base rate of APY interest when borrows are zero. | | BaseRateAPY | Dec | "0.0" | The base rate of APY interest when borrows are zero |
| BaseMultiplier | Dec | "0.01" | the percentage rate at which the interest rate APY increases for each percentage increase in borrow utilization. | | BaseMultiplier | Dec | "0.01" | The percentage rate at which the interest rate APY increases for each percentage increase in borrow utilization |
| Kink | Dec | "0.5" | the inflection point of utilization at which the BaseMultiplier no longer applies and the JumpMultiplier does. | | Kink | Dec | "0.5" | The inflection point of utilization at which the BaseMultiplier no longer applies and the JumpMultiplier does |
| JumpMultiplier | Dec | "0.5" | same as BaseMultiplier, but only applied when utilization is above the Kink | | JumpMultiplier | Dec | "0.5" | Same as BaseMultiplier, but only applied when utilization is above the Kink |

View File

@ -4,12 +4,11 @@ order: 6
# Begin Block # Begin Block
At the start of each block, interest is accumulated, and automated liquidations are attempted At the start of each block interest is accumulated
```go ```go
// BeginBlocker updates interest rates and attempts liquidations // BeginBlocker updates interest rates
func BeginBlocker(ctx sdk.Context, k Keeper) { func BeginBlocker(ctx sdk.Context, k Keeper) {
k.ApplyInterestRateUpdates(ctx) k.ApplyInterestRateUpdates(ctx)
k.AttemptIndexLiquidations(ctx)
} }
``` ```

View File

@ -2,29 +2,24 @@ package types
// Event types for hard module // Event types for hard module
const ( const (
EventTypeHardDeposit = "hard_deposit" EventTypeHardDeposit = "hard_deposit"
EventTypeHardDelegatorDistribution = "hard_delegator_distribution" EventTypeHardWithdrawal = "hard_withdrawal"
EventTypeHardLPDistribution = "hard_lp_distribution" EventTypeHardBorrow = "hard_borrow"
EventTypeDeleteHardDeposit = "delete_hard_deposit" EventTypeHardLiquidation = "hard_liquidation"
EventTypeHardWithdrawal = "hard_withdrawal" EventTypeHardRepay = "hard_repay"
EventTypeHardBorrow = "hard_borrow" AttributeValueCategory = ModuleName
EventTypeHardLiquidation = "hard_liquidation" AttributeKeyDeposit = "deposit"
EventTypeHardRepay = "hard_repay" AttributeKeyDepositDenom = "deposit_denom"
AttributeValueCategory = ModuleName AttributeKeyDepositCoins = "deposit_coins"
AttributeKeyBlockHeight = "block_height" AttributeKeyDepositor = "depositor"
AttributeKeyRewardsDistribution = "rewards_distributed" AttributeKeyBorrow = "borrow"
AttributeKeyDeposit = "deposit" AttributeKeyBorrower = "borrower"
AttributeKeyDepositDenom = "deposit_denom" AttributeKeyBorrowCoins = "borrow_coins"
AttributeKeyDepositCoins = "deposit_coins" AttributeKeySender = "sender"
AttributeKeyDepositor = "depositor" AttributeKeyRepayCoins = "repay_coins"
AttributeKeyBorrow = "borrow" AttributeKeyLiquidatedOwner = "liquidated_owner"
AttributeKeyBorrower = "borrower" AttributeKeyLiquidatedCoins = "liquidated_coins"
AttributeKeyBorrowCoins = "borrow_coins" AttributeKeyKeeper = "keeper"
AttributeKeySender = "sender" AttributeKeyKeeperRewardCoins = "keeper_reward_coins"
AttributeKeyRepayCoins = "repay_coins" AttributeKeyOwner = "owner"
AttributeKeyLiquidatedOwner = "liquidated_owner"
AttributeKeyLiquidatedCoins = "liquidated_coins"
AttributeKeyKeeper = "keeper"
AttributeKeyKeeperRewardCoins = "keeper_reward_coins"
AttributeKeyOwner = "owner"
) )