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: 23/120
Findings: 2
Award: $238.34
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: auditor0517
Also found by: 0xA5DF, _Adam, cccz, minhquanym, minhtrng, zzzitron
192.5076 USDC - $192.51
In FraxlendPairCore.constructor()
function, value of dirtyLiquidationFee
should be 90% of clean fee (in comment). But actually, in implementation, itโs only equal to 9% of clean fee because LIQ_PRECISION = 1e5
and 9000 is only 9% of 1e5.
This basically resulted in less amount of collateral liquidators will receive in liquidateClean()
function.
Line 194 init value of dirtyLiquidationFee
dirtyLiquidationFee = (_liquidationFee * 9000) / LIQ_PRECISION; // 90% of clean fee
This variable is used to calculate amount of collateral received by liquidators in line 988-990
_collateralForLiquidator = _leftoverCollateral <= 0 ? _userCollateralBalance : (_liquidationAmountInCollateralUnits * (LIQ_PRECISION + dirtyLiquidationFee)) / LIQ_PRECISION;
Manual Review
Fix line 194 to
dirtyLiquidationFee = (_liquidationFee * 90000) / LIQ_PRECISION;
#0 - 0xA5DF
2022-08-17T20:42:34Z
Duplicate of #132
#1 - amirnader-ghazvini
2022-08-29T18:41:20Z
Duplicate of #238
๐ 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.8345 USDC - $45.83
https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/FraxlendPairConstants.sol#L41 https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/LinearInterestRate.sol#L34 https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/VariableInterestRate.sol#L40 https://github.com/code-423n4/2022-08-frax/blob/c4189a3a98b38c8c962c5ea72f1a322fbc2ae45f/src/contracts/VariableInterestRate.sol#L41
All annual rate constants in the system are calculated with an assumption that block time is 15 second (actually itโs from 12 to 14 seconds as in the documentation. And these constants are used to calculate rate in rate calculator and also used to reset interest rate when there are no borrows.
But actually, the merge is really near and after the merge blocks come exactly each 12 seconds which basically makes all these constants wrong.
This resulted in wrong interest rate after reseting when there are no borrows and wrong rate returned by rate calculators.
These annual rate is calculated by solving an equation for r
with an assumption 365.24 days per year and 15s blocks. For example, this is for the 0.5% annual rate
1.005 = (1 + 15*r)^(365.24 * 24 * 3600 / 15)
But actually after the merge, blocks come in exactly each 12 seconds. Check out this blog post of Tim Beiko
Line 431-433 reset interest rate when there are no borrows
if (!paused()) { _currentRateInfo.ratePerSec = DEFAULT_INT; }
These constants are used in requireValidInitData()
and also getNewRate()
function in rate calculators and wrong constants might make getNewRate()
return wrong value. For example, line 72-74 used MIN_INT
as new interest rate
if (_newRatePerSec < MIN_INT) { _newRatePerSec = MIN_INT; }
Manual Review
Consider to update these constants with an assumption that block time is 12 seconds.
#0 - 0xA5DF
2022-08-17T21:28:07Z
Seems invalid, interest rate isn't affected by the frequency of block mining.
#1 - DrakeEvans
2022-09-06T11:53:10Z
This only effects the constants like DEFAULT_RATE. The actual interest is calculated properly. The constants are meant to provide a reasonable starting point. We have confirmed because 12s is a better assumption than 15s. However, this does not effect the rate calculation.
#2 - gititGoro
2022-10-05T02:03:24Z
The warden isn't wrong about the incorrectly calculated constants but those constants are just bounding values. The actual live pairs are not dependent on assumptions about block duration. Downgrading to QA
#3 - gititGoro
2022-10-10T07:26:06Z
Duplicate of #291