Platform: Code4rena
Start Date: 29/07/2022
Pot Size: $50,000 USDC
Total HM: 6
Participants: 75
Period: 5 days
Judge: GalloDaSballo
Total Solo HM: 3
Id: 149
League: ETH
Rank: 40/75
Findings: 2
Award: $88.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: oyc_109
Also found by: 0x1f8b, 0x52, 0xNazgul, 0xSmartContract, 0xf15ers, 8olidity, Aymen0909, Bnke0x0, CertoraInc, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, IllIllI, JC, Lambda, Noah3o6, NoamYakov, RedOneN, Respx, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Twpony, Waze, Yiko, __141345__, ajtra, apostle0x01, ashiq0x01, asutorufos, bardamu, benbaessler, berndartmueller, bharg4v, bulej93, c3phas, cccz, ch13fd357r0y3r, codexploder, cryptonue, cryptphi, defsec, djxploit, durianSausage, fatherOfBlocks, gogo, hansfriese, horsefacts, ignacio, kyteg, lucacez, mics, rbserver, robee, sashik_eth, simon135, sseefried, tofunmi, xiaoming90
56.1238 USDC - $56.12
Array out-of-bounds access causes a revert without any informative error message (it raises a Panic(0x32)
exception).
Check that an index which is used to access an array element fits the array's boundaries before accessing that array element.
AxelarAuthWeighted.sol
: line 105 (operatorIndex
must be < weights.length
)#0 - GalloDaSballo
2022-09-01T00:20:27Z
The code will revert as intended, I will mark this as Refactoring
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xNazgul, 0xsam, 8olidity, Aymen0909, Bnke0x0, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Fitraldys, JC, Lambda, MiloTruck, Noah3o6, NoamYakov, RedOneN, Respx, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Tomio, Waze, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, benbaessler, bharg4v, bulej93, c3phas, defsec, djxploit, durianSausage, erictee, fatherOfBlocks, gerdusx, gogo, kyteg, lucacez, medikko, mics, owenthurm, oyc_109, rbserver, robee, sashik_eth, simon135, tofunmi
31.8812 USDC - $31.88
There are many for loops that follows this for-each pattern:
for (uint256 i = 0; i < array.length; i++) { // do something with `array[i]` }
In such for loops, the array.length
is read on every iteration, instead of caching it once in a local variable and read it from there. Memory and calldata reads are a bit more expensive than reading local variables.
Read these values from memory or calldata once, cache them in local variables and then read them again from the local variables. For example:
uint256 length = array.length; for (uint256 i = 0; i < length; i++) { // do something with `array[i]` }
AxelarGateway.sol
: line 207AxelarAuthWeighted.sol
: lines 17, 98, 116AxelarDepositService.sol
: lines 114, 168, 204AxelarGasService.sol
: line 123If a variable is not set/initialized, it is assumed to have the default value (0
, false
, 0x0
etc. depending on the data type).
Explicitly initializing it with its default value is an anti-pattern and wastes gas. For example:
uint256 x = 0;
can be optimized to:
uint256 x;
AxelarGateway.sol
: line 207AxelarAuthWeighted.sol
: lines 68, 69, 94, 95, 98Use prefix increments (++x
) instead of postfix increments (x++
).
Change all postfix increments to prefix increments.
AxelarGateway.sol
: line 207AxelarDepositService.sol
: lines 114, 168, 204AxelarGasService.sol
: line 123There is no risk of overflow caused by increments to the iteration index in for loops (the i++
in for (uint256 i = 0; i < numIterations; i++)
). Increments perform overflow checks that are not necessary in this case.
Surround the increment expressions with an unchecked { ... }
block to avoid the default overflow checks. For example, change the loop
for (uint256 i = 0; i < numIterations; i++) { // ... }
to
for (uint256 i = 0; i < numIterations;) { // ... unchecked { i++; } }
It is a little less readable but it saves a significant amount of gas.
AxelarGateway.sol
: lines 195, 207, 292AxelarAuthWeighted.sol
: lines 17, 69, 98, 101, 109, 116AxelarDepositService.sol
: lines 114, 168, 204AxelarGasService.sol
: line 123Testing != 0
is cheaper than testing > 0
for unsigned integers.
Use != 0
instead of > 0
when testing unsigned integers.
AxelarGateway.sol
: lines 255, 613AxelarAuthWeighted.sol
: line 76AxelarDepositService.sol
: line 165ReceiverImplementation.sol
: lines 23, 51, 71AxelarGasService.sol
: lines 128, 131Some functions loads the same array element more than once. In such cases, only one array boundaries check should take place, and the rest are unnecessary. Therefore, this array element should be cached in a local variable and then be loaded again using that local variable, skipping the redundant second array boundaries check and saving gas.
Load the array elements once, cache them in local variables and then read them again using the local variables. For example:
uint256 item = array[i]; // do something with `item` // do some other thing with `item`
AxelarDepositService.sol
: lines 118+121 (refundTokens[i]
), 208+210 (refundTokens[i]
)#0 - GalloDaSballo
2022-08-23T00:59:57Z
300 gas