File: contracts/deposit-service/AxelarDepositService.sol
114: for (uint256 i; i < refundTokens.length; i++) {
168: for (uint256 i; i < refundTokens.length; i++) {
204: for (uint256 i; i < refundTokens.length; i++) {
Functions that are access-restricted from most users may be marked as payable
Marking a function as payable reduces gas cost since the compiler does not have to check whether a payment was provided or not. This change will save around 21 gas per function call.
There are 3 instances of this issue:
File: contracts/auth/AxelarAuthWeighted.sol
47: function transferOperatorship(bytes calldata params) external onlyOwner {
++i/i++ should be unchecked{++I}/unchecked{I++} in for-loops
When an increment or any arithmetic operation is not possible to overflow it should be placed in unchecked{} block. \This is because of the default compiler overflow and underflow safety checks since Solidity version 0.8.0. \In for-loops it saves around 30-40 gas per loop
There are 12 instances of this issue:
File: contracts/auth/AxelarAuthWeighted.sol
17: for (uint256 i; i < recentOperators.length; ++i) {
69: for (uint256 i = 0; i < weightsLength; ++i) {
98: for (uint256 i = 0; i < signatures.length; ++i) {
101: for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {}
116: for (uint256 i; i < accounts.length - 1; ++i) {
File: contracts/AxelarGateway.sol
195: for (uint256 i; i < adminCount; ++i) {
207: for (uint256 i = 0; i < symbols.length; i++) {
292: for (uint256 i; i < commandsLength; ++i) {
File: contracts/deposit-service/AxelarDepositService.sol
114: for (uint256 i; i < refundTokens.length; i++) {
168: for (uint256 i; i < refundTokens.length; i++) {
204: for (uint256 i; i < refundTokens.length; i++) {
Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead
'When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.' \ https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html \ Use a larger size then downcast where needed
Use calldata instead of memory for function parameters
If a reference type function parameter is read-only, it is cheaper in gas to use calldata instead of memory. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory. Try to use calldata as a data location because it will avoid copies and also makes sure that the data cannot be modified.
Replace x <= y with x < y + 1, and x >= y with x > y - 1
In the EVM, there is no opcode for >= or <=. When using greater than or equal, two operations are performed: > and =. Using strict comparison operators hence saves gas
There are 3 instances of this issue:
File: contracts/auth/AxelarAuthWeighted.sol
36: if (operatorsEpoch == 0 || epoch - operatorsEpoch >= OLD_KEY_RETENTION) revert InvalidOperators();
107: if (weight >= threshold) return;
117: if (accounts[i] >= accounts[i + 1]) {
2022-07-AXELAR
Gas Optimizations Report
++i
costs less gas thani++
(same for--i
/i--
)Saves 6 gas per instance/loop
There are 5 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L207
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/AxelarDepositService.sol#L114
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/gas-service/AxelarGasService.sol#L123
public
functions not called by the contract should be declaredexternal
insteadThere are 2 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/AxelarDepositService.sol#L241
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/DepositBase.sol#L41
It costs more gas to initialize non-
constant
/non-immutable
variables to zero than to let the default of zero be appliedNot overwriting the default for stack variables saves 8 gas. Storage and memory variables have larger savings
There are 6 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L68
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L207
Functions that are access-restricted from most users may be marked as
payable
Marking a function as
payable
reduces gas cost since the compiler does not have to check whether a payment was provided or not. This change will save around 21 gas per function call.There are 3 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L47
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L204
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/gas-service/AxelarGasService.sol#L120
++i
/i++
should beunchecked{++I}
/unchecked{I++}
infor
-loopsWhen an increment or any arithmetic operation is not possible to overflow it should be placed in
unchecked{}
block. \This is because of the default compiler overflow and underflow safety checks since Solidity version 0.8.0. \In for-loops it saves around 30-40 gas per loopThere are 12 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L17
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L195
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/AxelarDepositService.sol#L114
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/gas-service/AxelarGasService.sol#L123
Usage of
uint
s/int
s smaller than 32 bytes (256 bits) incurs overhead'When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.' \ https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html \ Use a larger size then downcast where needed
There are 2 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L14
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L332
Use
calldata
instead ofmemory
for function parametersIf a reference type function parameter is read-only, it is cheaper in gas to use calldata instead of memory. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory. Try to use calldata as a data location because it will avoid copies and also makes sure that the data cannot be modified.
There are 33 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L55
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/AxelarGateway.sol#L152
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/AxelarDepositService.sol#L220
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/gas-service/AxelarGasService.sol#L40
Replace
x <= y
withx < y + 1
, andx >= y
withx > y - 1
In the EVM, there is no opcode for
>=
or<=
. When using greater than or equal, two operations are performed:>
and=
. Using strict comparison operators hence saves gasThere are 3 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/auth/AxelarAuthWeighted.sol#L36
Use
immutable
&constant
for state variables that do not change their valueThere are 1 instances of this issue:
https://github.com/code-423n4/2022-07-axelar/tree/main/contracts/deposit-service/DepositBase.sol#L19