Skip to content

Commit

Permalink
price mode support
Browse files Browse the repository at this point in the history
  • Loading branch information
toteki committed Sep 27, 2023
1 parent 498bd30 commit af0c454
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements

- [2261](https://github.com/umee-network/umee/pull/2261) Use go 1.21
- [22XX](https://github.com/umee-network/umee/pull/22XX) Leverage transactions accept spot prices up to 3 minutes old, and leverage queries use most recet spot price when required.

### Bug Fixes

Expand Down
27 changes: 20 additions & 7 deletions x/leverage/keeper/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
oracletypes "github.com/umee-network/umee/v6/x/oracle/types"
)

// TODO: parameterize this
const maxSpotPriceAge = 180 // 3 minutes

var ten = sdk.MustNewDecFromStr("10")

// TokenPrice returns the USD value of a token's symbol denom, e.g. `UMEE` (rather than `uumee`).
Expand All @@ -26,8 +29,9 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo
return sdk.ZeroDec(), t.Exponent, types.ErrBlacklisted
}

// if a token is exempt from historic pricing, all price modes return Spot price
if t.HistoricMedians == 0 {
// if a token is exempt from historic pricing, all price modes return Spot price.
// price mode last is unaffected.
if t.HistoricMedians == 0 && mode != types.PriceModeLast {
mode = types.PriceModeSpot
}

Expand All @@ -39,9 +43,20 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo
if err != nil {
return sdk.ZeroDec(), t.Exponent, errors.Wrap(err, "oracle")
}
if mode != types.PriceModeLast {
// unless price mode is last price, require spot price to be recent
blockTime := ctx.BlockTime().Unix()
priceTime := spotPrice.Timestamp.Unix()
priceAge := blockTime - priceTime
if priceAge < 0 || priceAge > maxSpotPriceAge {
return sdk.ZeroDec(), t.Exponent, types.ErrExpiredOraclePrice.Wrapf(
"price: %d, block: %d", priceTime, blockTime)
}
}
}
if mode != types.PriceModeSpot {
// historic price is required for modes other than spot

if mode != types.PriceModeSpot && mode != types.PriceModeLast {
// historic price is required for modes other than spot and last
var numStamps uint32
historicPrice, numStamps, err = k.oracleKeeper.MedianOfHistoricMedians(
ctx, strings.ToUpper(t.SymbolDenom), uint64(t.HistoricMedians))
Expand All @@ -57,10 +72,8 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo
}
}

// TODO: need to use spotPrice.Timestamp to make a decision about the price

switch mode {
case types.PriceModeSpot:
case types.PriceModeSpot, types.PriceModeLast:
price = spotPrice.Rate
case types.PriceModeHistoric:
price = historicPrice
Expand Down
1 change: 1 addition & 0 deletions x/leverage/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
ErrUndercollateralized = errors.Register(ModuleName, 402, "borrow positions are undercollateralized")
ErrLiquidationIneligible = errors.Register(ModuleName, 403, "borrower not eligible for liquidation")
ErrNoHistoricMedians = errors.Register(ModuleName, 405, "insufficient historic medians available")
ErrExpiredOraclePrice = errors.Register(ModuleName, 406, "no recent oracle price")

// 5XX = Market Conditions
ErrLendingPoolInsufficient = errors.Register(ModuleName, 500, "lending pool insufficient")
Expand Down
4 changes: 3 additions & 1 deletion x/leverage/types/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ package types
type PriceMode uint64

const (
// Spot mode requests the most recent prices from oracle
// Spot mode requests the most recent prices from oracle, unless they are too old.
PriceModeSpot PriceMode = iota
// Last mode requests the most recent price, regardless of price age.
PriceModeLast
// Historic mode requests the median of the most recent historic medians
PriceModeHistoric
// High mode uses the higher of either Spot or Historic prices
Expand Down

0 comments on commit af0c454

Please sign in to comment.