-
Notifications
You must be signed in to change notification settings - Fork 14
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
Conversation
Changes to gas cost
🧾 Summary (10% most significant diffs)
Full diff report 👇
|
b93fb94
to
ddcbe73
Compare
(cache.borrowBase * cache.borrowIndex) / BORROWS_SCALER, | ||
newTotalSupply | ||
); | ||
return (uint72(cache.borrowIndex), inventory, inventory - cache.lastBalance, newTotalSupply); |
There was a problem hiding this comment.
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.
// Guard against reentrancy | ||
require(cache.lastAccrualTime != 0, "Aloe: locked"); | ||
|
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #206
// 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; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #216
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"); | ||
|
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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
{ | ||
(, , , bool initialized) = pool.observations((observationIndex + 1) % observationCardinality); | ||
if (!initialized) observationCardinality = observationIndex + 1; | ||
} |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #208
e8c7422
to
7edebd5
Compare
* Simpler computeTickTvl method in Volatility library * Eliminate IV's dependence on slot0.sqrtPriceX96 and pool.liquidity() * Clean up Oracle.sol
* 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
7edebd5
to
4ff9aea
Compare
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.