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: 14/62
Findings: 2
Award: $1,139.27
🌟 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
1047.4277 DAI - $1,047.43
We list 1 low-critical findings
reApprove()
doesn’t check alcx.approve()
’s return valuereApprove()
doesn’t check alcx.approve()
’s return valueIn gALCX.sol
, it is better to check alcx.approve()
’s return value in reApprove()
https://github.com/code-423n4/2022-05-alchemix/blob/main/contracts-full/gALCX.sol#L62-L64
None
Check return value of alcx.approve
🌟 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
91.8428 DAI - $91.84
validBridgeToken
modifier is duplicated in exchangeOldForCanonical()
and exchangeCanonicalForOld
In exchangeOldForCanonical()
and exchangeCanonicalForOld()
, validBridgeToken
modifier is used to check bridgeTokenEnabled[tokenAddress]
modifier validBridgeToken(address tokenAddress) { if (!bridgeTokenEnabled[tokenAddress]) { revert IllegalState(); } _; }
However in both functions, bridgeTokenEnabled[tokenAddress]
is check again.
function exchangeOldForCanonical(address bridgeTokenAddress, uint256 tokenAmount) external nonReentrant validBridgeToken(bridgeTokenAddress) returns (uint256 canonicalTokensOut) { … if (!bridgeTokenEnabled[bridgeTokenAddress]) { revert IllegalState(); } … }
function exchangeCanonicalForOld(address bridgeTokenAddress, uint256 tokenAmount) external nonReentrant validBridgeToken(bridgeTokenAddress) returns (uint256 bridgeTokensOut) { … if (!bridgeTokenEnabled[bridgeTokenAddress]) { revert IllegalState(); } … }
It’s duplicated. One of the checks should be removed to save gas.
The for loop has no overflow risk of i
. Use an unchecked block to save gas.
ThreePoolAssetManager.sol 250: for (uint256 i = 0; i < NUM_STABLE_COINS; i++) { 254: for (uint256 i = 0; i < NUM_META_COINS; i++) { 353: for (uint256 i = 0; i < 256; i++) { 773: for (uint256 i = 0; i < NUM_STABLE_COINS; i++) { 902: for (uint256 i = 0; i < NUM_META_COINS; i++) { test/TransmuterBufferMock.sol 15: for (uint256 i = 0; i < _underlyingTokens.length; i++) { EthAssetManager.sol 214: for (uint256 i = 0; i < NUM_META_COINS; i++) { 567: for (uint256 i = 0; i < NUM_META_COINS; i++) { CrossChainCanonicalBase.sol 57: for (uint256 i = 0; i < _bridgeTokens.length; i++){ 141: for (uint i = 0; i < bridgeTokensArray.length; i++){ TransmuterBuffer.sol 172: for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) { 186: for (uint256 i = 0; i < tokens.length; i++) { 235: for (uint256 i = 0; i < registeredUnderlyings.length; i++) { 242: for (uint256 i = 0; i < registeredUnderlyings.length; i++) { 272: for (uint256 i = 0; i < registeredUnderlyings.length; i++) { 382: for (uint256 j = 0; j < registeredUnderlyings.length; j++) { 387: for (uint256 i = 0; i < numYTokens; i++) { 479: for (uint256 j = 0; j < weighting.tokens.length; j++) { AlchemistV2.sol 990: for (uint256 i = 0; i < depositedTokens.values.length; i++) { 1282: for (uint256 i = 0; i < depositedTokens.values.length; i++) { 1355: for (uint256 i = 0; i < depositedTokens.values.length; i++) { 1461: for (uint256 i = 0; i < depositedTokens.values.length; i++) { 1524: for (uint256 i = 0; i < depositedTokens.values.length; i++) { StakingPools.sol 188: for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) { 363: for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) { base/Multicall.sol 14: for (uint256 i = 0; i < data.length; i++) {
Use unchecked
blocks to avoid overflow checks, or use ++i
rather than i++
if you don't use unchecked blocks.
for (uint256 i = 0; i < length; ) { ... unchecked { ++i; } }
#0 - 0xfoobar
2022-05-30T06:58:30Z
Good callout about duplicate bridgeTokenEnabled check