Platform: Code4rena
Start Date: 07/04/2022
Pot Size: $50,000 USDC
Total HM: 5
Participants: 19
Period: 5 days
Judge: 0xean
Total Solo HM: 4
Id: 109
League: COSMOS
Rank: 13/19
Findings: 1
Award: $197.36
🌟 Selected for report: 0
🚀 Solo Findings: 0
Using > 0
uses slightly more gas than using != 0
. Use != 0
when comparing uint variables to zero, which cannot hold values below zero
One instance of this gas savings was found https://github.com/code-423n4/2022-04-axelar/blob/main/src/AxelarGateway.sol#L269
grep
Replace > 0
with != 0
to save gas
Using a prefix increment (++i) instead of a postfix increment (i++) saves gas for each loop cycle, so it can have a big gas impact when the loop executes on a large number of elements.
Prefix is used in some for loops, but these locations use postfix:
util/AddressFormat.sol:14: for (uint256 i = 0; i < data.length; i++) { AxelarGatewayMultisig.sol:118: for (uint256 i; i < accounts.length; i++) { AxelarGatewayMultisig.sol:140: for (uint256 i; i < ownerCount; i++) { AxelarGatewayMultisig.sol:181: for (uint256 i; i < accountLength; i++) { AxelarGatewayMultisig.sol:271: for (uint256 i; i < accounts.length; i++) { AxelarGatewayMultisig.sol:293: for (uint256 i; i < operatorCount; i++) { AxelarGatewayMultisig.sol:332: for (uint256 i; i < accountLength; i++) { AxelarGatewayMultisig.sol:495: for (uint256 i; i < signatureCount; i++) { AxelarGatewayMultisig.sol:526: for (uint256 i; i < commandsLength; i++) { AdminMultisigBase.sol:51: for (uint256 i; i < adminCount; i++) { AdminMultisigBase.sol:158: for (uint256 i; i < adminLength; i++) { AxelarGatewaySinglesig.sol:269: for (uint256 i; i < commandsLength; i++) { AxelarGateway.sol:225: for (uint256 i; i < adminCount; i++) {
grep
Use prefix not postfix to increment in a loop
Solidity errors introduced in version 0.8.4 can save gas on revert conditions https://blog.soliditylang.org/2021/04/21/custom-errors/ https://twitter.com/PatrickAlphaC/status/1505197417884528640
Some error messages are used, but many require blocks still exist in the code. Many zero address check instances are in ERC20.sol https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L164 https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L165 https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L184 https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L205 https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L232 https://github.com/code-423n4/2022-04-axelar/blob/main/src/ERC20.sol#L233
Manual analysis
Replace require blocks with new solidity errors described in https://blog.soliditylang.org/2021/04/21/custom-errors/
Identifying a function as payable saves gas. Functions that have the onlyOwner modifier cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas.
There are many functions that have the onlyOwner modifier and can be payable https://github.com/code-423n4/2022-04-axelar/blob/main/src/Ownable.sol#L20 https://github.com/code-423n4/2022-04-axelar/blob/main/src/MintableCappedERC20.sol#L23 https://github.com/code-423n4/2022-04-axelar/blob/main/src/MintableCappedERC20.sol#L31 https://github.com/code-423n4/2022-04-axelar/blob/main/src/BurnableMintableCappedERC20.sol#L48
Manual analysis
Add payable to these functions for gas savings
The comparison operators >= and <= use more gas than >, <, or ==. Replacing the >= and ≤ operators with a comparison operator that has an opcode in the EVM saves gas
This code is in _isSortedAscAndContainsNoDuplicate from AxelarGatewayMultisig is the same as an if/else statement https://github.com/code-423n4/2022-04-axelar/blob/main/src/AxelarGatewayMultisig.sol#L41-L49
function _isSortedAscAndContainsNoDuplicate(address[] memory accounts) internal pure returns (bool) { for (uint256 i; i < accounts.length - 1; ++i) { if (accounts[i] >= accounts[i + 1]) { return false; } } return true; }
A simple comparison can be used for gas savings by reversing the logic. Because this happens in a for loop, the savings may be more noticeable
function _isSortedAscAndContainsNoDuplicate(address[] memory accounts) internal pure returns (bool) { for (uint256 i; i < accounts.length - 1; ++i) { if (accounts[i] < accounts[i + 1]) { return true; } } return false; }
The same gas efficiency can be used in two other places with the same pattern https://github.com/code-423n4/2022-04-axelar/blob/main/src/AxelarGatewayMultisig.sol#L114-L123 https://github.com/code-423n4/2022-04-axelar/blob/main/src/AxelarGatewayMultisig.sol#L267-L276
Manual analysis
Replace the comparison operator and reverse the logic to save gas using the suggestions above
#0 - deluca-mike
2022-04-20T08:16:59Z
Confirmed.
Confirmed.
Confirmed.
Acknowledged, but will not do since it is gas savings at the expense of confusion, readability issues, and the possibilities for ETH to be received.
Disputed. While correct about the gas savings, the proposed changes to the functions would actually break their functionality entirely. Returning true after the first positive test would result ignoring the rest of the data. Specifically, we want to return false for any issue, and only return true if there were no issues.