Skip to content

Commit

Permalink
Merge branch 'main' into zarazan/abci-test
Browse files Browse the repository at this point in the history
  • Loading branch information
zarazan authored Jan 19, 2023
2 parents 51acc06 + 13c2a19 commit 2ec415a
Show file tree
Hide file tree
Showing 20 changed files with 354 additions and 550 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
- [1685](https://github.com/umee-network/umee/pull/1685) Add medians param to Token registry.
- [1683](https://github.com/umee-network/umee/pull/1683) Add MaxBorrow query and allow returning all denoms from MaxWithdraw.
- [1690](https://github.com/umee-network/umee/pull/1690) Add MaxBorrow message type.
- [1711](https://github.com/umee-network/umee/pull/1711) Add historic pricing information to leverage MarketSummary and AccountSummary queries.
- [1715](https://github.com/umee-network/umee/pull/1715) Add spot borrow limit to AccountSummary query, and switch returned borrow limit to the minimum of spot and historic borrow limits.
- [1711](https://github.com/umee-network/umee/pull/1711) Add historic pricing information to leverage MarketSummary query
- [1715](https://github.com/umee-network/umee/pull/1715) Reverted.
- [1723](https://github.com/umee-network/umee/pull/1723) Compute borrow limits using the lower of either spot or historic price for each collateral token, and the higher of said prices for borrowed tokens. Remove extra spot/historic only fields in account summary.

## [v3.3.0](https://github.com/umee-network/umee/releases/tag/v3.3.0) - 2022-12-20

Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ lint:
@echo "--> Running linter with revive"
@go install github.com/mgechev/revive
@revive -config .revive.toml -formatter friendly ./...
# note: on new OSX, might require brew install diffutils
@echo "--> Running regular linter"
@go install mvdan.cc/gofumpt
@go install github.com/golangci/golangci-lint/cmd/golangci-lint
@$(golangci_lint_cmd) run
@cd price-feeder && $(golangci_lint_cmd) run

lint-fix:
@echo "--> Running linter to fix the lint issues"
Expand Down
20 changes: 1 addition & 19 deletions proto/umee/leverage/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ message QueryAccountSummaryResponse {
(gogoproto.nullable) = false
];
// Borrow Limit is the maximum Borrowed Value the account is allowed to reach through direct borrowing.
// It uses the lower of two borrow limits: spot_borrow_limit and historic_borrow_limit.
// The lower of spot or historic price for each collateral token is used when calculating borrow limits.
string borrow_limit = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
Expand All @@ -247,24 +247,6 @@ message QueryAccountSummaryResponse {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// Historic Borrowed Value is the sum of the USD value of all tokens the account has borrowed,
// including interest owed, using historic prices.
string historic_borrowed_value = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// Historic Borrow Limit is the maximum Borrowed Value the account is allowed to reach through direct borrowing,
// using historic prices.
string historic_borrow_limit = 7 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// Spot Borrow Limit is the maximum Borrowed Value the account is allowed to reach through direct borrowing,
// using spot prices.
string spot_borrow_limit = 8 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// QueryLiquidationTargets defines the request structure for the LiquidationTargets gRPC service handler.
Expand Down
50 changes: 4 additions & 46 deletions swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,34 +150,13 @@ paths:
Borrow Limit is the maximum Borrowed Value the account is
allowed to reach through direct borrowing.
It uses the lower of two borrow limits: spot_borrow_limit and
historic_borrow_limit.
The lower of spot or historic price for each collateral token
is used when calculating borrow limits.
liquidation_threshold:
type: string
description: >-
Liquidation Threshold is the Borrowed Value at which the
account becomes eligible for liquidation.
historic_borrowed_value:
type: string
description: >-
Historic Borrowed Value is the sum of the USD value of all
tokens the account has borrowed,
including interest owed, using historic prices.
historic_borrow_limit:
type: string
description: >-
Historic Borrow Limit is the maximum Borrowed Value the
account is allowed to reach through direct borrowing,
using historic prices.
spot_borrow_limit:
type: string
description: >-
Spot Borrow Limit is the maximum Borrowed Value the account is
allowed to reach through direct borrowing,
using spot prices.
description: >-
QueryAccountSummaryResponse defines the response structure for the
AccountSummary gRPC service handler.
Expand Down Expand Up @@ -2056,34 +2035,13 @@ definitions:
Borrow Limit is the maximum Borrowed Value the account is allowed to
reach through direct borrowing.
It uses the lower of two borrow limits: spot_borrow_limit and
historic_borrow_limit.
The lower of spot or historic price for each collateral token is used
when calculating borrow limits.
liquidation_threshold:
type: string
description: >-
Liquidation Threshold is the Borrowed Value at which the account
becomes eligible for liquidation.
historic_borrowed_value:
type: string
description: >-
Historic Borrowed Value is the sum of the USD value of all tokens the
account has borrowed,
including interest owed, using historic prices.
historic_borrow_limit:
type: string
description: >-
Historic Borrow Limit is the maximum Borrowed Value the account is
allowed to reach through direct borrowing,
using historic prices.
spot_borrow_limit:
type: string
description: >-
Spot Borrow Limit is the maximum Borrowed Value the account is allowed
to reach through direct borrowing,
using spot prices.
description: >-
QueryAccountSummaryResponse defines the response structure for the
AccountSummary gRPC service handler.
Expand Down
6 changes: 0 additions & 6 deletions x/leverage/client/tests/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,6 @@ func (s *IntegrationTestSuite) TestLeverageScenario() {
BorrowedValue: sdk.MustNewDecFromStr("0.00858671"),
// (1001 / 1000000) * 34.21 * 0.25 = 0.0085610525
BorrowLimit: sdk.MustNewDecFromStr("0.0085610525"),
// (251 / 1000000) * 34.21 = 0.00858671
HistoricBorrowedValue: sdk.MustNewDecFromStr("0.00858671"),
// (1001 / 1000000) * 34.21 * 0.25 = 0.0085610525
HistoricBorrowLimit: sdk.MustNewDecFromStr("0.0085610525"),
// (1001 / 1000000) * 34.21 * 0.25 = 0.0085610525
SpotBorrowLimit: sdk.MustNewDecFromStr("0.0085610525"),
// (1001 / 1000000) * 0.25 * 34.21 = 0.0085610525
LiquidationThreshold: sdk.MustNewDecFromStr("0.0085610525"),
},
Expand Down
40 changes: 11 additions & 29 deletions x/leverage/keeper/borrows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,25 @@ import (
)

// assertBorrowerHealth returns an error if a borrower is currently above their borrow limit,
// under either recent (historic median) or current prices. It returns an error if current
// prices cannot be calculated, but will use current prices (without returning an error)
// for any token whose historic prices cannot be calculated.
// under either recent (historic median) or current prices. It returns an error if
// prices cannot be calculated.
// This should be checked in msg_server.go at the end of any transaction which is restricted
// by borrow limits, i.e. Borrow, Decollateralize, Withdraw, MaxWithdraw.
func (k Keeper) assertBorrowerHealth(ctx sdk.Context, borrowerAddr sdk.AccAddress) error {
borrowed := k.GetBorrowerBorrows(ctx, borrowerAddr)
collateral := k.GetBorrowerCollateral(ctx, borrowerAddr)

// Check using current prices
err := k.checkPositionHealth(ctx, borrowed, collateral, false)
value, err := k.TotalTokenValue(ctx, borrowed, types.PriceModeHigh)
if err != nil {
return err
}

// Check using historic prices
return k.checkPositionHealth(ctx, borrowed, collateral, true)
}

// checkPositionHealth returns an error if a borrow + collateral position is not healthy. uses either
// current or historic prices.
func (k Keeper) checkPositionHealth(ctx sdk.Context, borrowed, collateral sdk.Coins, historic bool) error {
value, err := k.TotalTokenValue(ctx, borrowed, historic)
if err != nil {
return err
}
limit, err := k.CalculateBorrowLimit(ctx, collateral, historic)
limit, err := k.CalculateBorrowLimit(ctx, collateral)
if err != nil {
return err
}
if value.GT(limit) {
desc := "current"
if historic {
desc = "historic"
}
return types.ErrUndercollaterized.Wrapf(
"borrowed: %s, limit: %s (%s prices)", value, limit, desc)
"borrowed: %s, limit: %s", value, limit)
}
return nil
}
Expand Down Expand Up @@ -113,9 +95,9 @@ func (k Keeper) SupplyUtilization(ctx sdk.Context, denom string) sdk.Dec {

// CalculateBorrowLimit uses the price oracle to determine the borrow limit (in USD) provided by
// collateral sdk.Coins, using each token's uToken exchange rate and collateral weight.
// The lower of spot price or historic price is used for each collateral token.
// An error is returned if any input coins are not uTokens or if value calculation fails.
// If the historic parameter is true, uses medians of recent prices instead of current prices.
func (k Keeper) CalculateBorrowLimit(ctx sdk.Context, collateral sdk.Coins, historic bool) (sdk.Dec, error) {
func (k Keeper) CalculateBorrowLimit(ctx sdk.Context, collateral sdk.Coins) (sdk.Dec, error) {
limit := sdk.ZeroDec()

for _, coin := range collateral {
Expand All @@ -132,8 +114,8 @@ func (k Keeper) CalculateBorrowLimit(ctx sdk.Context, collateral sdk.Coins, hist

// ignore blacklisted tokens
if !ts.Blacklist {
// get USD value of base assets
v, err := k.TokenValue(ctx, baseAsset, historic)
// get USD value of base assets using the chosen price mode
v, err := k.TokenValue(ctx, baseAsset, types.PriceModeLow)
if err != nil {
return sdk.ZeroDec(), err
}
Expand All @@ -149,7 +131,7 @@ func (k Keeper) CalculateBorrowLimit(ctx sdk.Context, collateral sdk.Coins, hist
// borrower with given collateral could reach before being eligible for liquidation, using
// each token's oracle price, uToken exchange rate, and liquidation threshold.
// An error is returned if any input coins are not uTokens or if value
// calculation fails.
// calculation fails. Always uses spot prices.
func (k Keeper) CalculateLiquidationThreshold(ctx sdk.Context, collateral sdk.Coins) (sdk.Dec, error) {
totalThreshold := sdk.ZeroDec()

Expand All @@ -168,7 +150,7 @@ func (k Keeper) CalculateLiquidationThreshold(ctx sdk.Context, collateral sdk.Co
// ignore blacklisted tokens
if !ts.Blacklist {
// get USD value of base assets
v, err := k.TokenValue(ctx, baseAsset, false)
v, err := k.TokenValue(ctx, baseAsset, types.PriceModeSpot)
if err != nil {
return sdk.ZeroDec(), err
}
Expand Down
10 changes: 5 additions & 5 deletions x/leverage/keeper/borrows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ func (s *IntegrationTestSuite) TestCalculateBorrowLimit() {
app, ctx, require := s.app, s.ctx, s.Require()

// Empty coins
borrowLimit, err := app.LeverageKeeper.CalculateBorrowLimit(ctx, sdk.NewCoins(), false)
borrowLimit, err := app.LeverageKeeper.CalculateBorrowLimit(ctx, sdk.NewCoins())
require.NoError(err)
require.Equal(sdk.ZeroDec(), borrowLimit)

// Unregistered asset
invalidCoins := sdk.NewCoins(coin("abcd", 1000))
_, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, invalidCoins, false)
_, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, invalidCoins)
require.ErrorIs(err, types.ErrNotUToken)

// Create collateral uTokens (1k u/umee)
Expand All @@ -222,7 +222,7 @@ func (s *IntegrationTestSuite) TestCalculateBorrowLimit() {
Mul(sdk.MustNewDecFromStr("0.25"))

// Check borrow limit vs. manually computed value
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, umeeCollateral, false)
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, umeeCollateral)
require.NoError(err)
require.Equal(expectedUmeeLimit, borrowLimit)

Expand All @@ -237,7 +237,7 @@ func (s *IntegrationTestSuite) TestCalculateBorrowLimit() {
Mul(sdk.MustNewDecFromStr("0.25"))

// Check borrow limit vs. manually computed value
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, atomCollateral, false)
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, atomCollateral)
require.NoError(err)
require.Equal(expectedAtomLimit, borrowLimit)

Expand All @@ -246,7 +246,7 @@ func (s *IntegrationTestSuite) TestCalculateBorrowLimit() {
combinedCollateral := umeeCollateral.Add(atomCollateral...)

// Check borrow limit vs. manually computed value
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, combinedCollateral, false)
borrowLimit, err = app.LeverageKeeper.CalculateBorrowLimit(ctx, combinedCollateral)
require.NoError(err)
require.Equal(expectedCombinedLimit, borrowLimit)
}
4 changes: 2 additions & 2 deletions x/leverage/keeper/collateral.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (k Keeper) GetTotalCollateral(ctx sdk.Context, denom string) sdk.Coin {
}

// CalculateCollateralValue uses the price oracle to determine the value (in USD) provided by
// collateral sdk.Coins, using each token's uToken exchange rate.
// collateral sdk.Coins, using each token's uToken exchange rate. Always uses spot price.
// An error is returned if any input coins are not uTokens or if value calculation fails.
func (k Keeper) CalculateCollateralValue(ctx sdk.Context, collateral sdk.Coins) (sdk.Dec, error) {
total := sdk.ZeroDec()
Expand All @@ -66,7 +66,7 @@ func (k Keeper) CalculateCollateralValue(ctx sdk.Context, collateral sdk.Coins)
}

// get USD value of base assets
v, err := k.TokenValue(ctx, baseAsset, false)
v, err := k.TokenValue(ctx, baseAsset, types.PriceModeSpot)
if err != nil {
return sdk.ZeroDec(), err
}
Expand Down
Loading

0 comments on commit 2ec415a

Please sign in to comment.