Platform: Code4rena
Start Date: 22/09/2023
Pot Size: $100,000 USDC
Total HM: 15
Participants: 175
Period: 14 days
Judge: alcueca
Total Solo HM: 4
Id: 287
League: ETH
Rank: 60/175
Findings: 1
Award: $78.19
š Selected for report: 0
š Solo Findings: 0
š Selected for report: rvierdiiev
Also found by: 0x11singh99, 0xAnah, 0xta, Aamir, DavidGiladi, DevABDee, Eurovickk, JCK, K42, MrPotatoMagic, Pessimistic, Raihan, Rolezn, SM3_SS, SY_S, Sathish9098, Udsen, ayo_dev, blutorque, c3phas, clara, dharma09, hihen, hunter_w3b, jamshed, koxuan, lsaudit, marqymarq10, oualidpro, pfapostol, sivanesh_808, tabriz, wahedtalash77, zabihullahazadzoi, ziyou-
78.1884 USDC - $78.19
Total 27 instances over 5 issueswith 40213 gas saved:
ID | Issue | Instances | Gas |
---|---|---|---|
[Gā01] | Use unchecked block for safe subtractions | 1 | 85 |
[Gā02] | Do not cache state variables that are used only once | 2 | 6 |
[Gā03] | Unlimited gas consumption risk due to external call recipients | 13 | - |
[Gā04] | Use selfbalance() instead of address(x).balance | 9 | 135 |
[Gā05] | Consider using bytes32 rather than a string | 2 | 40000 |
unchecked
block for safe subtractionsIf it can be confirmed that the subtraction operation will not overflow, using an unchecked block can save gas.
For example, require(x <= y); z = y - x;
can be optimized to require(x <= y); unchecked { z = y - x; }
.
There is 1 instance:
/// @audit checked on line 1142 1149: if (_amount - _deposit > 0) {
It's cheaper to access the state variable directly if it is accessed only once. This can save the 3 gas cost of the extra stack allocation.
There are 2 instances:
195: address globalAddress = getGlobalTokenFromLocal[_localAddress][_srcChainId]; 206: address localAddress = getLocalTokenFromGlobal[_globalAddress][_srcChainId];
When calling an external function without specifying a gas limit , the called contract may consume all the remaining gas, causing the tx to be reverted. To mitigate this, it is recommended to explicitly set a gas limit when making low level external calls.
There are 13 instances (click to show):
239: IVirtualAccount(userAccount).call(calls); 248: IVirtualAccount(userAccount).call(calls); 275: IVirtualAccount(userAccount).call(calls); 328: IVirtualAccount(userAccount).call(calls); 337: IVirtualAccount(userAccount).call(calls); 364: IVirtualAccount(userAccount).call(calls); 416: IVirtualAccount(userAccount).call(calls); 425: IVirtualAccount(userAccount).call(calls); 452: IVirtualAccount(userAccount).call(calls);
835: callee.call{value: msg.value}(""); 927: callee.call{value: _value}("");
74: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData); 101: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
selfbalance()
instead of address(x).balance
Use assembly when getting a contract's balance of ETH.
You can use selfbalance()
instead of address(x).balance
when getting your contract's balance of ETH to save gas.
Additionally, you can use balance(address)
instead of address.balance()
when getting an external contract's balance of ETH.
Saves 15 gas when checking internal balance, 6 for external.
There are 9 instances:
717: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata); 737: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata); 787: ILayerZeroEndpoint(lzEndpointAddress).send{value: address(this).balance}(
92: _recipient.safeTransferETH(address(this).balance); 126: _recipient.safeTransferETH(address(this).balance);
695: address(this).balance 754: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata); 779: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata); 940: ILayerZeroEndpoint(lzEndpointAddress).send{value: address(this).balance}(
bytes32
rather than a string
Using the bytes
types for fixed-length strings is more efficient than having the EVM have to incur the overhead of string processing. Consider whether the value needs to be a string
. A good reason to keep it as a string
would be if the variable is defined in an interface that this project does not own.
There are 2 instances:
26: string public chainName; 29: string public chainSymbol;
#0 - c4-pre-sort
2023-10-15T17:07:08Z
0xA5DF marked the issue as sufficient quality report
#1 - c4-judge
2023-10-26T13:47:15Z
alcueca marked the issue as grade-a