Skip to content

Commit

Permalink
fix leveraged liquidate not working during low liquidity (#2285)
Browse files Browse the repository at this point in the history
* fix leveraged liquidate not working during low liquidity

* cl

* empty commit

* empty commit

* ++

* fix govulncheck flow name

* ++

---------

Co-authored-by: Robert Zaremba <[email protected]>
  • Loading branch information
toteki and robert-zaremba authored Oct 17, 2023
1 parent 39e19f6 commit 273efb4
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/govulncheck.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Tests
name: Vuln
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- [2267](https://github.com/umee-network/umee/pull/2267) Leverage transactions accept spot prices up to 3 minutes old, and leverage queries use most recent spot price when required.
- [2263](https://github.com/umee-network/umee/pull/2263) Add spot price fields to account summary.
- [2270](https://github.com/umee-network/umee/pull/2270) Increase free oracle tx limit to 200k gas.
- [2285](https://github.com/umee-network/umee/pull/2285) Leveraged liquidate works during low liquidity.

### Features

Expand Down
16 changes: 11 additions & 5 deletions x/leverage/keeper/liquidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func (k Keeper) getLiquidationAmounts(
priceRatio,
exchangeRate,
liqudationIncentive,
leveragedLiquidate,
)

return sdk.NewCoin(repayDenom, repay), sdk.NewCoin(collateralDenom, burn), sdk.NewCoin(rewardDenom, reward), nil
Expand All @@ -123,13 +124,15 @@ func (k Keeper) getLiquidationAmounts(
// - priceRatio: The ratio of repayPrice / rewardPrice, which is used when computing rewards
// - uTokenExchangeRate: The uToken exchange rate from collateral uToken denom to reward base denom
// - liquidationIncentive: The liquidation incentive of the token reward denomination
// - leverageLiquidate: whether liquidation is leveraged (in which case it can disregard availableReward)
func ComputeLiquidation(
availableRepay,
availableCollateral,
availableReward sdkmath.Int,
priceRatio,
uTokenExchangeRate,
liquidationIncentive sdk.Dec,
leverageLiquidate bool,
) (tokenRepay sdkmath.Int, collateralBurn sdkmath.Int, tokenReward sdkmath.Int) {
// Prevent division by zero
if uTokenExchangeRate.IsZero() || priceRatio.IsZero() {
Expand Down Expand Up @@ -157,12 +160,15 @@ func ComputeLiquidation(
ratio = sdk.MinDec(ratio,
toDec(availableCollateral).Quo(maxCollateral),
)
// Base token reward cannot exceed available unreserved module balance
ratio = sdk.MinDec(ratio,
toDec(availableReward).Quo(maxReward),
)
if !leverageLiquidate {
// Base token reward cannot exceed available unreserved module balance
ratio = sdk.MinDec(ratio,
toDec(availableReward).Quo(maxReward),
)
}

// Catch edge cases
if !ratio.IsPositive() {
if !ratio.IsPositive() || ratio.GT(sdk.OneDec()) {
return sdk.ZeroInt(), sdk.ZeroInt(), sdk.ZeroInt()
}

Expand Down
9 changes: 9 additions & 0 deletions x/leverage/keeper/liquidate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func TestComputeLiquidation(t *testing.T) {
rewardTokenPrice sdk.Dec
uTokenExchangeRate sdk.Dec
liquidationIncentive sdk.Dec
leveragedLiquidate bool
}

baseCase := func() testCase {
Expand All @@ -30,6 +31,7 @@ func TestComputeLiquidation(t *testing.T) {
sdk.OneDec(), // price(B) = $1
sdk.OneDec(), // utoken exchange rate 1 u/B => 1 B
sdk.MustNewDecFromStr("0.1"), // reward value is 110% repay value
false,
}
}

Expand All @@ -42,6 +44,7 @@ func TestComputeLiquidation(t *testing.T) {
priceRatio,
tc.uTokenExchangeRate,
tc.liquidationIncentive,
tc.leveragedLiquidate,
)

assert.Equal(t, true, sdkmath.NewInt(expectedRepay).Equal(repay),
Expand Down Expand Up @@ -74,6 +77,12 @@ func TestComputeLiquidation(t *testing.T) {
rewardLimited.availableReward = sdk.NewInt(330)
runTestCase(rewardLimited, 300, 330, 330, "reward limited")

// limiting factor would be available reward, but leveraged liquidation is not limited by base tokens
rewardNotLimited := baseCase()
rewardNotLimited.availableReward = sdk.NewInt(330)
rewardNotLimited.leveragedLiquidate = true
runTestCase(rewardNotLimited, 1000, 1100, 1100, "reward not limited")

// repay token is worth more
expensiveRepay := baseCase()
expensiveRepay.repayTokenPrice = sdk.MustNewDecFromStr("2")
Expand Down

0 comments on commit 273efb4

Please sign in to comment.