Platform: Code4rena
Start Date: 12/07/2023
Pot Size: $80,000 USDC
Total HM: 11
Participants: 47
Period: 9 days
Judge: berndartmueller
Total Solo HM: 1
Id: 260
League: ETH
Rank: 42/47
Findings: 1
Award: $19.28
π Selected for report: 0
π Solo Findings: 0
π Selected for report: Sathish9098
Also found by: 0x11singh99, 0xAnah, 0xn006e7, Arz, DavidGiladi, K42, Raihan, ReyAdmirado, Rolezn, SAQ, SM3_SS, SY_S, Walter, dharma09, flutter_developer, hunter_w3b, matrix_0wl, naman1778, petrichor, ybansal2403
19.2767 USDC - $19.28
no | Issue | Instance |
---|---|---|
[G-01] | Using a positive conditional flow to save a NOT opcode | 17 |
[G-02] | Use hardcode address instead address(this) | 24 |
[G-03] | Amounts should be checked for 0 before calling a transfer | 9 |
[G-04] | x += y costs more gas than x = x + y for state variables | 1 |
[G-05] | If statements that use && can be refactored into nested if statements | 6 |
[G-06] | abi.encode() is less efficient than abi.encodePacked() | 30 |
[G-07] | Use constants instead of type(uintx).max | 10 |
[G-08] | Using bools for storage incurs overhead | 6 |
[G-09] | Donβt Initialize Variables with Default Value | 4 |
[G-10] | Use custom errors rather than revert()/require() strings to save gas | 100 |
[G-11] | Using XOR (^) and OR (pipe line) bitwise equivalents | 3 |
[G-12] | Make 3 event parameters indexed when possible | 8 |
[G-13] | Cache state variables outside of loop to avoid reading storage on every iteration | 4 |
[G-14] | With assembly, .call (bool success) transfer can be done gas-optimized | 5 |
[G-15] | Use calldata instead of memory for function arguments that do not get mutated | 10 |
[G-16] | Use do while loops instead of for loops | 1 |
One way to save gas is to use positive conditions instead. For example, instead of writing if (!condition), you can write if (condition == false). This may seem counterintuitive at first, but it can actually save gas because the EVM does not need to perform a separate NOT operation.
296 if (!success) revert SetupFailed();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L296
363 if (!allowOperatorshipTransfer) continue;
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L363
402 if (!success) revert TokenDeployFailed(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L402
446 if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L446
45 if (!signers.isSigner[msg.sender]) revert NotSigner();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L45
55 if (!multisigApprovals[proposalHash]) revert NotApproved();
19 if (!success)
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L19
51 if (!success) revert SetupFailed();
51 if (!success) revert FailedInit();
58 if (!success) revert FailedInit();
82 if (!success) revert SetupFailed();
49 if (!whitelistedSenders[sourceChain][StringToAddress.toAddress(sourceAddress)])
57 if (!whitelistedCallers[sourceChain][interchainProposalCaller])
78 if (!success)
124 if (!remoteAddressValidator.validateSender(sourceChain, sourceAddress)) revert NotRemoteService();
816 if (!success)
866 if (!success)
The statement "Use hardcoded address instead of address(this) to save gas cost" means that using a hardcoded address instead of the address(this) expression can be more gas-efficient when sending or receiving Ether to or from the contract. This is because using the address(this) expression requires additional gas to be consumed to retrieve the address of the current contract, while using a hardcoded address does not.
23 implementationAddress = address(this); 31 if (address(this) == implementationAddress) revert NotProxy();
16 if (nativeValue > address(this).balance) revert InsufficientBalance();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L16
52 deployed = deployedAddress(address(this), salt);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L52
69 return Create3.deployedAddress(address(this), deploySalt);
73 if (msg.sender != address(this)) revert NotSelf(); 374 (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId)); 443 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler))) 449 depositHandler.destroy(address(this)); 543 IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount); 616 return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash)))));
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L73
61 implementation_ = Create3.deployedAddress(address(this), FINAL_IMPLEMENTATION_SALT);
162 tokenManagerAddress = deployer.deployedAddress(address(this), tokenId); 193 tokenAddress = deployer.deployedAddress(address(this), tokenId); 313 _deployTokenManager(tokenId, TokenManagerType.LOCK_UNLOCK, abi.encode(address(this).toBytes(), tokenAddress)); 696 abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress) 716 address(this),
205 tokenId = ITokenManagerProxy(address(this)).tokenId();
46 uint256 balance = token.balanceOf(address(this)); 48 SafeTokenTransferFrom.safeTransferFrom(token, from, address(this), amount); 51 return IERC20(token).balanceOf(address(this)) - balance;
19 implementationAddress = address(this);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L19
27 if (implementationAddress == address(this)) revert NotProxy();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L27
25 (bool success, bytes memory result) = address(this).delegatecall(data[i]);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L25
38 bytes memory args = abi.encode(address(this), implementationType, tokenId, params);
it is generally a good practice to check the amount for 0 before calling a transfer function in order to save gas. This is because if the amount is 0, there is no need to execute the transfer function, which can save gas costs.
524 IERC20(tokenAddress).safeTransfer(account, amount);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L524
66 tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
104 tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
451 SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);
482 SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);
82 SafeTokenTransferFrom.safeTransferFrom(token, from, liquidityPool_, amount);
98 SafeTokenTransferFrom.safeTransferFrom(token, liquidityPool(), to, amount);
48 SafeTokenTransferFrom.safeTransferFrom(token, from, address(this), amount);
64 SafeTokenTransfer.safeTransfer(token, to, amount);
107 totalGas += interchainCalls[i].gas;
In Solidity, using nested if statements can sometimes save gas compared to using the logical AND (&&) operator within a single if statement. When you use the AND operator, the EVM needs to evaluate both conditions before proceeding with the code block inside the if statement. This means that if the first condition is false, the second condition is still evaluated, even if it is also false. This can lead to unnecessary gas consumption.
88 if (msg.sender != getAddress(KEY_MINT_LIMITER) && msg.sender != getAddress(KEY_GOVERNANCE)) revert NotMintLimiter();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L88
446 if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L446
635 if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L635
50 if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();
33 if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L33
58 if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32));
abi.encode() is a more versatile function that can handle multiple arguments of different types. It is used to encode data for function calls, among other things. abi.encodePacked() is a more specialized function that is used specifically for concatenating data into a single byte array. It is commonly used when you need to pack multiple values together into a single value.
203 tokenId = keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_ID, chainNameHash, tokenAddress)); 214 tokenId = keccak256(abi.encode(PREFIX_CUSTOM_TOKEN_ID, sender, salt)); 242 params = abi.encode(operator, tokenAddress); 252 params = abi.encode(operator, tokenAddress); 267 params = abi.encode(operator, tokenAddress, liquidityPoolAddress); 313 _deployTokenManager(tokenId, TokenManagerType.LOCK_UNLOCK, abi.encode(address(this).toBytes(), tokenAddress)); 401 _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress)); 512 payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount); 520 payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata); 696 abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress) 755 bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params); 780 bytes memory payload = abi.encode( 828 return keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_SALT, tokenId));
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L203 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L214 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L242 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L252 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L267 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L313 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L401 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L512 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L520 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L696 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L755 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L780 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L828
32 slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId))) 57 abi.encode(
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L32 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L57
47 slot = uint256(keccak256(abi.encode(PREFIX_FLOW_OUT_AMOUNT, epoch))); 56 slot = uint256(keccak256(abi.encode(PREFIX_FLOW_IN_AMOUNT, epoch)));
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L47
62 bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo); 63 bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params));
38 bytes memory args = abi.encode(address(this), implementationType, tokenId, params);
562 return keccak256(abi.encode(PREFIX_TOKEN_MINT_AMOUNT, symbol, day)); 584 return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); 597 keccak256( abi.encode( PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT, commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount ) );
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L562
25 deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt))); 47 deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt))); 63 bytes32 newSalt = keccak256(abi.encode(sender, salt));
30 bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); 54 bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); 68 bytes32 deploySalt = keccak256(abi.encode(sender, salt));
66 emit ProposalExecuted(keccak256(abi.encode(sourceChain, sourceAddress, interchainProposalCaller, payload)));
89 bytes memory payload = abi.encode(msg.sender, interchainCall.calls);
Using constants instead of type(uintX).max can be an effective way to optimize gas costs in Solidity contracts. type(uintX).max is a built-in constant in Solidity that represents the maximum value that can be stored in a variable of size X bits. However, this constant can be expensive in terms of gas cost, particularly for large values of X, because it requires a lot of computational steps to calculate the result.
79 if (commandId > uint256(type(ServiceGovernanceCommand).max))
120 if (commandId > uint256(type(GovernanceCommand).max))
56 if (allowance_ != type(uint256).max) { 57 if (allowance_ > type(uint256).max - amount) { 58 allowance_ = type(uint256).max - amount; 88 if (_allowance != type(uint256).max) 95 if (allowance_ != type(uint256).max) { 96 if (allowance_ > type(uint256).max - amount) { 97 allowance_ = type(uint256).max - amount;
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L56 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L57 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L58 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L88 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L95 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L96 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L97
104 if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();
In Solidity, using bool variables for storage can incur additional overhead, which can result in higher gas costs. This is because each bool variable in storage takes up one full 32-byte storage slot, even though it only needs one bit to represent its value.
15 mapping(address => bool) hasVoted; 21 mapping(address => bool) isSigner;
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L15 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L21
22 mapping(bytes32 => bool) public multisigApprovals;
24 mapping(string => mapping(address => bool)) public whitelistedCallers; 27 mapping(string => mapping(address => bool)) public whitelistedSenders;
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L24 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L27
19 mapping(string => bool) public supportedByGateway;
In Solidity, initializing variables with their default values can result in unnecessary gas consumption. This is because the Solidity compiler automatically initializes all variables to their default values, which is zero for most types.
74 for (uint256 i = 0; i < calls.length; i++)
63 for (uint256 i = 0; i < interchainCalls.length; ) 106 for (uint256 i = 0; i < interchainCalls.length; )
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L63 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L106
24 for (uint256 i = 0; i < data.length; ++i)
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L24
using custom errors can be more gas-efficient than using strings with the revert() or require() functions. This is because strings are variable-length and can take up a significant amount of space in the contract's bytecode, leading to higher gas costs. Custom errors, on the other hand, are defined as static variables or constants in the contract and do not take up extra space in the bytecode. Using custom errors can also make your code more readable and easier to maintain, as it allows you to define and reuse meaningful error messages throughout your contract.
```solidity 65 if (authModule_.code.length == 0) revert InvalidAuthModule(); 66 if (tokenDeployerImplementation_.code.length == 0) revert InvalidTokenDeployer(); 73 if (msg.sender != address(this)) revert NotSelf(); 79 if (msg.sender != getAddress(KEY_GOVERNANCE)) revert NotGovernance(); 255 if (newGovernance == address(0)) revert InvalidGovernance(); 261 if (newMintLimiter == address(0)) revert InvalidMintLimiter(); 268 if (length != limits.length) revert InvalidSetMintLimitsParams(); 274 if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol); 285 if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash(); 296 if (!success) revert SetupFailed(); 309 if (implementation() == address(0)) revert NotProxy(); 338 if (chainId != block.chainid) revert InvalidChainId(); 342 if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands(); 392 if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol); 402 if (!success) revert TokenDeployFailed(symbol); 409 if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress); 432 if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); 446 if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol); 519 if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); 537 if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); 538 if (amount == 0) revert InvalidAmount(); 635 if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L65
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L635
45 if (!signers.isSigner[msg.sender]) revert NotSigner(); 51 if (voting.hasVoted[msg.sender]) revert AlreadyVoted(); 159 if (newThreshold > length) revert InvalidSigners(); 161 if (newThreshold == 0) revert InvalidSignerThreshold(); 172 if (signers.isSigner[account]) revert DuplicateSigner(account); 173 if (account == address(0)) revert InvalidSigners();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L45 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L51 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L159 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L161 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L172 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L173
55 if (!multisigApprovals[proposalHash]) revert NotApproved(); 80 revert InvalidCommand();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L55 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L80
93 revert NotGovernance(); 100 if (target == address(0)) revert InvalidTarget(); 121 revert InvalidCommand(); 162 revert TokenNotSupported();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L93 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L100 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L121 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L162
16 if (nativeValue > address(this).balance) revert InsufficientBalance(); 20 revert ExecutionFailed();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L16 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L20
14 if (owner() != msg.sender) revert NotOwner(); 25 if (newOwner == address(0)) revert InvalidOwner(); 46 if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash(); 51 if (!success) revert SetupFailed(); 63 if (implementation() == address(0)) revert NotProxy();
51 if (!success) revert FailedInit(); 81 if (bytecode.length == 0) revert EmptyBytecode(); 88 if (deployedAddress_ == address(0)) revert FailedDeploy();
file: contracts/gmp-sdk/deploy/Create3.sol 54 if (deployed.isContract()) revert AlreadyDeployed(); 55 if (bytecode.length == 0) revert EmptyBytecode(); 60 if (address(deployer) == address(0)) revert DeployFailed();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L54
58 if (!success) revert FailedInit();
77 if (msg.sender != owner) revert NotOwner(); 82 if (!success) revert SetupFailed();
46 if (msg.sender != owner) revert NotOwner(); 47 if (implementation() != address(0)) revert AlreadyInitialized(); 50 if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation(); 59 if (!success) revert SetupFailed();
30 if (owner == address(0)) revert InvalidOwner(); 33 if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation(); 42 if (!success) revert SetupFailed();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L30
31 if (address(this) == implementationAddress) revert NotProxy(); 57 if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation(); 58 if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash(); 63 if (!success) revert SetupFailed();
51 if (hash == 0) revert InvalidTimeLockHash(); 52 if (_getTimeLockEta(hash) != 0) revert TimeLockAlreadyScheduled(); 68 if (hash == 0) revert InvalidTimeLockHash(); 82 if (hash == 0 || eta == 0) revert InvalidTimeLockHash(); 84 if (block.timestamp < eta) revert TimeLockNotReady();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L51
50 revert NotWhitelistedSourceAddress(); 58 revert NotWhitelistedCaller(); 164 revert(add(32, result), mload(result)) 168 revert ProposalExecuteFailed();
97 revert ZeroAddress(); 104 revert LengthMismatch(); 124 revert NotRemoteService(); 133 revert NotTokenManager(); 172 revert TokenManagerDoesNotExist(tokenId); 311 if (gateway.tokenAddresses(tokenSymbol) == tokenAddress) revert GatewayToken(); 332 if (getCanonicalTokenId(tokenAddress) != tokenId) revert NotCanonicalTokenManager(); 445 if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId); 476 if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId); 519 if (version > 0) revert InvalidMetadataVersion(version); 536 if (length != flowLimits.length) revert LengthMismatch(); 565 if (implementation == address(0)) revert ZeroAddress(); 566 if (ITokenManager(implementation).implementationType() != uint256(tokenManagerType)) revert InvalidTokenManagerImplementation(); 590 revert SelectorUnknown(); 817 revert TokenManagerDeploymentFailed(); 867 revert StandardizedTokenDeploymentFailed();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L97 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L867
18 if (bytesAddress.length != 20) revert InvalidBytesLength(bytesAddress);
22 if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation(); 25 if (!success) revert SetupFailed();if (!success) revert SetupFailed();
28 if (_interchainTokenServiceAddress == address(0)) revert ZeroAddress(); 43 if (length != trustedAddresses.length) revert LengthMismatch(); 84 if (bytes(chain).length == 0) revert ZeroStringLength(); 85 if (bytes(addr).length == 0) revert ZeroStringLength(); 96 if (bytes(chain).length == 0) revert ZeroStringLength();
28 if (interchainTokenService_ == address(0)) revert TokenLinkerZeroAddress(); 36 if (msg.sender != address(interchainTokenService)) revert NotService(); 44 if (msg.sender != tokenAddress()) revert NotToken();
91 if (prevExpressCaller != address(0)) revert AlreadyExpressCalled(); 133 if (prevExpressCaller != address(0)) revert AlreadyExpressCalled();
101 if (flowToAdd + flowAmount > flowToCompare + flowLimit) revert FlowLimitExceeded();
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L101
342 if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands(); 446 if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L342 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L446
92 if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash)
8 event DistributorChanged(address distributor);
8 event FlowLimitSet(uint256 flowLimit);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IFlowLimit.sol#L8
8 event OperatorChanged(address operator);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IOperatable.sol#L8
11 event PausedSet(bool paused);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IPausable.sol#L11
14 event TrustedAddressAdded(string souceChain, string sourceAddress); 15 event TrustedAddressRemoved(string souceChain); 16 event GatewaySupportedChainAdded(string chain); 17 event GatewaySupportedChainRemoved(string chain);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L14 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L15 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L16 https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L17
Caching state variables outside of a loop can be an effective way to optimize gas costs in Solidity contracts. In Solidity, reading state variables from storage can be expensive in terms of gas cost, particularly if the state variable is large or complex. This is because reading from storage requires loading data from the storage to memory, which can be slow and costly.
108 for (uint256 i; i < length; ++i) { string calldata chainName = chainNames[i]; supportedByGateway[chainName] = true; emit GatewaySupportedChainAdded(chainName); } 119 function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner { uint256 length = chainNames.length; for (uint256 i; i < length; ++i) { string calldata chainName = chainNames[i]; supportedByGateway[chainName] = false; emit GatewaySupportedChainRemoved(chainName); } }
122 for (uint256 i; i < length; ++i) { if (votingPerTopic[signerEpoch][topic].hasVoted[signers.accounts[i]]) { voteCount++; } }
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L122-L125
70 for (uint256 i; i < count; ++i) { voting.hasVoted[signers.accounts[i]] = false; }
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L70-L73
the transfer() function is commonly used to transfer ether from one address to another. However, the transfer() function is known to be relatively expensive in terms of gas cost, particularly when transferring large amounts of ether.
374 (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId));
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L374
18 (bool success, ) = target.call{ value: nativeValue }(callData);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L18
50 (bool success, ) = deployedAddress_.call(init);
57 (bool success, ) = deployedAddress_.call(init);
76 (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData);
142 function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners 149 function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L142
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149
73 function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external;
42 function deployAndInit( bytes memory bytecode, bytes32 salt, bytes calldata init ) external returns
21 function deploy(bytes memory bytecode) external
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L21
73 function _executeProposal(InterchainCalls.Call[] memory calls) internal
15 function sendProposals(InterchainCalls.InterchainCall[] memory calls) external payable;
559 function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType)
18 function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IMulticall.sol#L18
22 function multicall(bytes[] calldata data) public payable returns (bytes[] memory results)
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L22
270 for (uint256 i; i < length; ++i) { string memory symbol = symbols[i]; uint256 limit = limits[i]; if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol); _setTokenMintLimit(symbol, limit); }
https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L270-L277
#0 - c4-judge
2023-09-04T19:23:07Z
berndartmueller marked the issue as grade-b