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: 90/120
Findings: 1
Award: $45.83
🌟 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.8341 USDC - $45.83
Zero-address checks are a common best practice for input validation of critical address parameters, particularly in constructors and setters. Accidental use of zero-addresses may result in unexpected exceptions, failures or require the redeployment of contracts.
To implement a zero-address check, use a pattern like the following:
error ZeroAddress(); // This probably belongs in FraxlendPairConstants require(DEPLOYER_ADDRESS != address(0), ZeroAddress()); // inside function where value defined
The following instances were identified where zero-address checks should be added.
In FraxlendPairCore.sol:
In FraxlendPairDeployer.sol:
In FraxlendWhitelist.sol:
Not all ERC20 tokens revert on approval failure. Some (such as USDT) will return false instead. This project ignores the return value of ERC20.approve() on several occasions:
leveragedPosition() - If this approve fails without a revert the code will still call the swapper. Not all swappers act the same (Uniswap v2 returns uint[] memory amounts for example, other swappers may act differently). repayAssetWithCollateral() - If this approve fails without a revert the contract will still call the swapper.
I've marked this as low as it's a last-day finding and I don't have time to test it, but it's worth the devs testing a mock swapper that doesn't revert if not approved to see the impact on the rest of these two functions. Remember that just because an approves can fail when allowances are already set. It's possible that the contract may enter an unexpected state with regards to positions and collateral, but I lacked the time to test.
Some ERC20 Tokens (most notably USDT) won't permit the use of .approve() to update an approval from one non-zero value to another. This can trigger situations such as outlined in my L-02 finding where an approve fails because one already exists and the swapper may act unexpectedly.
There are several ways to handle approves. The first (and not recommended) is to approve the token for 0, then for the amount. This is discouraged as this is a workaround for non-standard ERC tokens, where the expectation is they will already behave in a non-standard manner.
A preferred option - given the welcome decision to use SafeERC20 would be to use SafeERC20's increaseAllowance() and decreaseAllowance() functions instead of approve().
The instances where using SafeERC20 functions may be better are: