Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues uncovered during Sherlock Audit #224

Merged
merged 29 commits into from
Dec 9, 2023

Conversation

haydenshively
Copy link
Member

@haydenshively haydenshively commented Nov 22, 2023

This branch contains fixes for all issues uncovered during our October Sherlock Audit. Constituent PRs' descriptions explain the changes and link to the issues they fix. The only thing for which that's not really true is liquidations, which have been further modified/updated in this PR, building on top of #223.

@haydenshively haydenshively changed the title First batch of fixes from the Sherlock Audit Fix issues uncovered during Sherlock Audit Nov 24, 2023
Copy link

github-actions bot commented Nov 24, 2023

Changes to gas cost

Generated at commit: 917cda9193d720c894ed2fa98cefbf57f99fa5d0, compared to commit: e543bb4c48bec50e5c942c9c52c6c39575e1d2b0

🧾 Summary (10% most significant diffs)

Contract Method Avg (+/-) %
Borrower liquidate +126,628 ❌ +236.26%

Full diff report 👇
Contract Deployment Cost (+/-) Method Min (+/-) % Avg (+/-) % Median (+/-) % Max (+/-) % # Calls (+/-)
Borrower 3,526,599 (+277,332) borrow
getUniswapPositions
liquidate
modify
repay
transfer
uniswapDeposit
uniswapV3MintCallback
uniswapWithdraw
warn
0 (0)
0 (0)
120,262 (+120,262)
0 (0)
43,060 (+186)
0 (0)
0 (0)
0 (0)
93,585 (+25)
0 (0)
+∞%
+∞%
+∞%
+∞%
+0.43%
+∞%
+∞%
+∞%
+0.03%
+∞%
13,740 (+158)
552 (+39)
180,224 (+126,628)
68,865 (+4,132)
43,060 (+186)
10,639 (+11)
56,030 (+52)
7,769 (+26)
93,585 (+25)
7,428 (-6,646)
+1.16%
+7.60%
+236.26%
+6.38%
+0.43%
+0.10%
+0.09%
+0.34%
+0.03%
-47.22%
17,814 (+231)
552 (+39)
185,856 (+135,747)
95,110 (+4,434)
43,060 (+186)
0 (0)
0 (0)
0 (0)
93,585 (+25)
0 (-14,074)
+1.31%
+7.60%
+270.90%
+4.89%
+0.43%
+∞%
+∞%
+∞%
+0.03%
-100.00%
41,714 (+231)
1,104 (+77)
228,924 (+100,965)
241,486 (+10,066)
43,060 (+186)
31,917 (+33)
168,090 (+154)
23,307 (+77)
93,585 (+25)
37,141 (+8,993)
+0.56%
+7.50%
+78.90%
+4.35%
+0.43%
+0.10%
+0.09%
+0.33%
+0.03%
+31.95%
16 (0)
2 (0)
4 (-2)
26 (0)
1 (0)
3 (0)
3 (0)
3 (0)
1 (0)
5 (+3)
VolatilityOracle 1,809,715 (-54,865) consult
prepare
update
15,476 (+882)
128,618 (+140)
0 (0)
+6.04%
+0.11%
+∞%
15,476 (+882)
128,618 (+140)
81,709 (+25,186)
+6.04%
+0.11%
+44.56%
15,476 (+882)
128,618 (+140)
81,709 (+25,186)
+6.04%
+0.11%
+44.56%
15,476 (+882)
128,618 (+140)
163,418 (+50,372)
+6.04%
+0.11%
+44.56%
1 (0)
5 (0)
2 (0)
RateModel 65,923 (0) getYieldPerSecond 263 (+263) +∞% 263 (+30) +12.88% 263 (0) 0.00% 263 (0) 0.00% 20 (+11)
BorrowerDeployer 3,748,452 (+232,904) deploy 3,563,192 (+277,635) +8.45% 3,563,608 (+277,635) +8.45% 3,563,192 (+277,635) +8.45% 3,565,692 (+277,635) +8.44% 18 (0)

@haydenshively haydenshively force-pushed the sherlock-audit-fixes branch 3 times, most recently from b93fb94 to ddcbe73 Compare December 1, 2023 20:27
(cache.borrowBase * cache.borrowIndex) / BORROWS_SCALER,
newTotalSupply
);
return (uint72(cache.borrowIndex), inventory, inventory - cache.lastBalance, newTotalSupply);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inventory - cache.lastBalance == cache.borrowBase * cache.borrowIndex / BORROWS_SCALER because that's how inventory is computed in the first place.

Comment on lines -339 to -341
// Guard against reentrancy
require(cache.lastAccrualTime != 0, "Aloe: locked");

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we removed flash, there's no longer any possibility of reentrancy in Lender, so there's no reason for this guard.

newInventory,
newInventory - (newInventory - oldInventory) / rf
),
type(uint112).max
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're clamping to the maximum value so that accrueInterest doesn't revert, guaranteeing that governance can always set a new rate model. Added in #206

@@ -59,6 +55,8 @@ contract Lender is Ledger {
/// @notice Sets the `rateModel` and `reserveFactor`. Only the `FACTORY` can call this.
function setRateModelAndReserveFactor(IRateModel rateModel_, uint8 reserveFactor_) external {
require(msg.sender == address(FACTORY) && reserveFactor_ > 0);

accrueInterest();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #206

Comment on lines +117 to +122
// Callers are free to set their own courier, but they need permission to mess with others'
if (msg.sender != beneficiary) {
require(allowance[beneficiary][msg.sender] > 0, "Aloe: courier");
allowance[beneficiary][msg.sender] = 0;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #216

Comment on lines -217 to +227
uint256 b = borrows[msg.sender];
require(b != 0, "Aloe: not a borrower");

// Accrue interest and update reserves
(Cache memory cache, ) = _load();

unchecked {
uint256 b = borrows[msg.sender];
require(b != 0, "Aloe: not a borrower");

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved in as b wasn't used in the outer scope.

@@ -327,6 +309,7 @@ contract Lender is Ledger {
}

function transfer(address to, uint256 shares) external returns (bool) {
accrueInterest();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensures that Rewards tracking for RESERVE is correct.

} else {
(, int24 currentTick, uint16 observationIndex, uint16 observationCardinality, , , ) = pool.slot0();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved in because it wasn't used in outer scope

Comment on lines +39 to +42
{
(, , , bool initialized) = pool.observations((observationIndex + 1) % observationCardinality);
if (!initialized) observationCardinality = observationIndex + 1;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #217

// Uniswap divides before multiplying, so we do too
return (
tickCumL + ((tickCumR - tickCumL) / int56(denom)) * int56(delta),
liqCumL + uint160(((liqCumR - liqCumL) * delta) / denom)
liqCumL + uint160((uint256(liqCumR - liqCumL) * delta) / denom)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #208

* Increase FEE_GROWTH_AVG_WINDOW so it's harder to manipulate

* Allow IV to increase faster than it decreases to match CEX more closely

* Interpolate between old and new IV samples instead of jumping

* Switch to EMA updates for smoother IV
* Evaluate shortfall at the probe prices in BalanceSheet.isHealthy

* Rename SLOT0_MASK_UNLEASH

* Replace strain with closeFactor in bips

* Only reset warning state if healthy after liquidate()

* Operate on unleashTime inside liquidate() instead of pre-adding in warn()

* Implement dutch auction liquidations

* Reuse assets and liabilities values for gas efficiency

* Clamp liquidators' amounts to what's actually available
@haydenshively haydenshively merged commit 00339aa into master Dec 9, 2023
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant