Platform: Code4rena
Start Date: 18/02/2022
Pot Size: $125,000 USDC
Total HM: 13
Participants: 24
Period: 14 days
Judge: GalloDaSballo
Total Solo HM: 6
Id: 88
League: ETH
Rank: 22/24
Findings: 1
Award: $254.87
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, CertoraInc, TerrierLover, Tomio, WatchPug, d4rk, gzeon, kenta, kyliek, m_smirnova2020, rfa, robee, saian, ye0lde
The following functions check that an uint > 0 but it's always true.
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/
DepositBoxEth.sol#L122
There are several other places throughout the codebase where the same optimization
can be used.
require(approveTransfers[msg.sender] > 0, "User has insufficient ETH");
Manual analysis
Remove the checks.
The functions use prefix increaments (i ++) instead of postfix increaments (++ i). Prefix increaments are cheaper than postfix increaments.
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/
DepositBoxERC721.sol#L76 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/
DepositBoxERC721.sol#L260 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/
DepositBoxERC1155.sol#L79 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/
DepositBoxERC1155.sol#L275
There are several other places throughout the codebase where the same optimization
can be used.
for (uint256 i = 0; i < tokens.length; i++) {
Manual analysis
Change all prefix increaments to postfix increaments where it doesn't affects the
functionality.
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and
will decrease runtime gas when the revert condition has been met. Revert strings that are longer than 32 bytes require at least one additional
mstore, along with additional overhead for computing memory offset, etc.
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L152 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L171 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L186-L190 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L191 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L217 There are several other places throughout the codebase where the same optimization
can be used.
require(address(newCommunityPoolAddress) != address(0), "CommunityPool address has to be set");
Manual analysis
Shorten the revert strings to fit in 32 bytes. Or consider moving to solc 0.8.4 or
greater and use Custom Errors.
For loop indices across the contract functions use explicit 0 initializations which
are not required because the default value of uints is 0. Removing this explicit
unnecessary initialization will save a little gas.
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/Linker.sol#L1
00 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/Linker.sol#L1
49 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/Linker.sol#L1
75 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L118 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/MessageProxyF
orMainnet.sol#L235 There are several other places throughout the codebase where the same optimization
can be used.
for (uint i = 0; i < schainContracts.length; i++) {
Manual analysis
Remove unnecessary initialization of loop index variable
Declaring in the string public schainName` with type bytes32 can save gas.
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/extensions/ERC721Refe
renceMintAndMetadataMainnet.sol#L36
string public schainName;
Manual analysis
Custom errors from Solidity 0.8.4 are cheaper than revert strings. Source: https://blog.soliditylang.org/2021/04/21/custom-errors/: Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to
explain to users why an operation failed through the use of custom errors. Until
now, you could already use strings to give more information about failures (e.g.,
revert("Insufficient funds.");), but they are rather expensive, especially when it
comes to deploy cost, and it is difficult to use dynamic information in them. Custom errors are defined using the error statement, which can be used inside and
outside of contracts (including interfaces and libraries). require(_locked == 0, "LOCKED");
https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/MessageProxy.sol#L117 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/MessageProxy.sol#L125 https://github.com/skalenetwork/ima-c4-
audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/MessageProxy.sol#L133 There are several other places throughout the codebase where the same optimization
can be used.
require(hasRole(CHAIN_CONNECTOR_ROLE, msg.sender), "CHAIN_CONNECTOR_ROLE is required");
Manual analysis
Replace revert strings with custom errors.
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack.Caching the array length in the stack saves around 3 gas per iteration.
https://github.com/skalenetwork/ima-c4-audit/blob/11d6a6ae5bf16af552edd75183791375e501915f/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol#L265 function getFunds( string calldata schainName, address erc1155OnMainnet, address receiver, uint256[] memory ids, uint256[] memory amounts ) external override onlySchainOwner(schainName) whenKilled(keccak256(abi.encodePacked(schainName))) { bytes32 schainHash = keccak256(abi.encodePacked(schainName)); require(ids.length == amounts.length, "Incorrect length of arrays"); for (uint256 i = 0; i < ids.length; i++) {
Manual analysis
Consider to cache array length.
#0 - yavrsky
2022-03-14T14:29:46Z
Only marginal gas improvements.
#1 - GalloDaSballo
2022-04-28T17:36:47Z
Uint can be zero, disagree with this one
3 * 5 = 15 gas saved
5 * 2500 = 12500
5*3 = 15
In lack of explanation I just disagree
Hard to quantify savings in lack of POC
Saves 3 gas per iteration
Total Gas Saved 12518
Formatting of this report was abysmal, would recommend the warden previews their submissions on a markdown reader