G-01: use unchecked when incrementing for loop variable
Since the loop's iterator can't realistically overflow because of the loop's condition, you can increment it in an unchecked block to save gas:
./contracts/auth/AxelarAuthWeighted.sol:17: for (uint256 i; i < recentOperators.length; ++i) {
./contracts/auth/AxelarAuthWeighted.sol:69: for (uint256 i = 0; i < weightsLength; ++i) {
./contracts/auth/AxelarAuthWeighted.sol:98: for (uint256 i = 0; i < signatures.length; ++i) {
./contracts/auth/AxelarAuthWeighted.sol:116: for (uint256 i; i < accounts.length - 1; ++i) {
./contracts/gas-service/AxelarGasService.sol:123: for (uint256 i; i < tokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:114: for (uint256 i; i < refundTokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:168: for (uint256 i; i < refundTokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:204: for (uint256 i; i < refundTokens.length; i++) {
./contracts/AdminMultisigBase.sol:51: for (uint256 i; i < adminCount; ++i) {
./contracts/AdminMultisigBase.sol:158: for (uint256 i; i < adminLength; ++i) {
./contracts/AxelarGateway.sol:195: for (uint256 i; i < adminCount; ++i) {
./contracts/AxelarGateway.sol:207: for (uint256 i = 0; i < symbols.length; i++) {
./contracts/AxelarGateway.sol:293: for (uint256 i; i < commandsLength; ++i) {
./contracts/auth/AxelarAuthWeighted.sol:101: for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {}
Just search for "for (" in your .sol files to find all the relevant instances
G-02: increment using ++i instead of i++ consistently
Using ++i saves gas because you don't have to cache the original value in memory. You already use it in some places but not consistently.
./contracts/gas-service/AxelarGasService.sol:123: for (uint256 i; i < tokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:114: for (uint256 i; i < refundTokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:168: for (uint256 i; i < refundTokens.length; i++) {
./contracts/deposit-service/AxelarDepositService.sol:204: for (uint256 i; i < refundTokens.length; i++) {
./contracts/AxelarGateway.sol:207: for (uint256 i = 0; i < symbols.length; i++) {
G-03: use solmate's ERC20 contract
solmate's contracts are optimized for gas usage. They are more efficient than OZ's contracts. Consider switching to them. It will save gas for all the ERC20 transfers, burns, etc.
G-04: remove unnecessary require statement in XC20Wrapper.sol
In XC20Wrapper.unwrap() the function checks whether the caller has enough tokens to burn before calling the burn() function. But, the burn function will simply revert if the user doesn't have enough. Explicitly checking for that is a waste of gas.
Gas Report
G-01: use unchecked when incrementing for loop variable
Since the loop's iterator can't realistically overflow because of the loop's condition, you can increment it in an unchecked block to save gas:
Just search for "for (" in your
.sol
files to find all the relevant instancesG-02: increment using ++i instead of i++ consistently
Using
++i
saves gas because you don't have to cache the original value in memory. You already use it in some places but not consistently.G-03: use solmate's ERC20 contract
solmate's contracts are optimized for gas usage. They are more efficient than OZ's contracts. Consider switching to them. It will save gas for all the ERC20 transfers, burns, etc.
https://github.com/transmissions11/solmate
G-04: remove unnecessary require statement in XC20Wrapper.sol
In
XC20Wrapper.unwrap()
the function checks whether the caller has enough tokens to burn before calling theburn()
function. But, the burn function will simply revert if the user doesn't have enough. Explicitly checking for that is a waste of gas.https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L85