Platform: Code4rena
Start Date: 12/08/2022
Pot Size: $50,000 USDC
Total HM: 15
Participants: 120
Period: 5 days
Judge: Justin Goro
Total Solo HM: 6
Id: 153
League: ETH
Rank: 62/120
Findings: 2
Award: $67.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x1f8b
Also found by: 0x52, 0xA5DF, 0xDjango, 0xNazgul, 0xNineDec, 0xSmartContract, 0xmatt, 0xsolstars, Aymen0909, Bnke0x0, CertoraInc, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, EthLedger, Funen, IllIllI, JC, Junnon, Lambda, LeoS, MiloTruck, Noah3o6, PaludoX0, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, SaharAP, Sm4rty, SooYa, The_GUILD, TomJ, Waze, Yiko, _Adam, __141345__, a12jmx, ak1, asutorufos, auditor0517, ayeslick, ballx, beelzebufo, berndartmueller, bin2chen, brgltd, c3phas, cRat1st0s, cccz, cryptonue, cryptphi, d3e4, delfin454000, dipp, djxploit, durianSausage, dy, erictee, fatherOfBlocks, gogo, gzeon, hyh, ignacio, kyteg, ladboy233, medikko, mics, minhquanym, oyc_109, pfapostol, rbserver, reassor, ret2basic, robee, sach1r0, simon135, sryysryy, tabish, yac, yash90, zzzitron
45.8342 USDC - $45.83
// NOTE: reverts if _shares > userBorrowShares _repayAsset(_totalBorrow, _amountLiquidatorToRepay, _sharesToLiquidate, msg.sender, _borrower); // liquidator repays shares on behalf of borrower
_shares
should be _sharesToLiquidate
// NOTE: reverts if _sharesToLiquidate > userBorrowShares _repayAsset(_totalBorrow, _amountLiquidatorToRepay, _sharesToLiquidate, msg.sender, _borrower); // liquidator repays shares on behalf of borrower
/// @param _approval The approcal status
Should be
/// @param _approval The approval status
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xA5DF, 0xDjango, 0xNazgul, 0xSmartContract, 0xackermann, 0xbepresent, 0xc0ffEE, 0xkatana, 2997ms, Amithuddar, Aymen0909, Bnke0x0, Chinmay, Chom, CodingNameKiki, Deivitto, Diraco, Dravee, ElKu, EthLedger, Fitraldys, Funen, IgnacioB, JC, Junnon, Lambda, LeoS, Metatron, MiloTruck, Noah3o6, NoamYakov, PaludoX0, Randyyy, ReyAdmirado, Rohan16, Rolezn, Ruhum, SaharAP, Sm4rty, SooYa, TomJ, Tomio, Waze, Yiko, _Adam, __141345__, a12jmx, ajtra, ak1, asutorufos, ballx, brgltd, c3phas, cRat1st0s, carlitox477, chrisdior4, d3e4, delfin454000, dharma09, djxploit, durianSausage, erictee, fatherOfBlocks, find_a_bug, flyx, francoHacker, gerdusx, gogo, gzeon, hakerbaya, ignacio, jag, kyteg, ladboy233, ltyu, m_Rassska, medikko, mics, mrpathfindr, newfork01, nxrblsrpr, oyc_109, pfapostol, rbserver, reassor, ret2basic, robee, sach1r0, saian, simon135, sryysryy, zeesaw
21.1705 USDC - $21.17
https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/LinearInterestRate.sol#L53-L56 https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/LinearInterestRate.sol#L79-L82
/// @notice The ```requireValidInitData``` function reverts if initialization data fails to be validated /// @param _initData abi.encode(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) function requireValidInitData(bytes calldata _initData) public pure { (uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) = abi.decode( _initData, (uint256, uint256, uint256, uint256) ); require( _minInterest < MAX_INT && _minInterest <= _vertexInterest && _minInterest >= MIN_INT, "LinearInterestRate: _minInterest < MAX_INT && _minInterest <= _vertexInterest && _minInterest >= MIN_INT" ); require( _maxInterest <= MAX_INT && _vertexInterest <= _maxInterest && _maxInterest > MIN_INT, "LinearInterestRate: _maxInterest <= MAX_INT && _vertexInterest <= _maxInterest && _maxInterest > MIN_INT" ); require( _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization > 0, "LinearInterestRate: _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization > 0" ); } /// @notice Calculates interest rates using two linear functions f(utilization) /// @dev We use calldata to remain unopinionated about future implementations /// @param _data abi.encode(uint64 _currentRatePerSec, uint256 _deltaTime, uint256 _utilization, uint256 _deltaBlocks) /// @param _initData abi.encode(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) /// @return _newRatePerSec The new interest rate per second, 1e18 precision function getNewRate(bytes calldata _data, bytes calldata _initData) external pure returns (uint64 _newRatePerSec) { requireValidInitData(_initData); (, , uint256 _utilization, ) = abi.decode(_data, (uint64, uint256, uint256, uint256)); (uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) = abi.decode( _initData, (uint256, uint256, uint256, uint256) ); if (_utilization < _vertexUtilization) { uint256 _slope = ((_vertexInterest - _minInterest) * UTIL_PREC) / _vertexUtilization; _newRatePerSec = uint64(_minInterest + ((_utilization * _slope) / UTIL_PREC)); } else if (_utilization > _vertexUtilization) { uint256 _slope = (((_maxInterest - _vertexInterest) * UTIL_PREC) / (UTIL_PREC - _vertexUtilization)); _newRatePerSec = uint64(_vertexInterest + (((_utilization - _vertexUtilization) * _slope) / UTIL_PREC)); } else { _newRatePerSec = uint64(_vertexInterest); } }
Notice that this code block run 2 times
(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) = abi.decode( _initData, (uint256, uint256, uint256, uint256) );
You can split requireValidInitData function to avoid redundant abi.decode
function requireValidInitData(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) public pure { require( _minInterest < MAX_INT && _minInterest <= _vertexInterest && _minInterest >= MIN_INT, "LinearInterestRate: _minInterest < MAX_INT && _minInterest <= _vertexInterest && _minInterest >= MIN_INT" ); require( _maxInterest <= MAX_INT && _vertexInterest <= _maxInterest && _maxInterest > MIN_INT, "LinearInterestRate: _maxInterest <= MAX_INT && _vertexInterest <= _maxInterest && _maxInterest > MIN_INT" ); require( _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization > 0, "LinearInterestRate: _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization > 0" ); } /// @notice The ```requireValidInitData``` function reverts if initialization data fails to be validated /// @param _initData abi.encode(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) function requireValidInitData(bytes calldata _initData) public pure { (uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) = abi.decode( _initData, (uint256, uint256, uint256, uint256) ); requireValidInitData(_minInterest, _vertexInterest, _maxInterest, _vertexUtilization); } /// @notice Calculates interest rates using two linear functions f(utilization) /// @dev We use calldata to remain unopinionated about future implementations /// @param _data abi.encode(uint64 _currentRatePerSec, uint256 _deltaTime, uint256 _utilization, uint256 _deltaBlocks) /// @param _initData abi.encode(uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) /// @return _newRatePerSec The new interest rate per second, 1e18 precision function getNewRate(bytes calldata _data, bytes calldata _initData) external pure returns (uint64 _newRatePerSec) { (uint256 _minInterest, uint256 _vertexInterest, uint256 _maxInterest, uint256 _vertexUtilization) = abi.decode( _initData, (uint256, uint256, uint256, uint256) ); requireValidInitData(_minInterest, _vertexInterest, _maxInterest, _vertexUtilization); (, , uint256 _utilization, ) = abi.decode(_data, (uint64, uint256, uint256, uint256)); if (_utilization < _vertexUtilization) { uint256 _slope = ((_vertexInterest - _minInterest) * UTIL_PREC) / _vertexUtilization; _newRatePerSec = uint64(_minInterest + ((_utilization * _slope) / UTIL_PREC)); } else if (_utilization > _vertexUtilization) { uint256 _slope = (((_maxInterest - _vertexInterest) * UTIL_PREC) / (UTIL_PREC - _vertexUtilization)); _newRatePerSec = uint64(_vertexInterest + (((_utilization - _vertexUtilization) * _slope) / UTIL_PREC)); } else { _newRatePerSec = uint64(_vertexInterest); } }
(, , uint256 _utilization, ) = abi.decode(_data, (uint64, uint256, uint256, uint256));
Can be optimized by using assembly technique to skip unnecessary decoding of first two arguments.