Platform: Code4rena
Start Date: 05/05/2022
Pot Size: $125,000 DAI
Total HM: 17
Participants: 62
Period: 14 days
Judge: leastwood
Total Solo HM: 15
Id: 120
League: ETH
Rank: 21/62
Findings: 2
Award: $345.92
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xkatana, 0xsomeone, AuditsAreUS, BouSalman, BowTiedWardens, Cityscape, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Picodes, Ruhum, TerrierLover, WatchPug, Waze, bobirichman, catchup, cccz, cryptphi, csanuragjain, delfin454000, ellahi, fatherOfBlocks, hake, horsefacts, hyh, jayjonah8, joestakey, kebabsec, kenta, mics, oyc_109, robee, samruna, shenwilly, sikorico, simon135, throttle, tintin
242.6467 DAI - $242.65
AlchemicTokenV2.sol
gALCX.sol
L46 - in the migrateSource signature you can directly pass the IALCXSource interface instead of an address and then wrap it. This would make it so that if it doesn't match the interface, it will revert without executing any line inside the function.
L62 - There is no benefit to creating a reApprove function, it should be in the constructor. In the event that more allowance is needed, it could be executed directly from the contract.
CrossChainCanonicalBase.sol
AlchemistV2.sol
L259 - The admin can be set to zero on initialize and this would generate a DoS on setPendingAdmin, acceptAdmin, setSentinel, setKeeper, addUnderlyingToken, addYieldToken, configureRepayLimit, configureLiquidationLimit, setTransmuter, setMinimumCollateralization, setProtocolFee, setProtocolFeeReceiver, configureMintingLimit, configureCreditUnlockRate, setTokenAdapter, setMaximumValue, setMaximumExpected snap and sweepTokens. Since they are functions that have the _onlyAdmin() validation.
L425 - In the setTransmuter() function it is validated that the new address is not zero, but in the initialize it is not validated, therefore it could have an invalid state at each moment of the redeploy.
L448 - In the setProtocolFeeReceiver() function it is validated that the new address is not zero, but in the initialize it is not validated, therefore it could have an invalid state at each moment of the redeploy.
TransmuterBuffer.sol
L341 - in the withdeaw function "amount" is passed as the second parameter and because of how it is used, it would make more sense to pass second recipient and then amount.
L230 - the variable in storage alchemist should be saved in storage as IStorage, this way it would not be necessary to be in each function wrapping the address alchemist.
YearnTokenAdapter.sol
FuseTokenAdapterV1.sol
WstETHAdapterV1.sol
RETHAdapterV1.sol
EthAssetManager.sol
ThreePoolAssetManager.sol
L235 - As they are immutable variables, it should be validated that no address is zero if it does not match. Also, if you set the admin to zero, a DoS would be generated in several functions with the modifier onlyAdmin.
L455 - It is not necessary to validate if pendingAdmin == address(0), since address zero will never be able to calling a function, so validating pendingAdmin == msg.sender is enough.
L744 - In the _getEarnedConvex() function it is not possible to know what values โโconvexToken.reductionPerCliff() and convexToken.totalCliff() will return therefore, it should be validated if it is different from zero, since otherwise it would revert.
๐ Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xf15ers, 0xkatana, 0xsomeone, AlleyCat, BowTiedWardens, Cityscape, Fitraldys, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Randyyy, TerrierLover, Tomio, UnusualTurtle, WatchPug, Waze, _Adam, augustg, bobirichman, catchup, csanuragjain, ellahi, fatherOfBlocks, hake, hansfriese, horsefacts, ignacio, joestakey, kenta, mics, oyc_109, robee, samruna, sashik_eth, sikorico, simon135, throttle
103.2651 DAI - $103.27
AlchemicTokenV2.sol
gALCX.sol
CrossChainCanonicalBase.sol
L33 - modifier functions can save gas if a view function is used instead of a modifier.
L57/141 - In the for loop, gas could be saved if instead of i++ an unchecked{++i;} is used in the last line and when uint256 i=0; more is saved if it is not set to its default value.
AlchemistV2.sol
TransmuterBuffer.sol
L96/106/114/122 - modifier functions can save gas if a view function is used instead of a modifier.
L151 - create a local variable of flowAvailable[underlyingToken], since it will be executed once in the if and if it does not pass, it will be executed a second time in the else.
L172/186/235/242/272/382/387/479 - In the for loop, gas could be saved if instead of i++ an unchecked{++i;} is used in the last line and when uint256 i=0; more is saved if it is not set to its default value.
TransmuterV2.sol
L108 - the variable syntheticToken only defines its value in the constructor, so it could be immutable, that way you'd save gas.
L111 - the variable underlyingToken only defines its value in the constructor, so it could be immutable, that way you'd save gas.
167/175/183 - modifier functions can save gas if a view function is used instead of a modifier.
FuseTokenAdapterV1.sol
L36 - Gas is saved by not initializing the base value.
L53 - modifier functions can save gas if a view function is used instead of a modifier.
L81/103 - In the for loop, gas could be saved if instead of i++ an unchecked{++i;} is used in the last line and when uint256 i=0; more is saved if it is not set to its default value.
WstETHAdapterV1.sol
RETHAdapterV1.sol
EthAssetManager.sol
L185/193 - modifier functions can save gas if a view function is used instead of a modifier.
L214/567 - In the for loop, gas could be saved if instead of i++ an unchecked{++i;} is used in the last line and when uint256 i=0; more is saved if it is not set to its default value.
ThreePoolAssetManager.sol
L220/228 - modifier functions can save gas if a view function is used instead of a modifier.
L250/254/353 - In the for loop, gas could be saved if instead of i++ an unchecked{++i;} is used in the last line and when uint256 i=0; more is saved if it is not set to its default value.