Platform: Code4rena
Start Date: 08/06/2022
Pot Size: $115,000 USDC
Total HM: 26
Participants: 72
Period: 11 days
Judge: leastwood
Total Solo HM: 14
Id: 132
League: ETH
Rank: 29/72
Findings: 2
Award: $283.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedWardens
Also found by: 0x1f8b, 0x29A, 0x52, 0xNazgul, 0xNineDec, 0xf15ers, 0xkatana, 0xmint, Chom, ElKu, Funen, IllIllI, JMukesh, Jujic, Kaiziron, Lambda, MiloTruck, Ruhum, SmartSek, SooYa, TerrierLover, TomJ, WatchPug, Waze, _Adam, asutorufos, auditor0517, bardamu, c3phas, catchup, cccz, ch13fd357r0y3r, cloudjunky, cmichel, cryptphi, csanuragjain, defsec, fatherOfBlocks, hansfriese, hyh, jayjonah8, joestakey, k, kenta, obtarian, oyc_109, robee, sach1r0, shenwilly, simon135, slywaters, sorrynotsorry, tintin, unforgiven, xiaoming90, zzzitron
195.0221 USDC - $195.02
adopted
of repayAavePortal()
is not used anywhere.(bool success, uint256 amountIn, address adopted) = AssetLogic.swapFromLocalAssetIfNeededForExactOut( _local, totalAmount, _maxIn );
sponsoredFee
in reimburseRelayerFees()
sponsoredFee
in L246 will revert anyway when den
is zero.function reimburseRelayerFees(......) { if (address(gasTokenOracle) != address(0)) { (num, den) = gasTokenOracle.getRate(_originDomain); // note: this will revert when den == 0 sponsoredFee = (_originRelayerFee * num) / den; } else { num = rates[_originDomain].num; den = rates[_originDomain].den; } if (den != 0) { sponsoredFee = (_originRelayerFee * num) / den; }
--> contracts/core/connext/facets/BridgeFacet.sol:391:5: | 391 | uint32 _nonce, | ^^^^^^^^^^^^^ --> contracts/core/connext/facets/BridgeFacet.sol:987:5: | 987 | address _router, | ^^^^^^^^^^^^^^^ --> contracts/core/connext/facets/PortalFacet.sol:128:5: | 128 | address _router, // @qa unused function parameter | ^^^^^^^^^^^^^^^
#0 - jakekidd
2022-07-02T01:16:10Z
1 invalid, should be able to set to address 0 rest are fine
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xmint, BowTiedWardens, ElKu, Fitraldys, Funen, Kaiziron, Lambda, Metatron, MiloTruck, Randyyy, Ruhum, SmartSek, TomJ, Tomio, UnusualTurtle, Waze, _Adam, apostle0x01, asutorufos, c3phas, catchup, csanuragjain, defsec, fatherOfBlocks, hansfriese, hyh, ignacio, joestakey, k, kaden, nahnah, oyc_109, rfa, robee, sach1r0, simon135, slywaters
88.7836 USDC - $88.78
While looping through array, the array length can be cached to save gas instead of computing length in each array iteration.
for eg.
uint256 len = modules.length; for(uint256 i = 0; i < len; i++) { ... }
> grep -rn './core' -e 'for.*[.]length' ./core/connext/facets/StableSwapFacet.sol:415: for (uint8 i = 0; i < _pooledTokens.length; i++) { ./core/connext/facets/RelayerFacet.sol:140: for (uint256 i; i < _transferIds.length; ) { ./core/connext/facets/RelayerFacet.sol:164: for (uint256 i; i < _transferIds.length; ) { ./core/connext/libraries/LibDiamond.sol:104: for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) { ./core/connext/libraries/LibDiamond.sol:129: for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) { ./core/connext/libraries/LibDiamond.sol:147: for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) { ./core/connext/libraries/LibDiamond.sol:162: for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) { ./core/connext/libraries/SwapUtils.sol:205: for (uint256 i = 0; i < xp.length; i++) { ./core/connext/libraries/SwapUtils.sol:558: for (uint256 i = 0; i < balances.length; i++) { ./core/connext/libraries/SwapUtils.sol:591: for (uint256 i = 0; i < balances.length; i++) { ./core/connext/libraries/SwapUtils.sol:844: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:869: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:924: for (uint256 i = 0; i < amounts.length; i++) { ./core/connext/libraries/SwapUtils.sol:1014: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1019: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1039: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1055: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/helpers/ConnextPriceOracle.sol:176: for (uint256 i = 0; i < tokenAddresses.length; i++) { ./core/connext/helpers/StableSwap.sol:81: for (uint8 i = 0; i < _pooledTokens.length; i++) {
++i
) is cheaper than postfix increment (i++
)Using prefix increment is saves small amount of gas than postfix increment because it returns the updated value hence doesn't requires to store intermediate value. This can be more significant in loops where this operation is done multiple times.
for eg.
// before for(uint256 i = 0; i < len; i++) { ... } // Replace with for(uint256 i = 0; i < len; ++i) { ... }
./core/connext/libraries/SwapUtils.sol:425: for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) { ./core/connext/libraries/SwapUtils.sol:558: for (uint256 i = 0; i < balances.length; i++) { ./core/connext/libraries/SwapUtils.sol:591: for (uint256 i = 0; i < balances.length; i++) { ./core/connext/libraries/SwapUtils.sol:844: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:869: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:924: for (uint256 i = 0; i < amounts.length; i++) { ./core/connext/libraries/SwapUtils.sol:1014: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1019: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1039: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/libraries/SwapUtils.sol:1055: for (uint256 i = 0; i < pooledTokens.length; i++) { ./core/connext/helpers/ConnextPriceOracle.sol:176: for (uint256 i = 0; i < tokenAddresses.length; i++) { ./core/connext/helpers/StableSwap.sol:81: for (uint8 i = 0; i < _pooledTokens.length; i++) { ...
address(this).balance
in ternary operator to save gas instead of evaluating it twicesponsoredFee = sponsoredFee > address(this).balance ? address(this).balance : sponsoredFee;
#0 - liu-zhipeng
2022-06-30T14:14:11Z
1, 2 : duplicated 3: fixed
#1 - 0xleastwood
2022-08-16T19:41:02Z
Useful optimisations but also found by many other wardens.