Skip to content

Instantly share code, notes, and snippets.

@thebrittfactor
Created July 13, 2023 16:22
Show Gist options
  • Save thebrittfactor/c400e0012d0092316699c53843ecad41 to your computer and use it in GitHub Desktop.
Save thebrittfactor/c400e0012d0092316699c53843ecad41 to your computer and use it in GitHub Desktop.
Lightchaser-axelar.md

Winning bot race submission

This is the top-ranked automated findings report, from warden ChasetheLights's LightChaser bot. All findings in this report will be considered known issues for the purposes of your C4 audit.

Report Generated for: Code4rena

Generated on: 2023-07-12

Total findings: 113

Total GAS findings: 30

Total NC findings: 48

Total LOW findings: 28

Total MEDIUM findings: 6

Total HIGH findings: 1

Summary for HIGH findings

Number Details Instances
[HIGH-1] Contract contains payable multicall 2

Summary for MEDIUM findings

Number Details Instances
[MEDIUM-1] Privileged functions can create points of failure 25
[MEDIUM-2] Contracts are vulnerable to fee-on-transfer accounting-related issues 4
[MEDIUM-3] Gas grief possible on unsafe external calls 15
[MEDIUM-5] If statement with missing revert keyword 1763
[MEDIUM-6] NFT minting can allow JSON Injection 19
[MEDIUM-7] Remaining eth may not be refunded to users 4

Summary for LOW findings

Number Details Instances
[LOW-1] Low level calls in solidity versions preceding 0.8.14 can result in an optimiser bug 36
[LOW-2] Empty receive functions can cause gas issues 5
[LOW-3] The call abi.encodeWithSelector is not type safe 12
[LOW-4] Upgradable contracts should have a __gap variable 2
[LOW-6] Double type casts create complexity within the code 3
[LOW-7] Use SafeCast to safely downcast variables 6
[LOW-8] Upgradable contracts should have an initialization function 2
[LOW-9] Functions which set address state variables should have zero address checks 15
[LOW-10] Max allowance is not compatible with all tokens 2
[LOW-11] Function calls within for loops 11
[LOW-12] For loops in public or external functions should be avoided due to high gas costs and possible DOS 7
[LOW-14] Minting to the zero address should be avoided 4
[LOW-15] Contracts do not use their OZ upgradable counterparts 1
[LOW-16] Contract inherits Pausable but does not expose pausing/unpausing functionality 2
[LOW-17] Loss of precision 4
[LOW-18] Missing zero address check in constructor 18
[LOW-19] Use of onlyOwner functions can be lost 1
[LOW-20] Using zero as a parameter 6
[LOW-21] Solidity version 0.8.20 won't work on all chains due to PUSH0 73
[LOW-22] increase/decrease allowance should be used instead of approve 3
[LOW-23] Contract existence is not checked before low level call 2
[LOW-24] Storage Write Removal Bug On Conditional Early Termination 2
[LOW-25] Functions calling contracts/addresses with transfer hooks are missing reentrancy guards 2
[LOW-26] Revert on Transfer to the Zero Address 5
[LOW-27] Two or more functions contain the exact same code 27
[LOW-28] Constructors contains no validation 7
[LOW-29] Utilizing delegatecall within a loop 1
[LOW-30] Must approve or increase allowance first 7

Summary for NC findings

Number Details Instances
[NC-1] Floating pragma should be avoided 73
[NC-2] Empty function blocks 7
[NC-3] In functions which accept an address as a parameter, there should be a zero address check to prevent bugs 74
[NC-4] Default int values are manually set 2
[NC-5] Default address values are manually set 1
[NC-6] Keccak state variables should be immutable not constant 23
[NC-7] Zero address checks should be present in constructors which take address(es) as parameters 23
[NC-8] Ownable2Step should be used in place of Ownable 1
[NC-9] Functions which are either private or internal should have a preceding _ in their name 7
[NC-10] Private and internal state variables should have a preceding _ in their name unless they are constants 9
[NC-11] Contract lines should not be longer than 110 characters for readability 113
[NC-12] Use newer solidity versions 145
[NC-13] Explicitly define visibility of state variables to prevent misconceptions on what can access the variable 1
[NC-14] Function names should differ to make the code more readable 48
[NC-15] Functions should not be longer than 50 lines 1
[NC-16] It is standard for all external and public functions to be override from an interface 67
[NC-17] Functions within contracts are not ordered according to the solidity style guide 11
[NC-18] Emits without msg.sender parameter 13
[NC-19] Functions with array parameters should have length checks in place 3
[NC-20] Interface imports should be declared first 76
[NC-21] Upgradable contract contractors should have the initialize modifier 2
[NC-22] A function which defines named returns in it's declaration doesn't need to use return 4
[NC-23] Constant state variables defined more than once 8
[NC-24] Multiple mappings can be replaced with a single struct mapping 6
[NC-25] Using abi.encodePacked can result in hash collision when used in hashing functions 21
[NC-26] Constants should be on the left side of the 11
[NC-27] Defined named returns not used within function 30
[NC-28] Both immutable and constant state variables should be CONSTANT_CASE 19
[NC-29] Consider using named mappings 6
[NC-30] Use a single file for system wide constants 40
[NC-31] Functions with unused parameters 13
[NC-32] Default address(0) can be returned 30
[NC-33] Critical functions should be a two step procedure 33
[NC-34] Variables should be used in place of magic numbers to improve readability 2
[NC-35] Utility contracts can be made into libraries 6
[NC-36] Address values should be used through variables rather than used as literals 4
[NC-37] Use immutable not constant for keccak state variables 21
[NC-38] Unused errors present 1
[NC-39] Consider adding emergency-stop functionality 35
[NC-40] Employ Explicit Casting to Bytes or Bytes32 for Enhanced Code Clarity and Meaning 18
[NC-41] Custom error has no error details 4
[NC-42] Strings should use double quotes rather than single quotes 138
[NC-43] Large or complicated code bases should implement invariant tests 1
[NC-44] Some if-statement can be converted to a ternary 1
[NC-45] File is missing NatSpec 20
[NC-46] Addresses shouldn't be hard-coded 5
[NC-47] Empty bytes check is missing 99
[NC-48] Consider adding a time delay to upgrade implementation functions 2

Summary for GAS findings

Number Details Instances Gas
[GAS-1] The use of a logical AND in place of double if is slightly less gas efficient in instances where there isn't a corresponding else statement for the given if statement 5 75
[GAS-2] Calling .length in a for loop wastes gas 3 291
[GAS-3] ++X costs slightly less gas than X++ (same with --) 3 15
[GAS-4] Internal functions never used once can be removed 4 -
[GAS-5] Internal functions only used once can be inlined so save gas 31 930
[GAS-6] Public functions not used internally can be marked as external to save gas 15 -
[GAS-7] Solidity version 0.8.19 is more gas efficient 73 73000
[GAS-8] bytes.concat() can be used in place of abi.encodePacked 3 -
[GAS-9] Constructors can be marked as payable to save deployment gas 27 -
[GAS-10] Usage of smaller uint/int types causes overhead 14 770
[GAS-11] Avoid updating storage when the value hasn't changed 32 25600
[GAS-12] Use != 0 instead of > 0 8 24
[GAS-13] Integer increments by one can be unchecked to save on gas fees 14 1680
[GAS-14] Default bool values are manually reset 8 -
[GAS-15] <= or >= is more efficient than < or > 1 3
[GAS-16] State variables used within a function more than once should be cached to save gas 34 3400
[GAS-17] Mappings used within a function more than once should be cached to save gas 3 300
[GAS-18] Use assembly to check for the zero address 18 -
[GAS-19] Use storage instead of memory for structs/arrays 7 29400
[GAS-20] Divisions which do not divide by -X cannot overflow or overflow so such operations can be unchecked to save gas 6 -
[GAS-21] State variables which are not modified within functions should be set as constants or immutable for values set at deployment 3 -
[GAS-22] Use assembly to calculate hashes to save gas 42 3360
[GAS-23] Redundant else statement 1 -
[GAS-24] Unbounded Gas Consumption Risk Due to External Call Recipients 4 -
[GAS-25] Consider activating via-ir for deploying 73 18250
[GAS-26] The result of a function call should be cached rather than re-calling the function 9 900
[GAS-27] Private functions used once can be inlined 1 -
[GAS-28] Use bitmap to save gas 10 700
[GAS-29] Use assembly hashing 38 -
[GAS-30] Consider merging sequential for loops 2 -

[HIGH-1] Contract contains payable multicall

Number of instances found

2

Resolution

Incorporating multiple delegate calls or ordinary calls in a single payable function can pose significant security risks, especially concerning the potential drainage of funds. Each call in a function can potentially make use of msg.value (the amount of Ether sent with the function call), and if there's no explicit control over the division of msg.value across these calls, a user could intentionally or inadvertently trigger a condition where funds are drained from the contract in unexpected ways.

To mitigate these risks, it's crucial to implement rigorous checks and explicit control mechanisms over how msg.value is used. This may involve ensuring that msg.value is divided as intended across multiple calls or including checks to prevent recursive or reentrant calls. Additionally, using a 'pull over push' payment design can also provide added security, wherein instead of the contract sending out payments, recipients request withdrawals. This method can limit the amount of Ether that leaves the contract during a single function call and provide better control over funds.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L22-L25

22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
23:         results = new bytes[](data.length);
24:         for (uint256 i = 0; i < data.length; ++i) { // <= FOUND
25:             (bool success, bytes memory result) = address(this).delegatecall(data[i]); // <= FOUND
26: 
27:             if (!success) {
28:                 revert(string(result));
29:             }
30: 
31:             results[i] = result;
32:         }
33:     }

[MEDIUM-1] Privileged functions can create points of failure

Number of instances found

25

Resolution

Ensure such accounts are protected and consider implementing multi sig to prevent a single point of failure

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L96-L96

92:     function setWhitelistedProposalCaller(
93:         string calldata sourceChain,
94:         address sourceCaller,
95:         bool whitelisted
96:     ) external override onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L111-L111

107:     function setWhitelistedProposalSender(
108:         string calldata sourceChain,
109:         address sourceSender,
110:         bool whitelisted
111:     ) external override onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L56-L56

52:     function upgrade(
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L547-L547

547:     function setPaused(bool paused) external onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L83-L83

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L95-L95

95:     function removeTrustedAddress(string calldata chain) external onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L106-L106

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L119-L119

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L161-L161

161:     function getTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L170-L170

170:     function getValidTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L343-L345

343:     function deployCustomTokenManager( // <= FOUND
344:         bytes32 salt,
345:         TokenManagerType tokenManagerType, // <= FOUND
346:         bytes memory params
347:     ) public payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L365-L368

365:     function deployRemoteCustomTokenManager( // <= FOUND
366:         bytes32 salt,
367:         string calldata destinationChain,
368:         TokenManagerType tokenManagerType, // <= FOUND
369:         bytes calldata params,
370:         uint256 gasValue
371:     ) external payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L509-L509

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType) // <= FOUND
560:         internal
561:         pure
562:         returns (address implementation)
563:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L666-L666

666:     function _processDeployTokenManagerPayload(bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L678-L678

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L748-L752

748:     function _deployRemoteTokenManager( // <= FOUND
749:         bytes32 tokenId,
750:         string calldata destinationChain,
751:         uint256 gasValue,
752:         TokenManagerType tokenManagerType, // <= FOUND
753:         bytes memory params
754:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L808-L810

808:     function _deployTokenManager( // <= FOUND
809:         bytes32 tokenId,
810:         TokenManagerType tokenManagerType, // <= FOUND
811:         bytes memory params
812:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L40-L40

40:     function getTokenManager() public view override returns (ITokenManager)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L8-L8

8:     function tokenManagerRequiresApproval() public pure override returns (bool)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L33-L33

33:     function deployTokenManager( // <= FOUND
34:         bytes32 tokenId,
35:         uint256 implementationType,
36:         bytes calldata params
37:     ) external payable 

[MEDIUM-2] Contracts are vulnerable to fee-on-transfer accounting-related issues

Number of instances found

4

Resolution

The below-listed functions use transferFrom() to move funds from the sender to the recipient but fail to verify if the received token amount matches the transferred amount. This could pose an issue with fee-on-transfer tokens, where the post-transfer balance might be less than anticipated, leading to balance inconsistencies. There might be subsequent checks for a second transfer, but an attacker might exploit leftover funds (such as those accidentally sent by another user) to gain unjustified credit. A practical solution is to gauge the balance prior and post-transfer, and consider the differential as the transferred amount, instead of the predefined amount.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L542-L546

529:     function _burnTokenFrom(
530:         address sender,
531:         string memory symbol,
532:         uint256 amount
533:     ) internal {
534:         address tokenAddress = tokenAddresses(symbol);
535: 
536:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
537:         if (amount == 0) revert InvalidAmount();
538: 
539:         TokenType tokenType = _getTokenType(symbol);
540: 
541:         if (tokenType == TokenType.External) {
542:             IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount); // <= FOUND
543:         } else if (tokenType == TokenType.InternalBurnableFrom) {
544:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount));
545:         } else {
546:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount); // <= FOUND
547:             IBurnableMintableCappedERC20(tokenAddress).burn(bytes32(0));
548:         }
549:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L451-L451

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external {
445:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
446: 
447:         address caller = msg.sender;
448:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
449:         IERC20 token = IERC20(tokenManager.tokenAddress());
450: 
451:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
452: 
453:         _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);
454:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L482-L482

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external {
476:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
477: 
478:         address caller = msg.sender;
479:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
480:         IERC20 token = IERC20(tokenManager.tokenAddress());
481: 
482:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
483: 
484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);
485: 
486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
487:     }

[MEDIUM-3] Gas grief possible on unsafe external calls

Number of instances found

15

Resolution

In Solidity, the use of low-level call methods can expose contracts to gas griefing attacks. The potential problem arises when the callee contract returns a large amount of data. This data is allocated in the memory of the calling contract, which pays for the gas costs. If the callee contract intentionally returns an enormous amount of data, the gas costs can skyrocket, causing the transaction to fail due to an Out of Gas error. Therefore, it's advisable to limit the use of call when interacting with untrusted contracts, or ensure that the callee's returned data size is capped or known in advance to prevent unexpected high gas costs.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L373

322:     function execute(bytes calldata input) external override { // <= FOUND
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId)); // <= FOUND
374: 
375:             if (success) emit Executed(commandId);
376:             else _setCommandExecuted(commandId, false);
377:         }
378:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L50-L50

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) {
47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));
48: 
49:         
50:         (bool success, ) = deployedAddress_.call(init); // <= FOUND
51:         if (!success) revert FailedInit();
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L57-L57

49:     function deployAndInit(
50:         bytes memory bytecode,
51:         bytes32 salt,
52:         bytes calldata init
53:     ) external returns (address deployedAddress_) {
54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));
55:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
56: 
57:         (bool success, ) = deployedAddress_.call(init); // <= FOUND
58:         if (!success) revert FailedInit();
59: 
60:         emit Deployed(keccak256(bytecode), salt, deployedAddress_);
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L853-L853
```javascript
841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals,
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal {
850:         bytes32 salt = _getStandardizedTokenSalt(tokenId);
851:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
852: 
853:         (bool success, ) = standardizedTokenDeployer.delegatecall( // <= FOUND
854:             abi.encodeWithSelector(
855:                 IStandardizedTokenDeployer.deployStandardizedToken.selector,
856:                 salt,
857:                 tokenManagerAddress,
858:                 distributor,
859:                 name,
860:                 symbol,
861:                 decimals,
862:                 mintAmount,
863:                 mintTo
864:             )
865:         );
866:         if (!success) {
867:             revert StandardizedTokenDeploymentFailed();
868:         }
869:         emit StandardizedTokenDeployed(tokenId, name, symbol, decimals, mintAmount, mintTo);
870:     }

[MEDIUM-6] NFT minting can allow JSON Injection

Number of instances found

19

Resolution

Reason: JSON injection in NFT metadata can create various vulnerabilities and manipulation tactics in the NFT ecosystem. The metadata of NFTs, often stored off-chain and referenced by URI, could be manipulated through JSON injection if unsanitized inputs are allowed. This could alter the visual representation of an NFT on platforms and mislead buyers or impact the perceived value of the asset.

Resolution: To protect against JSON injection, the metadata processing system should properly sanitize and validate all inputs. Smart contracts should not handle this task due to their limitations. Instead, robust off-chain server code should manage the processing, using tools designed to prevent JSON injection such as input validation, escaping special characters, and utilizing secure JSON parsing libraries. In addition, implementing strict access control to the metadata storage can further safeguard against unauthorized changes.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L841-L869

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name, // <= FOUND
845:         string memory symbol, // <= FOUND
846:         uint8 decimals,
847:         uint256 mintAmount, // <= FOUND
848:         address mintTo // <= FOUND
849:     ) internal {
850:         bytes32 salt = _getStandardizedTokenSalt(tokenId);
851:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
852: 
853:         (bool success, ) = standardizedTokenDeployer.delegatecall(
854:             abi.encodeWithSelector(
855:                 IStandardizedTokenDeployer.deployStandardizedToken.selector,
856:                 salt,
857:                 tokenManagerAddress,
858:                 distributor,
859:                 name, // <= FOUND
860:                 symbol, // <= FOUND
861:                 decimals,
862:                 mintAmount, // <= FOUND
863:                 mintTo // <= FOUND
864:             )
865:         );
866:         if (!success) {
867:             revert StandardizedTokenDeploymentFailed();
868:         }
869:         emit StandardizedTokenDeployed(tokenId, name, symbol, decimals, mintAmount, mintTo); 
870:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L388-L397

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name, // <= FOUND
391:         string calldata symbol, // <= FOUND
392:         uint8 decimals,
393:         uint256 mintAmount, // <= FOUND
394:         address distributor
395:     ) external payable notPaused {
396:         bytes32 tokenId = getCustomTokenId(msg.sender, salt);
397:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, mintAmount, msg.sender); // <= FOUND
398:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
399:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
400:         address tokenAddress = getStandardizedTokenAddress(tokenId);
401:         _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress));
402:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L49-L62

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name, // <= FOUND
54:         string calldata symbol, // <= FOUND
55:         uint8 decimals,
56:         uint256 mintAmount, // <= FOUND
57:         address mintTo // <= FOUND
58:     ) external payable {
59:         bytes memory bytecode;
60:         address implementationAddress = distributor == tokenManager ? implementationMintBurnAddress : implementationLockUnlockAddress;
61:         {
62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo); // <= FOUND
63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params));
64:         }
65:         address tokenAddress = deployer.deploy(bytecode, salt);
66:         if (tokenAddress.code.length == 0) revert TokenDeploymentFailed();
67:     }

[MEDIUM-7] Remaining eth may not be refunded to users

Number of instances found

4

Resolution

When a contract function accepts Ethereum and executes a .call() or similar function that also forwards Ethereum value, it's important to check for and refund any remaining balance. This is because some of the supplied value may not be used during the call execution due to gas constraints, a revert in the called contract, or simply because not all the value was needed.

If you do not account for this remaining balance, it can become "locked" in the contract. It's crucial to either return the remaining balance to the sender or handle it in a way that ensures it is not permanently stuck. Neglecting to do so can lead to loss of funds and degradation of the contract's reliability. Furthermore, it's good practice to ensure fairness and trust with your users by returning unused funds.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L11-L18

11:     function _call(
12:         address target,
13:         bytes calldata callData,
14:         uint256 nativeValue
15:     ) internal {
16:         if (nativeValue > address(this).balance) revert InsufficientBalance();
17: 
18:         (bool success, ) = target.call{ value: nativeValue }(callData); // <= FOUND
19:         if (!success) {
20:             revert ExecutionFailed();
21:         }
22:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L73-L76

73:     function _executeProposal(InterchainCalls.Call[] memory calls) internal {
74:         for (uint256 i = 0; i < calls.length; i++) {
75:             InterchainCalls.Call memory call = calls[i];
76:             (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData); // <= FOUND
77: 
78:             if (!success) {
79:                 _onTargetExecutionFailed(call, result);
80:             } else {
81:                 _onTargetExecuted(call, result);
82:             }
83:         }
84:     }

[LOW-1] Low level calls in solidity versions preceding 0.8.14 can result in an optimiser bug

Number of instances found

36

Resolution

In Solidity versions 0.8.13 and 0.8.14, a known optimizer bug presents potential risks when a variable is used in a separate assembly block from the one in which it was stored. Specifically, the 'mstore' operation could be optimized out due to this bug, leading to the use of uninitialized memory. Although the current code does not exhibit this risky pattern of execution, it does utilize 'mstore' within assembly blocks, which introduces a vulnerability risk for future code modifications. As a preventative measure, it is advisable to avoid the usage of the afflicted Solidity versions, 0.8.13 and 0.8.14. Instead, consider utilizing a version that is not impacted by this optimizer bug to prevent potential memory initialization issues in your smart contract.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L95-L95

95:         assembly { // <= FOUND
96:             eta := sload(key)
97:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L106-L106

106:         assembly { // <= FOUND
107:             sstore(key, eta)
108:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L84-L84

84:         assembly { // <= FOUND
85:             deployedAddress_ := create2(0, add(bytecode, 32), mload(bytecode), salt)
86:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L24-L24

24:         assembly { // <= FOUND
25:             deployed := create(0, add(bytecode, 32), mload(bytecode))
26:             if iszero(deployed) {
27:                 revert(0, 0)
28:             }
29:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L40-L40

40:        assembly { // <= FOUND
41:             implementation_ := sload(_IMPLEMENTATION_SLOT)
42:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L40-L40

40:         assembly { // <= FOUND
41:             calldatacopy(0, 0, calldatasize())
42: 
43:             let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
44:             returndatacopy(0, 0, returndatasize())
45: 
46:             switch result
47:             case 0 {
48:                 revert(0, returndatasize())
49:             }
50:             default {
51:                 return(0, returndatasize())
52:             }
53:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L35-L35

35:         assembly { // <= FOUND
36:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
37:             sstore(_OWNER_SLOT, owner)
38:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L68-L68

68:         assembly { // <= FOUND
69:             sstore(_IMPLEMENTATION_SLOT, newImplementation)
70:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L21-L21

21:        assembly { // <= FOUND
22:             sstore(_OWNER_SLOT, caller())
23:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L74-L74

74:         assembly { // <= FOUND
75:             owner := sload(_OWNER_SLOT)
76:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L52-L52

52:         assembly { // <= FOUND
53:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
54:             sstore(_OWNER_SLOT, newOwner)
55:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L603-L603

603:         assembly { // <= FOUND
604:             commandId := calldataload(4)
605:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L873-L873

873:        assembly { // <= FOUND
874:             data.length := sub(metadata.length, 4)
875:             data.offset := add(metadata.offset, 4)
876:             version := calldataload(sub(metadata.offset, 28))
877:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L20-L20

20:         assembly { // <= FOUND
21:             addr := mload(add(bytesAddress, 20))
22:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L33-L33

33:         assembly { // <= FOUND
34:             mstore(add(bytesAddress, 20), addr)
35:             mstore(bytesAddress, 20)
36:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L75-L75

75:         assembly { // <= FOUND
76:             calldatacopy(0, 0, calldatasize())
77: 
78:             let result := delegatecall(gas(), implementaion_, 0, calldatasize(), 0, 0)
79:             returndatacopy(0, 0, returndatasize())
80: 
81:             switch result
82:             case 0 {
83:                 revert(0, returndatasize())
84:             }
85:             default {
86:                 return(0, returndatasize())
87:             }
88:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L29-L29

29:        assembly { // <= FOUND
30:             tokenAddress_ := sload(TOKEN_ADDRESS_SLOT)
31:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L39-L39

39:        assembly { // <= FOUND
40:             sstore(TOKEN_ADDRESS_SLOT, tokenAddress_)
41:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L48-L48

48:        assembly { // <= FOUND
49:             sstore(LIQUIDITY_POOL_SLOT, liquidityPool_)
50:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L58-L58

58:        assembly { // <= FOUND
59:             liquidityPool_ := sload(LIQUIDITY_POOL_SLOT)
60:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L30-L30

30:        assembly { // <= FOUND
31:             distr := sload(DISTRIBUTOR_SLOT)
32:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L40-L40

40:        assembly { // <= FOUND
41:             sstore(DISTRIBUTOR_SLOT, distributor_)
42:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L88-L88

88:         assembly { // <= FOUND
89:             prevExpressCaller := sload(slot)
90:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L92-L92

92:         assembly { // <= FOUND
93:             sstore(slot, expressCaller)
94:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L155-L155

155:         assembly { // <= FOUND
156:             expressCaller := sload(slot)
157:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L213-L213

213:            assembly { // <= FOUND
214:                 sstore(slot, 0)
215:             }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L25-L25

25:        assembly { // <= FOUND
26:             flowLimit := sload(FLOW_LIMIT_SLOT)
27:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L35-L35

35:        assembly { // <= FOUND
36:             sstore(FLOW_LIMIT_SLOT, flowLimit)
37:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L66-L66

66:         assembly { // <= FOUND
67:             flowOutAmount := sload(slot)
68:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L78-L78

78:         assembly { // <= FOUND
79:             flowInAmount := sload(slot)
80:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L97-L97

97:         assembly { // <= FOUND
98:             flowToAdd := sload(slotToAdd)
99:             flowToCompare := sload(slotToCompare)
100:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L102-L102

102:         assembly { // <= FOUND
103:             sstore(slotToAdd, add(flowToAdd, flowAmount))
104:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L30-L30

30:        assembly { // <= FOUND
31:             operator_ := sload(OPERATOR_SLOT)
32:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L40-L40

40:        assembly { // <= FOUND
41:             sstore(OPERATOR_SLOT, operator_)
42:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L30-L30

30:        assembly { // <= FOUND
31:             paused := sload(PAUSE_SLOT)
32:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L42-L42

42:        assembly { // <= FOUND
43:             sstore(PAUSE_SLOT, paused)
44:         }

[LOW-2] Empty receive functions can cause gas issues

Number of instances found

5

Resolution

In Solidity, functions that receive Ether without corresponding functionality to utilize or withdraw these funds can inadvertently lead to a permanent loss of value. This is because if someone sends Ether to the contract, they may be unable to retrieve it. To avoid this, functions receiving Ether should be accompanied by additional methods that process or allow the withdrawal of these funds. If the intent is to use the received Ether, it should trigger a separate function; if not, it should revert the transaction (for instance, via require(msg.sender == address(weth))). Access control checks can also prevent unintended Ether transfers, despite the slight gas cost they entail. If concerns over gas costs persist, at minimum, include a rescue function to recover unused Ether. Missteps in handling Ether in smart contracts can lead to irreversible financial losses, hence these precautions are crucial.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L41-L41

41:     receive() external payable {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L59-L59

59:     receive() external payable virtual {}

[LOW-3] The call abi.encodeWithSelector is not type safe

Number of instances found

12

Resolution

The call abi.encodeCall shout be used instead. Note abi.encodeCall is only safe from typographical errors in solidity versions 0.8.13 and above

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L293-L293

279:     function upgrade(
280:         address newImplementation,
281:         bytes32 newImplementationCodeHash,
282:         bytes calldata setupParams
283:     ) external override onlyGovernance {
284:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();
285: 
286:         if (AxelarGateway(newImplementation).contractId() != contractId()) revert InvalidImplementation();
287: 
288:         emit Upgraded(newImplementation);
289: 
290:         
291:         
292:         if (setupParams.length != 0) {
293:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(IAxelarGateway.setup.selector, setupParams)); // <= FOUND
294: 
295:             if (!success) revert SetupFailed();
296:         }
297: 
298:         _setImplementation(newImplementation);
299:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L373-L373

322:     function execute(bytes calldata input) external override {
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId)); // <= FOUND
374: 
375:             if (success) emit Executed(commandId);
376:             else _setCommandExecuted(commandId, false);
377:         }
378:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L398-L398

384:     function deployToken(bytes calldata params, bytes32) external onlySelf {
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol);
392: 
393:         if (tokenAddress == address(0)) {
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol));
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt) // <= FOUND
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol);
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom);
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);
409: 
410:             
411:             _setTokenType(symbol, TokenType.External);
412:         }
413: 
414:         _setTokenAddress(symbol, tokenAddress);
415:         _setTokenMintLimit(symbol, mintLimit);
416: 
417:         emit TokenDeployed(symbol, tokenAddress);
418:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L442-L442

426:     function burnToken(bytes calldata params, bytes32) external onlySelf {
427:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));
428: 
429:         address tokenAddress = tokenAddresses(symbol);
430: 
431:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
432: 
433:         if (_getTokenType(symbol) == TokenType.External) {
434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode)));
435: 
436:             if (_hasCode(depositHandlerAddress)) return;
437: 
438:             DepositHandler depositHandler = new DepositHandler{ salt: salt }();
439: 
440:             (bool success, bytes memory returnData) = depositHandler.execute(
441:                 tokenAddress,
442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler))) // <= FOUND
443:             );
444: 
445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
446: 
447:             
448:             depositHandler.destroy(address(this));
449:         } else {
450:             IBurnableMintableCappedERC20(tokenAddress).burn(salt);
451:         }
452:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L544-L544

529:     function _burnTokenFrom(
530:         address sender,
531:         string memory symbol,
532:         uint256 amount
533:     ) internal {
534:         address tokenAddress = tokenAddresses(symbol);
535: 
536:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
537:         if (amount == 0) revert InvalidAmount();
538: 
539:         TokenType tokenType = _getTokenType(symbol);
540: 
541:         if (tokenType == TokenType.External) {
542:             IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount);
543:         } else if (tokenType == TokenType.InternalBurnableFrom) {
544:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount)); // <= FOUND
545:         } else {
546:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount);
547:             IBurnableMintableCappedERC20(tokenAddress).burn(bytes32(0));
548:         }
549:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L61-L61

52:     function upgrade(
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner {
57:         if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation();
58:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();
59: 
60:         if (params.length > 0) {
61:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params)); // <= FOUND
62: 
63:             if (!success) revert SetupFailed();
64:         }
65: 
66:         emit Upgraded(newImplementation);
67: 
68:         assembly {
69:             sstore(_IMPLEMENTATION_SLOT, newImplementation)
70:         }
71:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L58-L58

35:     function init(
36:         address implementationAddress,
37:         address newOwner,
38:         bytes memory params
39:     ) external {
40:         address owner;
41: 
42:         assembly {
43:             owner := sload(_OWNER_SLOT)
44:         }
45: 
46:         if (msg.sender != owner) revert NotOwner();
47:         if (implementation() != address(0)) revert AlreadyInitialized();
48: 
49:         bytes32 id = contractId();
50:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();
51: 
52:         assembly {
53:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
54:             sstore(_OWNER_SLOT, newOwner)
55:         }
56: 
57:         if (params.length != 0) {
58:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, params)); // <= FOUND
59:             if (!success) revert SetupFailed();
60:         }
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L81-L81

72:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) public returns (address finalImplementation_) {
73:         address owner;
74:         assembly {
75:             owner := sload(_OWNER_SLOT)
76:         }
77:         if (msg.sender != owner) revert NotOwner();
78: 
79:         finalImplementation_ = Create3.deploy(FINAL_IMPLEMENTATION_SALT, bytecode);
80:         if (setupParams.length != 0) {
81:             (bool success, ) = finalImplementation_.delegatecall(abi.encodeWithSelector(BaseProxy.setup.selector, setupParams)); // <= FOUND
82:             if (!success) revert SetupFailed();
83:         }
84:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L814-L814

808:     function _deployTokenManager(
809:         bytes32 tokenId,
810:         TokenManagerType tokenManagerType,
811:         bytes memory params
812:     ) internal {
813:         (bool success, ) = tokenManagerDeployer.delegatecall(
814:             abi.encodeWithSelector(ITokenManagerDeployer.deployTokenManager.selector, tokenId, tokenManagerType, params) // <= FOUND
815:         );
816:         if (!success) {
817:             revert TokenManagerDeploymentFailed();
818:         }
819:         emit TokenManagerDeployed(tokenId, tokenManagerType, params);
820:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L854-L854

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals,
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal {
850:         bytes32 salt = _getStandardizedTokenSalt(tokenId);
851:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
852: 
853:         (bool success, ) = standardizedTokenDeployer.delegatecall(
854:             abi.encodeWithSelector( // <= FOUND
855:                 IStandardizedTokenDeployer.deployStandardizedToken.selector,
856:                 salt,
857:                 tokenManagerAddress,
858:                 distributor,
859:                 name,
860:                 symbol,
861:                 decimals,
862:                 mintAmount,
863:                 mintTo
864:             )
865:         );
866:         if (!success) {
867:             revert StandardizedTokenDeploymentFailed();
868:         }
869:         emit StandardizedTokenDeployed(tokenId, name, symbol, decimals, mintAmount, mintTo);
870:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L48-L48

45:     function _takeToken(address from, uint256 amount) internal override returns (uint256) {
46:         IERC20 token = IERC20(tokenAddress());
47: 
48:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.burn.selector, from, amount)); // <= FOUND
49: 
50:         return amount;
51:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L62-L62

59:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
60:         IERC20 token = IERC20(tokenAddress());
61: 
62:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.mint.selector, to, amount)); // <= FOUND
63: 
64:         return amount;
65:     }

[LOW-4] Upgradable contracts should have a __gap variable

Number of instances found

2

Resolution

This is to ensure the team can add new state variables without compromising compatability.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L37-L37

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L12-L12

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable 

[LOW-6] Double type casts create complexity within the code

Number of instances found

3

Resolution

Double type casting should be avoided in Solidity contracts to prevent unintended consequences and ensure accurate data representation. Performing multiple type casts in succession can lead to unexpected truncation, rounding errors, or loss of precision, potentially compromising the contract's functionality and reliability. Furthermore, double type casting can make the code less readable and harder to maintain, increasing the likelihood of errors and misunderstandings during development and debugging. To ensure precise and consistent data handling, developers should use appropriate data types and avoid unnecessary or excessive type casting, promoting a more robust and dependable contract execution.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L72

72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L74-L74

74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND

[LOW-7] Use SafeCast to safely downcast variables

Number of instances found

6

Resolution

Downcasting int/uints in Solidity can be unsafe due to the potential for data loss and unintended behavior. When downcasting a larger integer type to a smaller one (e.g., uint256 to uint128), the value may exceed the range of the target type, leading to truncation and loss of significant digits. This data loss can result in unexpected state changes, incorrect calculations, or other contract vulnerabilities, ultimately compromising the contracts functionality and reliability. To prevent these risks, developers should carefully consider the range of values their variables may hold and ensure that proper checks are in place to prevent out-of-range values before performing downcasting. Also consider using OZ SafeCast functionality.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L57-L58

54:     function _lowerCase(string memory s) internal pure returns (string memory) {
55:         uint256 length = bytes(s).length;
56:         for (uint256 i; i < length; i++) {
57:             uint8 b = uint8(bytes(s)[i]); // <= FOUND
58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32)); // <= FOUND
59:         }
60:         return s;
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND
616:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L65-L65

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) {
63:         bytes32 newSalt = keccak256(abi.encode(sender, salt));
64:         deployedAddress_ = address(
65:             uint160( // <= FOUND
66:                 uint256(
67:                     keccak256(
68:                         abi.encodePacked(
69:                             hex'ff',
70:                             address(this),
71:                             newSalt,
72:                             keccak256(bytecode) 
73:                         )
74:                     )
75:                 )
76:             )
77:         );
78:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L74

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND
73: 
74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND
75:     }

[LOW-8] Upgradable contracts should have an initialization function

Number of instances found

2

Resolution

Upgradable contracts in Solidity should have an initialization function to ensure proper setup, maintain state consistency, and enhance security. Unlike regular contracts, upgradable contracts use a proxy pattern that separates the contract's logic from its data storage, enabling seamless updates to the logic without affecting the stored data. However, this approach requires careful initialization of the contract state to avoid inconsistencies or vulnerabilities.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L40-L40

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable, // <= FOUND
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: {
46:     using StringToBytes32 for string;
47:     using Bytes32ToString for bytes32;
48:     using AddressBytesUtils for bytes;
49:     using AddressBytesUtils for address;
50: 
51:     address internal immutable implementationLockUnlock;
52:     address internal immutable implementationMintBurn;
53:     address internal immutable implementationLiquidityPool;
54:     IAxelarGasService public immutable gasService;
55:     IRemoteAddressValidator public immutable remoteAddressValidator;
56:     address public immutable tokenManagerDeployer;
57:     address public immutable standardizedTokenDeployer;
58:     Create3Deployer internal immutable deployer;
59:     bytes32 internal immutable chainNameHash;
60:     bytes32 internal immutable chainName;
61: 
62:     bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id');
63:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id');
64:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt');

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L12-L12

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable { // <= FOUND
13:     using AddressToString for address;
14: 
15:     mapping(string => bytes32) public remoteAddressHashes;
16:     mapping(string => string) public remoteAddresses;
17:     address public immutable interchainTokenServiceAddress;
18:     bytes32 public immutable interchainTokenServiceAddressHash;
19:     mapping(string => bool) public supportedByGateway;
20: 
21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
22: 
23:     
24: 
25: 
26: 
27: 
28: 
29:     
30: 
31: 
32: 
33: 
34: 
35: 
36:     

[LOW-9] Functions which set address state variables should have zero address checks

Number of instances found

15

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L643-L643

643:     function _setTokenAddress(string memory symbol, address tokenAddress) internal {
644:         _setAddress(_getTokenAddressKey(symbol), tokenAddress);
645:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved(
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal {
658:         _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true);
659:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint(
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal {
670:         _setBool(
671:             _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount),
672:             true
673:         );
674:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L676-L676

676:     function _setImplementation(address newImplementation) internal {
677:         _setAddress(KEY_IMPLEMENTATION, newImplementation);
678:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L38-L38

38:     function _setTokenAddress(address tokenAddress_) internal {
39:         assembly {
40:             sstore(TOKEN_ADDRESS_SLOT, tokenAddress_)
41:         }
42:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L47-L47

47:     function _setLiquidityPool(address liquidityPool_) internal {
48:         assembly {
49:             sstore(LIQUIDITY_POOL_SLOT, liquidityPool_)
50:         }
51:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L39-L39

39:     function _setDistributor(address distributor_) internal {
40:         assembly {
41:             sstore(DISTRIBUTOR_SLOT, distributor_)
42:         }
43:         emit DistributorChanged(distributor_);
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L79-L79

79:     function _setExpressReceiveToken(
80:         bytes32 tokenId,
81:         address destinationAddress,
82:         uint256 amount,
83:         bytes32 commandId,
84:         address expressCaller
85:     ) internal {
86:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
87:         address prevExpressCaller;
88:         assembly {
89:             prevExpressCaller := sload(slot)
90:         }
91:         if (prevExpressCaller != address(0)) revert AlreadyExpressCalled();
92:         assembly {
93:             sstore(slot, expressCaller)
94:         }
95:         emit ExpressReceive(tokenId, destinationAddress, amount, commandId, expressCaller);
96:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L110-L110

110:     function _setExpressReceiveTokenWithData(
111:         bytes32 tokenId,
112:         string memory sourceChain,
113:         bytes memory sourceAddress,
114:         address destinationAddress,
115:         uint256 amount,
116:         bytes calldata data,
117:         bytes32 commandId,
118:         address expressCaller
119:     ) internal {
120:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
121:             tokenId,
122:             sourceChain,
123:             sourceAddress,
124:             destinationAddress,
125:             amount,
126:             data,
127:             commandId
128:         );
129:         address prevExpressCaller;
130:         assembly {
131:             prevExpressCaller := sload(slot)
132:         }
133:         if (prevExpressCaller != address(0)) revert AlreadyExpressCalled();
134:         assembly {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L39-L39

39:     function _setOperator(address operator_) internal {
40:         assembly {
41:             sstore(OPERATOR_SLOT, operator_)
42:         }
43:         emit OperatorChanged(operator_);
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L92

92:     function setWhitelistedProposalCaller(
93:         string calldata sourceChain,
94:         address sourceCaller,
95:         bool whitelisted
96:     ) external override onlyOwner {
97:         whitelistedCallers[sourceChain][sourceCaller] = whitelisted;
98:         emit WhitelistedProposalCallerSet(sourceChain, sourceCaller, whitelisted);
99:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L107

107:     function setWhitelistedProposalSender(
108:         string calldata sourceChain,
109:         address sourceSender,
110:         bool whitelisted
111:     ) external override onlyOwner {
112:         whitelistedSenders[sourceChain][sourceSender] = whitelisted;
113:         emit WhitelistedProposalSenderSet(sourceChain, sourceSender, whitelisted);
114:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67-L67

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
68:         _setLiquidityPool(newLiquidityPool);
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L51-L51

51:     function setDistributor(address distr) external onlyDistributor {
52:         _setDistributor(distr);
53:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator {
52:         _setOperator(operator_);
53:     }

[LOW-10] Max allowance is not compatible with all tokens

Number of instances found

2

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L58-L58

43:     function interchainTransfer(
44:         string calldata destinationChain,
45:         bytes calldata recipient,
46:         uint256 amount,
47:         bytes calldata metadata
48:     ) external payable {
49:         address sender = msg.sender;
50:         ITokenManager tokenManager = getTokenManager();
51:         
52: 
53: 
54:         if (tokenManagerRequiresApproval()) {
55:             uint256 allowance_ = allowance[sender][address(tokenManager)];
56:             if (allowance_ != type(uint256).max) {
57:                 if (allowance_ > type(uint256).max - amount) {
58:                     allowance_ = type(uint256).max - amount; // <= FOUND
59:                 }
60: 
61:                 _approve(sender, address(tokenManager), allowance_ + amount);
62:             }
63:         }
64: 
65:         
66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L97-L97

79:     function interchainTransferFrom(
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable {
86:         uint256 _allowance = allowance[sender][msg.sender];
87: 
88:         if (_allowance != type(uint256).max) {
89:             _approve(sender, msg.sender, _allowance - amount);
90:         }
91: 
92:         ITokenManager tokenManager = getTokenManager();
93:         if (tokenManagerRequiresApproval()) {
94:             uint256 allowance_ = allowance[sender][address(tokenManager)];
95:             if (allowance_ != type(uint256).max) {
96:                 if (allowance_ > type(uint256).max - amount) {
97:                     allowance_ = type(uint256).max - amount; // <= FOUND
98:                 }
99: 
100:                 _approve(sender, address(tokenManager), allowance_ + amount);
101:             }
102:         }
103: 
104:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
105:     }

[LOW-11] Function calls within for loops

Number of instances found

11

Resolution

Making function calls or external calls within loops in Solidity can lead to inefficient gas usage, potential bottlenecks, and increased vulnerability to attacks. Each function call or external call consumes gas, and when executed within a loop, the gas cost multiplies, potentially causing the transaction to run out of gas or exceed block gas limits. This can result in transaction failure or unpredictable behavior.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L273-L275

269:        for (uint256 i; i < length; ++i) {
270:             string memory symbol = symbols[i];
271:             uint256 limit = limits[i];
272: 
273:             if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol); // <= FOUND
274: 
275:             _setTokenMintLimit(symbol, limit); // <= FOUND
276:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L346-L376

343:        for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue;  // <= FOUND
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true); // <= FOUND
372: 
373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId));
374: 
375:             if (success) emit Executed(commandId);
376:             else _setCommandExecuted(commandId, false); // <= FOUND
377:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L64-L64

63:        for (uint256 i = 0; i < interchainCalls.length; ) {
64:             _sendProposal(interchainCalls[i]); // <= FOUND
65:             unchecked {
66:                 ++i;
67:             }
68:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L79-L81

74:        for (uint256 i = 0; i < calls.length; i++) {
75:             InterchainCalls.Call memory call = calls[i];
76:             (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData);
77: 
78:             if (!success) {
79:                 _onTargetExecutionFailed(call, result); // <= FOUND
80:             } else {
81:                 _onTargetExecuted(call, result); // <= FOUND
82:             }
83:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L538-L539

537:        for (uint256 i; i < length; ++i) {
538:             ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i])); // <= FOUND
539:             tokenManager.setFlowLimit(flowLimits[i]); // <= FOUND
540:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L45-L45

44:        for (uint256 i; i < length; ++i) {
45:             addTrustedAddress(trustedChainNames[i], trustedAddresses[i]); // <= FOUND
46:         }

[LOW-12] For loops in public or external functions should be avoided due to high gas costs and possible DOS

Number of instances found

7

Resolution

In Solidity, for loops can potentially cause Denial of Service (DoS) attacks if not handled carefully. DoS attacks can occur when an attacker intentionally exploits the gas cost of a function, causing it to run out of gas or making it too expensive for other users to call. Below are some scenarios where for loops can lead to DoS attacks: Nested for loops can become exceptionally gas expensive and should be used sparingly

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L122-L122

119:     function getSignerVotesCount(bytes32 topic) external view override returns (uint256) {
120:         uint256 length = signers.accounts.length;
121:         uint256 voteCount;
122:         for (uint256 i; i < length; ++i) { // <= FOUND
123:             if (votingPerTopic[signerEpoch][topic].hasVoted[signers.accounts[i]]) {
124:                 voteCount++;
125:             }
126:         }
127: 
128:         return voteCount;
129:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L269-L269

265:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {
266:         uint256 length = symbols.length;
267:         if (length != limits.length) revert InvalidSetMintLimitsParams();
268: 
269:         for (uint256 i; i < length; ++i) { // <= FOUND
270:             string memory symbol = symbols[i];
271:             uint256 limit = limits[i];
272: 
273:             if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol);
274: 
275:             _setTokenMintLimit(symbol, limit);
276:         }
277:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L343-L343

322:     function execute(bytes calldata input) external override {
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) { // <= FOUND
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L63-L63

59:     function sendProposals(InterchainCalls.InterchainCall[] calldata interchainCalls) external payable override {
60:         
61:         revertIfInvalidFee(interchainCalls);
62: 
63:         for (uint256 i = 0; i < interchainCalls.length; ) { // <= FOUND
64:             _sendProposal(interchainCalls[i]);
65:             unchecked {
66:                 ++i;
67:             }
68:         }
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L537-L537

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {
535:         uint256 length = tokenIds.length;
536:         if (length != flowLimits.length) revert LengthMismatch();
537:         for (uint256 i; i < length; ++i) { // <= FOUND
538:             ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i]));
539:             tokenManager.setFlowLimit(flowLimits[i]);
540:         }
541:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L108-L108

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {
107:         uint256 length = chainNames.length;
108:         for (uint256 i; i < length; ++i) { // <= FOUND
109:             string calldata chainName = chainNames[i];
110:             supportedByGateway[chainName] = true;
111:             emit GatewaySupportedChainAdded(chainName);
112:         }
113:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L121-L121

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {
120:         uint256 length = chainNames.length;
121:         for (uint256 i; i < length; ++i) { // <= FOUND
122:             string calldata chainName = chainNames[i];
123:             supportedByGateway[chainName] = false;
124:             emit GatewaySupportedChainRemoved(chainName);
125:         }
126:     }

[LOW-14] Minting to the zero address should be avoided

Number of instances found

4

Resolution

Minting tokens to the zero address in Solidity is a potential pitfall that should be carefully guarded against. The zero address (0x0) is generally used as a default value and represents an uninitialized or null address. Minting tokens to this address effectively burns them, making them inaccessible and permanently removing them from the total supply. This could lead to unintended token loss if performed accidentally. To prevent this, it's important to include a check in the minting function to ensure that the target address is not the zero address. Using a library like OpenZeppelin's Address can provide utility functions like requireNonZero, which simplifies this check and enhances the security of the minting function.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L511-L511

511:     function _mintToken(
512:         string memory symbol,
513:         address account,
514:         uint256 amount
515:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L388-L388

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name,
391:         string calldata symbol,
392:         uint8 decimals,
393:         uint256 mintAmount,
394:         address distributor
395:     ) external payable notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L841-L841

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals,
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L49-L49

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name,
54:         string calldata symbol,
55:         uint8 decimals,
56:         uint256 mintAmount,
57:         address mintTo
58:     ) external payable 

[LOW-15] Contracts do not use their OZ upgradable counterparts

Number of instances found

1

Resolution

Using the upgradeable counterpart of the OpenZeppelin (OZ) library in Solidity is beneficial for creating contracts that can be updated in the future. OpenZeppelin's upgradeable contracts library is designed with proxy patterns in mind, which allow the logic of contracts to be upgraded while preserving the contract's state and address. This can be crucial for long-lived contracts where future requirements or improvements may not be fully known at the time of deployment. The upgradeable OZ contracts also include protection against a class of vulnerabilities related to initialization of storage variables in upgradeable contracts. Hence, it's a good idea to use them when developing contracts that may need to be upgraded in the future, as they provide a solid foundation for secure and upgradeable smart contracts.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L37-L43

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable, // <= FOUND
44:     Multicall
45: 

[LOW-16] Contract inherits Pausable but does not expose pausing/unpausing functionality

Number of instances found

2

Resolution

When a contract inherits from the Pausable contract in Solidity, it gains the ability to pause and resume certain actions, which can be crucial in mitigating potential risks or issues. However, the _pause and _unpause functions are internal and can only be called from within the contract or derived contracts. If the functionality to pause and unpause isn't exposed through public or external functions, it can't be called by the contract owner or designated pauser account.

Resolution: To take advantage of the Pausable contract, create public or external functions that call _pause and _unpause.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L37-L37

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L12-L12

12: contract Pausable is IPausable 

[LOW-17] Loss of precision

Number of instances found

4

Resolution

Dividing by large numbers in Solidity can cause a loss of precision due to the language's inherent integer division behavior. Solidity does not support floating-point arithmetic, and as a result, division between integers yields an integer result, truncating any fractional part. When dividing by a large number, the resulting value may become significantly smaller, leading to a loss of precision, as the fractional part is discarded.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L64-L64

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount) {
64:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
65:         uint256 slot = _getFlowOutSlot(epoch);
66:         assembly {
67:             flowOutAmount := sload(slot)
68:         }
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L76-L76

75:     function getFlowInAmount() external view returns (uint256 flowInAmount) {
76:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
77:         uint256 slot = _getFlowInSlot(epoch);
78:         assembly {
79:             flowInAmount := sload(slot)
80:         }
81:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L114-L114

111:     function _addFlowOut(uint256 flowOutAmount) internal {
112:         uint256 flowLimit = getFlowLimit();
113:         if (flowLimit == 0) return;
114:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
115:         uint256 slotToAdd = _getFlowOutSlot(epoch);
116:         uint256 slotToCompare = _getFlowInSlot(epoch);
117:         _addFlow(flowLimit, slotToAdd, slotToCompare, flowOutAmount);
118:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L127-L127

124:     function _addFlowIn(uint256 flowInAmount) internal {
125:         uint256 flowLimit = getFlowLimit();
126:         if (flowLimit == 0) return;
127:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
128:         uint256 slotToAdd = _getFlowInSlot(epoch);
129:         uint256 slotToCompare = _getFlowOutSlot(epoch);
130:         _addFlow(flowLimit, slotToAdd, slotToCompare, flowInAmount);
131:     }

[LOW-18] Missing zero address check in constructor

Number of instances found

18

Resolution

In Solidity, constructors often take address parameters to initialize important components of a contract, such as owner or linked contracts. However, without a check, there's a risk that an address parameter could be mistakenly set to the zero address (0x0). This could occur due to a mistake or oversight during contract deployment. A zero address in a crucial role can cause serious issues, as it cannot perform actions like a normal address, and any funds sent to it are irretrievable. Therefore, it's crucial to include a zero address check in constructors to prevent such potential problems. If a zero address is detected, the constructor should revert the transaction.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L34-L34

33:     constructor(
34:         address gateway, // <= FOUND
35:         string memory governanceChain_,
36:         string memory governanceAddress_,
37:         uint256 minimumTimeDelay
38:     ) AxelarExecutable(gateway) TimeLock(minimumTimeDelay) {
39:         governanceChain = governanceChain_;
40:         governanceAddress = governanceAddress_;
41:         governanceChainHash = keccak256(bytes(governanceChain_));
42:         governanceAddressHash = keccak256(bytes(governanceAddress_));
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L34-L34

33:     constructor(
34:         address gateway, // <= FOUND
35:         string memory governanceChain,
36:         string memory governanceAddress,
37:         uint256 minimumTimeDelay,
38:         address[] memory cosigners,
39:         uint256 threshold
40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L64-L64

64:     constructor(address authModule_, address tokenDeployerImplementation_) { // <= FOUND
65:         if (authModule_.code.length == 0) revert InvalidAuthModule();
66:         if (tokenDeployerImplementation_.code.length == 0) revert InvalidTokenDeployer();
67: 
68:         AUTH_MODULE = authModule_;
69:         TOKEN_DEPLOYER_IMPLEMENTATION = tokenDeployerImplementation_;
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L42-L42

42:     constructor(address _gateway, address _gasService) { // <= FOUND
43:         gateway = IAxelarGateway(_gateway);
44:         gasService = IAxelarGasService(_gasService);
45:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L29-L29

29:     constructor(address _gateway, address _owner) AxelarExecutable(_gateway) { // <= FOUND
30:         _transferOwnership(_owner);
31:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L27-L28

26:     constructor(
27:         address implementationAddress, // <= FOUND
28:         address owner, // <= FOUND
29:         bytes memory setupParams
30:     ) Proxy(implementationAddress, owner, setupParams) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L23-L23

23:     constructor(address implementationAddress) { // <= FOUND
24:         implementation = implementationAddress;
25:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L20-L22

19:     constructor(
20:         address implementationAddress, // <= FOUND
21:         address owner, // <= FOUND
22:         address operator // <= FOUND
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L21-L22

20:     constructor(
21:         address implementationAddress, // <= FOUND
22:         address owner, // <= FOUND
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L21-L21

21:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) { // <= FOUND
22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();
23: 
24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
25:         if (!success) revert SetupFailed();
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L26-L34

25:     constructor(
26:         address interchainTokenServiceAddress_, // <= FOUND
27:         uint256 implementationType_,
28:         bytes32 tokenId_,
29:         bytes memory params
30:     ) {
31:         interchainTokenServiceAddress = IInterchainTokenService(interchainTokenServiceAddress_);
32:         implementationType = implementationType_;
33:         tokenId = tokenId_;
34:         address impl = _getImplementation(IInterchainTokenService(interchainTokenServiceAddress_), implementationType_); // <= FOUND
35: 
36:         (bool success, ) = impl.delegatecall(abi.encodeWithSelector(TokenManagerProxy.setup.selector, params));
37:         if (!success) revert SetupFailed();
38:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L19-L19

19:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L22-L22

22:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {} // <= FOUND

[LOW-19] Use of onlyOwner functions can be lost

Number of instances found

1

Resolution

In Solidity, renouncing ownership of a contract essentially transfers ownership to the zero address. This is an irreversible operation and has considerable security implications. If the renounceOwnership function is used, the contract will lose the ability to perform any operations that are limited to the owner. This can be problematic if there are any bugs, flaws, or unexpected events that require owner intervention to resolve. Therefore, in some instances, it is better to disable or omit the renounceOwnership function, and instead implement a secure transferOwnership function. This way, if necessary, ownership can be transferred to a new, trusted party without losing the potential for administrative intervention.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L22-L22

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable  // <= FOUND

[LOW-20] Using zero as a parameter

Number of instances found

6

Resolution

Taking 0 as a valid argument in Solidity without checks can lead to severe security issues. A historical example is the infamous 0x0 address bug where numerous tokens were lost. This happens because '0' can be interpreted as an uninitialized address, leading to transfers to the '0x0' address, effectively burning tokens. Moreover, 0 as a denominator in division operations would cause a runtime exception. It's also often indicative of a logical error in the caller's code. It's important to always validate input and handle edge cases like 0 appropriately. Use require() statements to enforce conditions and provide clear error messages to facilitate debugging and safer code.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L67-L70

67:     function _cancelTimeLock(bytes32 hash) internal { // <= FOUND
68:         if (hash == 0) revert InvalidTimeLockHash();
69: 
70:         _setTimeLockEta(hash, 0); // <= FOUND
71:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L79-L86

79:     function _finalizeTimeLock(bytes32 hash) internal { // <= FOUND
80:         uint256 eta = _getTimeLockEta(hash);
81: 
82:         if (hash == 0 || eta == 0) revert InvalidTimeLockHash();
83: 
84:         if (block.timestamp < eta) revert TimeLockNotReady();
85: 
86:         _setTimeLockEta(hash, 0); // <= FOUND
87:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L678-L691

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal { // <= FOUND
679:         (
680:             ,
681:             bytes32 tokenId,
682:             string memory name,
683:             string memory symbol,
684:             uint8 decimals,
685:             bytes memory distributorBytes,
686:             bytes memory operatorBytes
687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));
688:         address tokenAddress = getStandardizedTokenAddress(tokenId);
689:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
690:         address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress;
691:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, 0, distributor); // <= FOUND
692:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
693:         _deployTokenManager(
694:             tokenId,
695:             tokenManagerType,
696:             abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)
697:         );
698:     }

[LOW-21] Solidity version 0.8.20 won't work on all chains due to PUSH0

Number of instances found

73

Resolution

Solidity version 0.8.20 uses the new Shanghai EVM which introduces the PUSH0 opcode, this may not be implemented on all chains and L2 thus reducing the portability and compatability of the code. Consider using a earlier solidity version.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L3-L3

3: pragma solidity ^0.8.0; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L3-L3

3: pragma solidity ^0.8.9; // <= FOUND

[LOW-22] increase/decrease allowance should be used instead of approve

Number of instances found

3

Resolution

In order to prevent front running, increase/decrease allowance should be used in place of approve where possible

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L61-L61

43:     function interchainTransfer(
44:         string calldata destinationChain,
45:         bytes calldata recipient,
46:         uint256 amount,
47:         bytes calldata metadata
48:     ) external payable {
49:         address sender = msg.sender;
50:         ITokenManager tokenManager = getTokenManager();
51:         
52: 
53: 
54:         if (tokenManagerRequiresApproval()) {
55:             uint256 allowance_ = allowance[sender][address(tokenManager)];
56:             if (allowance_ != type(uint256).max) {
57:                 if (allowance_ > type(uint256).max - amount) {
58:                     allowance_ = type(uint256).max - amount;
59:                 }
60: 
61:                 _approve(sender, address(tokenManager), allowance_ + amount); // <= FOUND
62:             }
63:         }
64: 
65:         
66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L89-L100

79:     function interchainTransferFrom(
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable {
86:         uint256 _allowance = allowance[sender][msg.sender];
87: 
88:         if (_allowance != type(uint256).max) {
89:             _approve(sender, msg.sender, _allowance - amount); // <= FOUND
90:         }
91: 
92:         ITokenManager tokenManager = getTokenManager();
93:         if (tokenManagerRequiresApproval()) {
94:             uint256 allowance_ = allowance[sender][address(tokenManager)];
95:             if (allowance_ != type(uint256).max) {
96:                 if (allowance_ > type(uint256).max - amount) {
97:                     allowance_ = type(uint256).max - amount;
98:                 }
99: 
100:                 _approve(sender, address(tokenManager), allowance_ + amount); // <= FOUND
101:             }
102:         }
103: 
104:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
105:     }

[LOW-23] Contract existence is not checked before low level call

Number of instances found

2

Resolution

Low-level assembly calls, such as call, can return a successful status even when the target address contains no executable code. This is due to the fact that a call operation merely checks if the call operation itself was successful, not whether the call was made to an address with code. As a result, these calls might lead to false positives when assessing the success of an operation. To prevent potential issues, consider using Solidity's extcodesize function to check the size of the contract code at the target address. If extcodesize returns zero, this indicates that there is no code at the specified address, and the function can safely revert.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L603-L604

603:         assembly {
604:             commandId := calldataload(4) // <= FOUND
605:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L873-L876

873:        assembly {
874:             data.length := sub(metadata.length, 4)
875:             data.offset := add(metadata.offset, 4)
876:             version := calldataload(sub(metadata.offset, 28)) // <= FOUND
877:         }

[LOW-24] Storage Write Removal Bug On Conditional Early Termination

Number of instances found

2

Resolution

In September 2022, a bug in Solidity’s Yul optimizer was identified through differential fuzzing. This bug, introduced in version 0.8.13 and fixed by version 0.8.17, can be activated easier with optimized via-IR code generation but can also potentially occur in optimized legacy code generation. This bug is of medium/high severity, which requires contracts that use large inline assembly blocks containing user-defined assembly functions involving return(...) or stop() instructions to be reviewed.

The bug is associated with the Unused Store Eliminator in Yul optimizer, which removes redundant storage writes, and is triggered when function calls are performed. If the function call conditionally continues after the call to a function and terminates using return(...) or stop(), the optimizer may incorrectly remove storage writes before calls to the function.

To evaluate if a contract is affected, you need to check contracts that include inline assembly block with return(...) or stop() statements. If early termination happens conditionally within a function, the optimizer might remove storage writes before function calls.

To avoid this, contracts should not allow for conditional early termination within a function. It is also recommended to use a version of Solidity where this bug has been fixed (version 0.8.17 or later).

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L51-L51

40:         assembly {
41:             calldatacopy(0, 0, calldatasize())
42: 
43:             let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
44:             returndatacopy(0, 0, returndatasize())
45: 
46:             switch result
47:             case 0 {
48:                 revert(0, returndatasize())
49:             }
50:             default {
51:                 return(0, returndatasize()) // <= FOUND
52:             }
53:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L86-L86

75:         assembly {
76:             calldatacopy(0, 0, calldatasize())
77: 
78:             let result := delegatecall(gas(), implementaion_, 0, calldatasize(), 0, 0)
79:             returndatacopy(0, 0, returndatasize())
80: 
81:             switch result
82:             case 0 {
83:                 revert(0, returndatasize())
84:             }
85:             default {
86:                 return(0, returndatasize()) // <= FOUND
87:             }
88:         }

[LOW-25] Functions calling contracts/addresses with transfer hooks are missing reentrancy guards

Number of instances found

2

Resolution

While adherence to the check-effects-interaction pattern is commendable, the absence of a reentrancy guard in functions, especially where transfer hooks might be present, can expose the protocol users to risks of read-only reentrancies. Such reentrancy vulnerabilities can be exploited to execute malicious actions even without altering the contract state. Without a reentrancy guard, the only potential mitigation would be to blocklist the entire protocol - an extreme and disruptive measure. Therefore, incorporating a reentrancy guard into these functions is vital to bolster security, as it helps protect against both traditional reentrancy attacks and read-only reentrancies, ensuring robust and safe protocol operations.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L523-L523

511:     function _mintToken(
512:         string memory symbol,
513:         address account,
514:         uint256 amount
515:     ) internal {
516:         address tokenAddress = tokenAddresses(symbol);
517: 
518:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
519: 
520:         _setTokenMintAmount(symbol, tokenMintAmount(symbol) + amount);
521: 
522:         if (_getTokenType(symbol) == TokenType.External) {
523:             IERC20(tokenAddress).safeTransfer(account, amount); // <= FOUND
524:         } else {
525:             IBurnableMintableCappedERC20(tokenAddress).mint(account, amount);
526:         }
527:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L64-L64

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
61:         IERC20 token = IERC20(tokenAddress());
62:         uint256 balance = IERC20(token).balanceOf(to);
63: 
64:         SafeTokenTransfer.safeTransfer(token, to, amount); // <= FOUND
65: 
66:         return IERC20(token).balanceOf(to) - balance;
67:     }

[LOW-26] Revert on Transfer to the Zero Address

Number of instances found

5

Resolution

Many ERC-20 and ERC-721 token contracts implement a safeguard that reverts transactions which attempt to transfer tokens to the zero address. This is because such transfers are often the result of programming errors. The OpenZeppelin library, a popular choice for implementing these standards, includes this safeguard. For token contract developers who want to avoid unintentional transfers to the zero address, it's good practice to include a condition that reverts the transaction if the recipient's address is the zero address.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L451

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external {
445:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
446: 
447:         address caller = msg.sender;
448:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
449:         IERC20 token = IERC20(tokenManager.tokenAddress());
450: 
451:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
452: 
453:         _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);
454:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L482

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external {
476:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
477: 
478:         address caller = msg.sender;
479:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
480:         IERC20 token = IERC20(tokenManager.tokenAddress());
481: 
482:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
483: 
484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);
485: 
486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
487:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L44-L48

44:     function _takeToken(address from, uint256 amount) internal override returns (uint256) {
45:         IERC20 token = IERC20(tokenAddress());
46:         uint256 balance = token.balanceOf(address(this));
47: 
48:         SafeTokenTransferFrom.safeTransferFrom(token, from, address(this), amount); // <= FOUND
49: 
50:         
51:         return IERC20(token).balanceOf(address(this)) - balance;
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L77-L82

77:     function _takeToken(address from, uint256 amount) internal override returns (uint256) {
78:         IERC20 token = IERC20(tokenAddress());
79:         address liquidityPool_ = liquidityPool();
80:         uint256 balance = token.balanceOf(liquidityPool_);
81: 
82:         SafeTokenTransferFrom.safeTransferFrom(token, from, liquidityPool_, amount); // <= FOUND
83: 
84:         
85:         return IERC20(token).balanceOf(liquidityPool_) - balance;
86:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L94-L98

94:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
95:         IERC20 token = IERC20(tokenAddress());
96:         uint256 balance = IERC20(token).balanceOf(to);
97: 
98:         SafeTokenTransferFrom.safeTransferFrom(token, liquidityPool(), to, amount); // <= FOUND
99: 
100:         return IERC20(token).balanceOf(to) - balance;
101:     }

[LOW-27] Two or more functions contain the exact same code

Number of instances found

27

Resolution

In Solidity programming, duplicate code in multiple functions introduces potential security risks and maintainability issues. It magnifies the impact of any bugs or vulnerabilities, since developers must fix these in every location where the code is replicated. Overlooking any instance of replicated code could leave vulnerabilities intact. Furthermore, code duplication leads to contract bloating, diminishing the readability and manageability of the code. Future logic changes would need to be applied in every location where the code is replicated, increasing the complexity of updates. To resolve this, it is recommended to consolidate duplicate code into a single internal function, and replace the duplicate instances with calls to this new function. This approach streamlines the code, reducing the attack surface and making it easier to maintain and update.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L208-L208

208:     function allTokensFrozen() external pure override returns (bool) { // <= FOUND
209:         return false;
210:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L213-L213

213:     function adminEpoch() external pure override returns (uint256) { // <= FOUND
214:         return 0;
215:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L218-L218

218:     function adminThreshold(uint256) external pure override returns (uint256) { // <= FOUND
219:         return 0;
220:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L237-L237

237:     function tokenFrozen(string memory) external pure override returns (bool) { // <= FOUND
238:         return false;
239:     }
126:     function _beforeProposalExecuted(
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         bytes calldata payload
130:     ) internal virtual {
131:         
132:     }
142:     function _onProposalExecuted(
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual {
148:         
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual { // <= FOUND
179:         
180:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L22-L22

22:     function implementation() public view virtual returns (address implementation_) { // <= FOUND
23:         assembly {
24:             implementation_ := sload(_IMPLEMENTATION_SLOT)
25:         }
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L306-L306

306:     function setup(bytes calldata params) external override { // <= FOUND
307:         
308:         if (implementation() == address(0)) revert NotProxy();
309: 
310:         (address governance_, address mintLimiter_, bytes memory newOperatorsData) = abi.decode(params, (address, address, bytes));
311: 
312:         if (governance_ != address(0)) _transferGovernance(governance_);
313:         if (mintLimiter_ != address(0)) _transferMintLimiter(mintLimiter_);
314: 
315:         if (newOperatorsData.length != 0) {
316:             IAxelarAuth(AUTH_MODULE).transferOperatorship(newOperatorsData);
317: 
318:             emit OperatorshipTransferred(newOperatorsData);
319:         }
320:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L32-L32

32:     function setup(bytes calldata params) external {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L49-L49

49:     function setup(bytes calldata params) external override onlyProxy { // <= FOUND
50:         {
51:             address distributor_;
52:             address tokenManager_;
53:             string memory tokenName;
54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));
55:             _setDistributor(distributor_);
56:             tokenManager = tokenManager_;
57:             _setDomainTypeSignatureHash(tokenName);
58:             name = tokenName;
59:         }
60:         {
61:             uint256 mintAmount;
62:             address mintTo;
63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
64:             if (mintAmount > 0) {
65:                 _mint(mintTo, mintAmount);
66:             }
67:         }
68:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external override onlyProxy { // <= FOUND
62:         bytes memory operatorBytes = abi.decode(params, (bytes));
63:         address operator_;
64:         
65: 
66: 
67: 
68:         if (operatorBytes.length == 0) {
69:             operator_ = address(interchainTokenService);
70:         } else {
71:             operator_ = operatorBytes.toAddress();
72:         }
73:         _setOperator(operator_);
74:         _setup(params);
75:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L39-L39

39:     function implementation() public view returns (address implementation_) { // <= FOUND
40:         assembly {
41:             implementation_ := sload(_IMPLEMENTATION_SLOT)
42:         }
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L36-L36

36:     function contractId() external pure returns (bytes32) { // <= FOUND
37:         return CONTRACT_ID;
38:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L241-L241

241:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) { // <= FOUND
242:         params = abi.encode(operator, tokenAddress);
243:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L251-L251

251:     function getParamsMintBurn(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) { // <= FOUND
252:         params = abi.encode(operator, tokenAddress);
253:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L30-L30

30:     function contractId() internal pure override returns (bytes32) { // <= FOUND
31:         return CONTRACT_ID;
32:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenLockUnlock.sol#L8-L8

8:     function tokenManagerRequiresApproval() public pure override returns (bool) { // <= FOUND
9:         return true;
10:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L8-L8

8:     function tokenManagerRequiresApproval() public pure override returns (bool) { // <= FOUND
9:         return false;
10:     }
136:     function transmitInterchainTransfer(
137:         address sender,
138:         string calldata destinationChain,
139:         bytes calldata destinationAddress,
140:         uint256 amount,
141:         bytes calldata metadata
142:     ) external payable virtual onlyToken {
143:         amount = _takeToken(sender, amount);
144:         _addFlowOut(amount);
145:         interchainTokenService.transmitSendToken{ value: msg.value }(
146:             _getTokenId(),
147:             sender,
148:             destinationChain,
149:             destinationAddress,
150:             amount,
151:             metadata
152:         );
153:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L24-L24

24:     function implementationType() external pure returns (uint256) { // <= FOUND
25:         return 0;
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L25-L25

25:     function implementationType() external pure returns (uint256) { // <= FOUND
26:         return 1;
27:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L28-L28

28:     function implementationType() external pure returns (uint256) { // <= FOUND
29:         return 2;
30:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L555-L555

555:     function _setup(bytes calldata params) internal override { // <= FOUND
556:         _setOperator(params.toAddress());
557:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L40-L40

40:     function _setup(bytes calldata params) internal override { // <= FOUND
41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));
42:         uint256 length = trustedChainNames.length;
43:         if (length != trustedAddresses.length) revert LengthMismatch();
44:         for (uint256 i; i < length; ++i) {
45:             addTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
46:         }
47:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L32-L32

32:     function _setup(bytes calldata params) internal override { // <= FOUND
33:         
34:         (, address tokenAddress) = abi.decode(params, (bytes, address));
35:         _setTokenAddress(tokenAddress);
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L36-L36

36:     function _setup(bytes calldata params) internal override { // <= FOUND
37:         
38:         (, address tokenAddress_, address liquidityPool_) = abi.decode(params, (bytes, address, address));
39:         _setTokenAddress(tokenAddress_);
40:         _setLiquidityPool(liquidityPool_);
41:     }
148:     function getExpressReceiveToken(
149:         bytes32 tokenId,
150:         address destinationAddress,
151:         uint256 amount,
152:         bytes32 commandId
153:     ) public view returns (address expressCaller) {
154:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
155:         assembly {
156:             expressCaller := sload(slot)
157:         }
158:     }
171:     function getExpressReceiveTokenWithData(
172:         bytes32 tokenId,
173:         string memory sourceChain,
174:         bytes memory sourceAddress,
175:         address destinationAddress,
176:         uint256 amount,
177:         bytes calldata data,
178:         bytes32 commandId
179:     ) public view returns (address expressCaller) {
180:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
181:             tokenId,
182:             sourceChain,
183:             sourceAddress,
184:             destinationAddress,
185:             amount,
186:             data,
187:             commandId
188:         );
189:         assembly {
190:             expressCaller := sload(slot)
191:         }
192:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator { // <= FOUND
52:         _setOperator(operator_);
53:     }

[LOW-28] Constructors contains no validation

Number of instances found

7

Resolution

In Solidity, when values are being assigned in constructors to unsigned or integer variables, it's crucial to ensure the provided values adhere to the protocol's specific operational boundaries as laid out in the project specifications and documentation. If the constructors lack appropriate validation checks, there's a risk of setting state variables with values that could cause unexpected and potentially detrimental behavior within the contract's operations, violating the intended logic of the protocol. This can compromise the contract's security and impact the maintainability and reliability of the system. In order to avoid such issues, it is recommended to incorporate rigorous validation checks in constructors. These checks should align with the project's defined rules and constraints, making use of Solidity's built-in require function to enforce these conditions. If the validation checks fail, the require function will cause the transaction to revert, ensuring the integrity and adherence to the protocol's expected behavior.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L33-L42

33:     constructor(
34:         address gateway,
35:         string memory governanceChain_,
36:         string memory governanceAddress_,
37:         uint256 minimumTimeDelay // <= FOUND
38:     ) AxelarExecutable(gateway) TimeLock(minimumTimeDelay) {
39:         governanceChain = governanceChain_; // <= FOUND
40:         governanceAddress = governanceAddress_; // <= FOUND
41:         governanceChainHash = keccak256(bytes(governanceChain_)); // <= FOUND
42:         governanceAddressHash = keccak256(bytes(governanceAddress_)); // <= FOUND
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L21-L22

21:     constructor(uint256 minimumTimeDelay) { // <= FOUND
22:         _minimumTimeLockDelay = minimumTimeDelay; // <= FOUND
23:     }

[LOW-29] Utilizing delegatecall within a loop

Number of instances found

1

Resolution

Using delegatecall in a for loop can lead to high gas costs, as delegatecall is an expensive operation and its costs compound when used in a loop. Additionally, it can pose security risks including reentrancy attacks, as it executes code in the calling contract's context. The function selector collisions can also lead to unpredictable behaviour. To mitigate these risks, control the loop's iterations, apply a reentrancy guard, strictly audit contracts called via delegatecall, and consider alternatives like call or proxy patterns if the use case allows. Always thoroughly vet contracts involved in delegatecall operations.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L25-L25

24:        for (uint256 i = 0; i < data.length; ++i) {
25:             (bool success, bytes memory result) = address(this).delegatecall(data[i]); // <= FOUND
26: 
27:             if (!success) {
28:                 revert(string(result));
29:             }
30: 
31:             results[i] = result;
32:         }

[LOW-30] Must approve or increase allowance first

Number of instances found

7

Resolution

In the context of ERC20 tokens, a token holder needs to "approve" another account to transfer a certain amount of their tokens on their behalf. This is accomplished by calling the approve() function, which takes the address of the spender and the amount they're allowed to spend as parameters.

This approval step is a crucial part of the ERC20 standard because it allows for secure delegated transfers. A common use case for this feature is in decentralized exchanges or DeFi protocols, where a user can approve a smart contract to transfer tokens on their behalf.

After the approval step, the approved account (or contract) can then transfer tokens up to the approved amount from the token holder's account by calling the transferFrom() function. This function takes three parameters: the address of the token holder, the recipient's address, and the amount to transfer.

If an account tries to call transferFrom() before the token holder has called approve(), the transaction will fail because the ERC20 contract checks whether the transferFrom() caller has an adequate allowance.

In summary, if a contract or user needs to move ERC20 tokens on behalf of another account, it's necessary to ensure that the token holder has first called approve() to set a sufficient allowance. This is a key aspect of ERC20 token security and functionality.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L529-L546

529:     function _burnTokenFrom(
530:         address sender,
531:         string memory symbol,
532:         uint256 amount
533:     ) internal {
534:         address tokenAddress = tokenAddresses(symbol);
535: 
536:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
537:         if (amount == 0) revert InvalidAmount();
538: 
539:         TokenType tokenType = _getTokenType(symbol);
540: 
541:         if (tokenType == TokenType.External) {
542:             IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount); // <= FOUND
543:         } else if (tokenType == TokenType.InternalBurnableFrom) {
544:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount));
545:         } else {
546:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount); // <= FOUND
547:             IBurnableMintableCappedERC20(tokenAddress).burn(bytes32(0));
548:         }
549:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L451

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external {
445:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
446: 
447:         address caller = msg.sender;
448:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
449:         IERC20 token = IERC20(tokenManager.tokenAddress());
450: 
451:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
452: 
453:         _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);
454:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L482

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external {
476:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
477: 
478:         address caller = msg.sender;
479:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
480:         IERC20 token = IERC20(tokenManager.tokenAddress());
481: 
482:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount); // <= FOUND
483: 
484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);
485: 
486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
487:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L44-L48

44:     function _takeToken(address from, uint256 amount) internal override returns (uint256) {
45:         IERC20 token = IERC20(tokenAddress());
46:         uint256 balance = token.balanceOf(address(this));
47: 
48:         SafeTokenTransferFrom.safeTransferFrom(token, from, address(this), amount); // <= FOUND
49: 
50:         
51:         return IERC20(token).balanceOf(address(this)) - balance;
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L77-L82

77:     function _takeToken(address from, uint256 amount) internal override returns (uint256) {
78:         IERC20 token = IERC20(tokenAddress());
79:         address liquidityPool_ = liquidityPool();
80:         uint256 balance = token.balanceOf(liquidityPool_);
81: 
82:         SafeTokenTransferFrom.safeTransferFrom(token, from, liquidityPool_, amount); // <= FOUND
83: 
84:         
85:         return IERC20(token).balanceOf(liquidityPool_) - balance;
86:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L94-L98

94:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
95:         IERC20 token = IERC20(tokenAddress());
96:         uint256 balance = IERC20(token).balanceOf(to);
97: 
98:         SafeTokenTransferFrom.safeTransferFrom(token, liquidityPool(), to, amount); // <= FOUND
99: 
100:         return IERC20(token).balanceOf(to) - balance;
101:     }

[NC-1] Floating pragma should be avoided

Number of instances found

73

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L3-L3

3: pragma solidity ^0.8.0; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L3-L3

3: pragma solidity ^0.8.9; // <= FOUND

[NC-2] Empty function blocks

Number of instances found

7

Resolution

Empty code blocks (i.e., {}) in a Solidity contract can be harmful as they can lead to ambiguity, misinterpretation, and unintended behavior. When developers encounter empty code blocks, it may be unclear whether the absence of code is intentional or the result of an oversight. This uncertainty can cause confusion during development, testing, and debugging, increasing the likelihood of introducing errors or vulnerabilities. Moreover, empty code blocks may give a false impression of implemented functionality or security measures, creating a misleading sense of assurance. To ensure clarity and maintainability, it is essential to avoid empty code blocks and explicitly document the intended behavior or any intentional omissions.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L126-L126

126:     function _beforeProposalExecuted(
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         bytes calldata payload
130:     ) internal virtual {
131:         
132:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L142-L142

142:     function _onProposalExecuted(
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual {
148:         
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual {
179:         
180:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L32-L32

32:     function setup(bytes calldata params) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L33-L33

33:     constructor(
34:         address gateway,
35:         string memory governanceChain,
36:         string memory governanceAddress,
37:         uint256 minimumTimeDelay,
38:         address[] memory cosigners,
39:         uint256 threshold
40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L20-L20

20:     constructor(address[] memory accounts, uint256 threshold) MultisigBase(accounts, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L26-L26

26:     constructor(
27:         address implementationAddress,
28:         address owner,
29:         bytes memory setupParams
30:     ) Proxy(implementationAddress, owner, setupParams) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L19-L19

19:     constructor(
20:         address implementationAddress,
21:         address owner,
22:         address operator
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L20-L20

20:     constructor(
21:         address implementationAddress,
22:         address owner,
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L19-L19

19:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L22-L22

22:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}

[NC-3] In functions which accept an address as a parameter, there should be a zero address check to prevent bugs

Number of instances found

74

Resolution

Implement a zero address check to ensure input isn't the zero address

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L52-L52

52:     function getProposalEta(
53:         address target,
54:         bytes calldata callData,
55:         uint256 nativeValue
56:     ) external view returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L68-L68

68:     function executeProposal(
69:         address target,
70:         bytes calldata callData,
71:         uint256 nativeValue
72:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L113-L113

113:     function _processCommand(
114:         uint256 commandId,
115:         address target,
116:         bytes memory callData,
117:         uint256 nativeValue,
118:         uint256 eta
119:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L143-L143

143:     function _getProposalHash(
144:         address target,
145:         bytes memory callData,
146:         uint256 nativeValue
147:     ) internal pure returns (bytes32) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L48

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L72

72:     function _processCommand(
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L103-L103

103:     function isSigner(address account) external view override returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L111-L111

111:     function hasSignerVoted(address account, bytes32 topic) external view override returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L142-L142

142:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L149

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L30-L30

30:     function execute(
31:         address target,
32:         bytes calldata callData,
33:         uint256 nativeValue
34:     ) external payable onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L11-L11

11:     function _call(
12:         address target,
13:         bytes calldata callData,
14:         uint256 nativeValue
15:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L125-L125

125:     function isContractCallApproved(
126:         bytes32 commandId,
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         address contractAddress,
130:         bytes32 payloadHash
131:     ) external view override returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L135-L135

135:     function isContractCallAndMintApproved(
136:         bytes32 commandId,
137:         string calldata sourceChain,
138:         string calldata sourceAddress,
139:         address contractAddress,
140:         bytes32 payloadHash,
141:         string calldata symbol,
142:         uint256 amount
143:     ) external view override returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L253-L253

253:     function transferGovernance(address newGovernance) external override onlyGovernance 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L259-L259

259:     function transferMintLimiter(address newMintLimiter) external override onlyMintLimiter 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L279-L279

279:     function upgrade(
280:         address newImplementation,
281:         bytes32 newImplementationCodeHash,
282:         bytes calldata setupParams
283:     ) external override onlyGovernance 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L504-L504

504:     function _hasCode(address addr) internal view returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L511-L511

511:     function _mintToken(
512:         string memory symbol,
513:         address account,
514:         uint256 amount
515:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L529-L529

529:     function _burnTokenFrom(
530:         address sender,
531:         string memory symbol,
532:         uint256 amount
533:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L576-L576

576:     function _getIsContractCallApprovedKey(
577:         bytes32 commandId,
578:         string memory sourceChain,
579:         string memory sourceAddress,
580:         address contractAddress,
581:         bytes32 payloadHash
582:     ) internal pure returns (bytes32) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L586-L586

586:     function _getIsContractCallApprovedWithMintKey(
587:         bytes32 commandId,
588:         string memory sourceChain,
589:         string memory sourceAddress,
590:         address contractAddress,
591:         bytes32 payloadHash,
592:         string memory symbol,
593:         uint256 amount
594:     ) internal pure returns (bytes32) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L643-L643

643:     function _setTokenAddress(string memory symbol, address tokenAddress) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved(
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint(
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L676-L676

676:     function _setImplementation(address newImplementation) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L680-L680

680:     function _transferGovernance(address newGovernance) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L686-L686

686:     function _transferMintLimiter(address newMintLimiter) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L92

92:     function setWhitelistedProposalCaller(
93:         string calldata sourceChain,
94:         address sourceCaller,
95:         bool whitelisted
96:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L107

107:     function setWhitelistedProposalSender(
108:         string calldata sourceChain,
109:         address sourceSender,
110:         bool whitelisted
111:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L142-L142

142:     function _onProposalExecuted(
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L58

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L67-L67

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L71

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L52-L52

52:     function upgrade(
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L79-L79

79:     function interchainTransferFrom(
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L202-L202

202:     function getCanonicalTokenId(address tokenAddress) public view returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L213-L213

213:     function getCustomTokenId(address sender, bytes32 salt) public pure returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L241-L241

241:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L251-L251

251:     function getParamsMintBurn(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L262-L262

262:     function getParamsLiquidityPool(
263:         bytes memory operator,
264:         address tokenAddress,
265:         address liquidityPoolAddress
266:     ) public pure returns (bytes memory params) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L309-L309

309:     function registerCanonicalToken(address tokenAddress) external payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L388-L388

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name,
391:         string calldata symbol,
392:         uint8 decimals,
393:         uint256 mintAmount,
394:         address distributor
395:     ) external payable notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L439

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L467

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L502-L502

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType)
560:         internal
561:         pure
562:         returns (address implementation)
563:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L707-L707

707:     function _callContract(
708:         string calldata destinationChain,
709:         bytes memory payload,
710:         uint256 gasValue,
711:         address refundTo
712:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L726-L726

726:     function _validateToken(address tokenAddress)
727:         internal
728:         returns (
729:             string memory name,
730:             string memory symbol,
731:             uint8 decimals
732:         )
733:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L841-L841

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals,
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L880-L880

880:     function _expressExecuteWithInterchainTokenToken(
881:         bytes32 tokenId,
882:         address destinationAddress,
883:         string memory sourceChain,
884:         bytes memory sourceAddress,
885:         bytes calldata data,
886:         uint256 amount
887:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L30-L30

30:     function toBytes(address addr) internal pure returns (bytes memory bytesAddress) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L76-L76

76:     function mint(address account, uint256 amount) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L86-L86

86:     function burn(address account, uint256 amount) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L136-L136

136:     function transmitInterchainTransfer(
137:         address sender,
138:         string calldata destinationChain,
139:         bytes calldata destinationAddress,
140:         uint256 amount,
141:         bytes calldata metadata
142:     ) external payable virtual onlyToken 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L161-L161

161:     function giveToken(address destinationAddress, uint256 amount) external onlyService returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L38-L38

38:     function _setTokenAddress(address tokenAddress_) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L44-L44

44:     function _takeToken(address from, uint256 amount) internal override returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L60-L60

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L47-L47

47:     function _setLiquidityPool(address liquidityPool_) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67-L67

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L39-L39

39:     function _setDistributor(address distributor_) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L51-L51

51:     function setDistributor(address distr) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L26-L26

26:     function _getExpressReceiveTokenSlot(
27:         bytes32 tokenId,
28:         address destinationAddress,
29:         uint256 amount,
30:         bytes32 commandId
31:     ) internal pure returns (uint256 slot) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L46-L46

46:     function _getExpressReceiveTokenWithDataSlot(
47:         bytes32 tokenId,
48:         string memory sourceChain,
49:         bytes memory sourceAddress,
50:         address destinationAddress,
51:         uint256 amount,
52:         bytes memory data,
53:         bytes32 commandId
54:     ) internal pure returns (uint256 slot) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L148-L148

148:     function getExpressReceiveToken(
149:         bytes32 tokenId,
150:         address destinationAddress,
151:         uint256 amount,
152:         bytes32 commandId
153:     ) public view returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L171-L171

171:     function getExpressReceiveTokenWithData(
172:         bytes32 tokenId,
173:         string memory sourceChain,
174:         bytes memory sourceAddress,
175:         address destinationAddress,
176:         uint256 amount,
177:         bytes calldata data,
178:         bytes32 commandId
179:     ) public view returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L39-L39

39:     function _setOperator(address operator_) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L49-L49

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name,
54:         string calldata symbol,
55:         uint8 decimals,
56:         uint256 mintAmount,
57:         address mintTo
58:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L35-L35

35:     function init(
36:         address implementationAddress,
37:         address newOwner,
38:         bytes memory params
39:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L79-L79

79:     function _setExpressReceiveToken(
80:         bytes32 tokenId,
81:         address destinationAddress,
82:         uint256 amount,
83:         bytes32 commandId,
84:         address expressCaller
85:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L110-L110

110:     function _setExpressReceiveTokenWithData(
111:         bytes32 tokenId,
112:         string memory sourceChain,
113:         bytes memory sourceAddress,
114:         address destinationAddress,
115:         uint256 amount,
116:         bytes calldata data,
117:         bytes32 commandId,
118:         address expressCaller
119:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L202-L202

202:     function _popExpressReceiveToken(
203:         bytes32 tokenId,
204:         address destinationAddress,
205:         uint256 amount,
206:         bytes32 commandId
207:     ) internal returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L231-L231

231:     function _popExpressReceiveTokenWithData(
232:         bytes32 tokenId,
233:         string memory sourceChain,
234:         bytes memory sourceAddress,
235:         address destinationAddress,
236:         uint256 amount,
237:         bytes memory data,
238:         bytes32 commandId
239:     ) internal returns (address expressCaller) 

[NC-4] Default int values are manually set

Number of instances found

2

Resolution

In instances where a new variable is defined, there is no need to set it to it's default value.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L105-L105

105:         uint256 totalGas = 0; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L118-L118

118:         uint32 version = 0; // <= FOUND

[NC-5] Default address values are manually set

Number of instances found

1

Resolution

In instances where a new variable is defined, there is no need to set it to it's default value.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L63-L63

63:         if (implementation_.code.length == 0) implementation_ = address(0); // <= FOUND

[NC-6] Keccak state variables should be immutable not constant

Number of instances found

23

Resolution

Constant keccak variables should be replaced with immutable variables in Solidity contracts to optimize gas usage and enhance efficiency. While constant variables are evaluated and computed at runtime, immutable variables are assigned during contract deployment and stored directly in the contract bytecode. By using immutable for keccak variables, their hash values are computed only once during deployment, reducing the gas cost associated with repeated computations at runtime. This approach leads to more efficient execution, conserving resources for users, and allowing for smoother contract interactions, ultimately benefiting the overall performance and user experience.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L13-L13

13: bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L44-L44

44: bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L45-L45

45: bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L46-L46

46: bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L47-L47

47: bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L48-L48

48: bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L49-L49

49: bytes32 internal constant PREFIX_TOKEN_MINT_LIMIT = keccak256('token-mint-limit'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L50-L50

50: bytes32 internal constant PREFIX_TOKEN_MINT_AMOUNT = keccak256('token-mint-amount'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L52-L52

52: bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L53-L53

53: bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L54-L54

54: bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L55-L55

55: bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L56-L56

56: bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L57-L57

57: bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L18-L18

18: bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L62-L62

62: bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L63-L63

63: bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L64-L64

64: bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L71-L71

71: bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

12: bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L27-L27

27: bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L15-L15

15: uint256 internal constant PREFIX_FLOW_OUT_AMOUNT = uint256(keccak256('prefix-flow-out-amount')); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L16-L16

16: uint256 internal constant PREFIX_FLOW_IN_AMOUNT = uint256(keccak256('prefix-flow-in-amount')); // <= FOUND

[NC-7] Zero address checks should be present in constructors which take address(es) as parameters

Number of instances found

23

Resolution

Implement a zero address check to prevent wrong address assignation during deployment

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L33-L33

33:     constructor(
34:         address gateway,
35:         string memory governanceChain_,
36:         string memory governanceAddress_,
37:         uint256 minimumTimeDelay
38:     ) AxelarExecutable(gateway) TimeLock(minimumTimeDelay) {
39:         governanceChain = governanceChain_;
40:         governanceAddress = governanceAddress_;
41:         governanceChainHash = keccak256(bytes(governanceChain_));
42:         governanceAddressHash = keccak256(bytes(governanceAddress_));
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L33-L33

33:     constructor(
34:         address gateway,
35:         string memory governanceChain,
36:         string memory governanceAddress,
37:         uint256 minimumTimeDelay,
38:         address[] memory cosigners,
39:         uint256 threshold
40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L35-L35

35:     constructor(address[] memory accounts, uint256 threshold) {
36:         _rotateSigners(accounts, threshold);
37:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L20-L20

20:     constructor(address[] memory accounts, uint256 threshold) MultisigBase(accounts, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L64-L64

64:     constructor(address authModule_, address tokenDeployerImplementation_) {
65:         if (authModule_.code.length == 0) revert InvalidAuthModule();
66:         if (tokenDeployerImplementation_.code.length == 0) revert InvalidTokenDeployer();
67: 
68:         AUTH_MODULE = authModule_;
69:         TOKEN_DEPLOYER_IMPLEMENTATION = tokenDeployerImplementation_;
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L42-L42

42:     constructor(address _gateway, address _gasService) {
43:         gateway = IAxelarGateway(_gateway);
44:         gasService = IAxelarGasService(_gasService);
45:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L29-L29

29:     constructor(address _gateway, address _owner) AxelarExecutable(_gateway) {
30:         _transferOwnership(_owner);
31:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L25-L25

25:     constructor(
26:         address implementationAddress,
27:         address owner,
28:         bytes memory setupParams
29:     ) {
30:         if (owner == address(0)) revert InvalidOwner();
31: 
32:         bytes32 id = contractId();
33:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();
34: 
35:         assembly {
36:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
37:             sstore(_OWNER_SLOT, owner)
38:         }
39: 
40:         if (setupParams.length != 0) {
41:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, setupParams));
42:             if (!success) revert SetupFailed();
43:         }
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L26-L26

26:     constructor(
27:         address implementationAddress,
28:         address owner,
29:         bytes memory setupParams
30:     ) Proxy(implementationAddress, owner, setupParams) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L23-L23

23:     constructor(address implementationAddress) {
24:         implementation = implementationAddress;
25:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L83-L83

83:     constructor(
84:         address tokenManagerDeployer_,
85:         address standardizedTokenDeployer_,
86:         address gateway_,
87:         address gasService_,
88:         address remoteAddressValidator_,
89:         address[] memory tokenManagerImplementations,
90:         string memory chainName_
91:     ) AxelarExecutable(gateway_) {
92:         if (
93:             remoteAddressValidator_ == address(0) ||
94:             gasService_ == address(0) ||
95:             tokenManagerDeployer_ == address(0) ||
96:             standardizedTokenDeployer_ == address(0)
97:         ) revert ZeroAddress();
98:         remoteAddressValidator = IRemoteAddressValidator(remoteAddressValidator_);
99:         gasService = IAxelarGasService(gasService_);
100:         tokenManagerDeployer = tokenManagerDeployer_;
101:         standardizedTokenDeployer = standardizedTokenDeployer_;
102:         deployer = ITokenManagerDeployer(tokenManagerDeployer_).deployer();
103: 
104:         if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();
105: 
106:         implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK);
107:         implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L19-L19

19:     constructor(
20:         address implementationAddress,
21:         address owner,
22:         address operator
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L20-L20

20:     constructor(
21:         address implementationAddress,
22:         address owner,
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L21-L21

21:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) {
22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();
23: 
24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
25:         if (!success) revert SetupFailed();
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L25-L25

25:     constructor(
26:         address interchainTokenServiceAddress_,
27:         uint256 implementationType_,
28:         bytes32 tokenId_,
29:         bytes memory params
30:     ) {
31:         interchainTokenServiceAddress = IInterchainTokenService(interchainTokenServiceAddress_);
32:         implementationType = implementationType_;
33:         tokenId = tokenId_;
34:         address impl = _getImplementation(IInterchainTokenService(interchainTokenServiceAddress_), implementationType_);
35: 
36:         (bool success, ) = impl.delegatecall(abi.encodeWithSelector(TokenManagerProxy.setup.selector, params));
37:         if (!success) revert SetupFailed();
38:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L27-L27

27:     constructor(address _interchainTokenServiceAddress) {
28:         if (_interchainTokenServiceAddress == address(0)) revert ZeroAddress();
29:         interchainTokenServiceAddress = _interchainTokenServiceAddress;
30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString())));
31:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L27-L27

27:     constructor(address interchainTokenService_) {
28:         if (interchainTokenService_ == address(0)) revert TokenLinkerZeroAddress();
29:         interchainTokenService = IInterchainTokenService(interchainTokenService_);
30:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L19-L19

19:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L22-L22

22:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L26-L26

26:     constructor(
27:         address deployer_,
28:         address implementationLockUnlockAddress_,
29:         address implementationMintBurnAddress_
30:     ) {
31:         if (deployer_ == address(0) || implementationLockUnlockAddress_ == address(0) || implementationMintBurnAddress_ == address(0))
32:             revert AddressZero();
33:         deployer = Create3Deployer(deployer_);
34:         implementationLockUnlockAddress = implementationLockUnlockAddress_;
35:         implementationMintBurnAddress = implementationMintBurnAddress_;
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L22-L22

22:     constructor(address deployer_) {
23:         if (deployer_ == address(0)) revert AddressZero();
24:         deployer = Create3Deployer(deployer_);
25:     }

[NC-8] Ownable2Step should be used in place of Ownable

Number of instances found

1

Resolution

Ownable2Step further prevents risks posed by centralised privileges as there is a smaller likelihood of the owner being wrongfully changed

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L22-L22

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable  // <= FOUND

[NC-9] Functions which are either private or internal should have a preceding _ in their name

Number of instances found

7

Resolution

Add a preceding underscore to the function name, take care to refactor where there functions are called

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L51-L51

51:     function deploy(bytes32 salt, bytes memory bytecode) internal returns (address deployed) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L71

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L39-L39

39:     function contractId() internal pure virtual returns (bytes32) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L17-L17

17:     function toAddress(bytes memory bytesAddress) internal pure returns (address addr) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L30-L30

30:     function toBytes(address addr) internal pure returns (bytes memory bytesAddress) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L30-L30

30:     function contractId() internal pure override returns (bytes32) 

[NC-10] Private and internal state variables should have a preceding _ in their name unless they are constants

Number of instances found

9

Resolution

Add a preceding underscore to the state variable name, take care to refactor where there variables are read/wrote

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L13-L13

13: address private immutable implementationAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L60-L60

60: address internal immutable AUTH_MODULE; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L62-L62

62: address internal immutable TOKEN_DEPLOYER_IMPLEMENTATION; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L51-L51

51: address internal immutable implementationLockUnlock; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L52-L52

52: address internal immutable implementationMintBurn; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L53-L53

53: address internal immutable implementationLiquidityPool; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L59-L59

59: bytes32 internal immutable chainNameHash; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L60-L60

60: bytes32 internal immutable chainName; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L15-L15

15: address internal immutable implementationAddress; // <= FOUND

[NC-11] Contract lines should not be longer than 110 characters for readability

Number of instances found

113

Resolution

Consider spreading these lines over multiple lines to aid in readability and the support of VIM users everywhere.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IInterchainGovernance.sol#L18-L18

18:     event ProposalScheduled(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed eta); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IInterchainGovernance.sol#L19-L19

19:     event ProposalCancelled(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed eta); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IInterchainGovernance.sol#L20-L20

20:     event ProposalExecuted(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed timestamp); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L92-L92

92:         if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L95-L95

95:         (uint256 command, address target, bytes memory callData, uint256 nativeValue, uint256 eta) = abi.decode( // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IAxelarServiceGovernance.sol#L15-L15

15:     event MultisigApproved(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IAxelarServiceGovernance.sol#L16-L16

16:     event MultisigCancelled(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IAxelarServiceGovernance.sol#L17-L17

17:     event MultisigExecuted(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L40-L40

40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L35-L35

35:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L38-L38

38:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L41-L41

41:     bytes32 internal constant KEY_MINT_LIMITER = bytes32(0x627f0c11732837b3240a2de89c0b6343512886dd50978b99c76a68c6416a4d92); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L48-L48

48:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L56-L56

56:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L87-L87

87:         if (msg.sender != getAddress(KEY_MINT_LIMITER) && msg.sender != getAddress(KEY_GOVERNANCE)) revert NotMintLimiter(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L111-L111

111:         emit ContractCall(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L122-L122

122:         emit ContractCallWithToken(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload, symbol, amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L132-L132

132:         return getBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L146-L146

146:                 _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L156-L156

156:         bytes32 key = _getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L169-L169

169:         bytes32 key = _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash, symbol, amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L265-L265

265:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L293-L293

293:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(IAxelarGateway.setup.selector, setupParams)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L310-L310

310:         (address governance_, address mintLimiter_, bytes memory newOperatorsData) = abi.decode(params, (address, address, bytes)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L373-L373

373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L385-L385

385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode( // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L421-L421

421:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L434-L434

434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L442-L442

442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler))) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L445-L445

445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L465-L465

465:         emit ContractCallApproved(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, sourceTxHash, sourceEventIndex); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L480-L480

480:         _setContractCallApprovedWithMint(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L508-L508

508:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L544-L544

544:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L546-L546

546:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L583-L583

583:         return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L658-L658

658:         _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L671-L671

671:             _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount), // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L59-L59

59:     function sendProposals(InterchainCalls.InterchainCall[] calldata interchainCalls) external payable override { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L85-L85

85:         _sendProposal(InterchainCalls.InterchainCall(destinationChain, destinationContract, msg.value, calls)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L54-L54

54:         (address interchainProposalCaller, InterchainCalls.Call[] memory calls) = abi.decode(payload, (address, InterchainCalls.Call[])); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L66-L66

66:         emit ProposalExecuted(keccak256(abi.encode(sourceChain, sourceAddress, interchainProposalCaller, payload))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol#L7-L7

7:     event WhitelistedProposalCallerSet(string indexed sourceChain, address indexed sourceCaller, bool whitelisted); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol#L10-L10

10:     event WhitelistedProposalSenderSet(string indexed sourceChain, address indexed sourceSender, bool whitelisted); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L72

72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L14-L14

14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L16-L16

16:     bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L50-L50

50:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L41-L41

41:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, setupParams)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L57-L57

57:         if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L61-L61

61:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L58-L58

58:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, params)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L72-L72

72:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) public returns (address finalImplementation_) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L81-L81

81:             (bool success, ) = finalImplementation_.delegatecall(abi.encodeWithSelector(BaseProxy.setup.selector, setupParams)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L66-L66

66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L104-L104

104:         if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L106-L106

106:         implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L107-L107

107:         implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L108-L108

108:         implementationLiquidityPool = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LIQUIDITY_POOL); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L172-L172

172:         if (ITokenManagerProxy(tokenManagerAddress).tokenId() != tokenId) revert TokenManagerDoesNotExist(tokenId); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L241-L241

241:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L251-L251

251:     function getParamsMintBurn(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L309-L309

309:     function registerCanonicalToken(address tokenAddress) external payable notPaused returns (bytes32 tokenId) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L313-L313

313:         _deployTokenManager(tokenId, TokenManagerType.LOCK_UNLOCK, abi.encode(address(this).toBytes(), tokenAddress)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L333-L333

333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L334-L334

334:         _deployRemoteStandardizedToken(tokenId, tokenName, tokenSymbol, tokenDecimals, '', '', destinationChain, gasValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L399-L399

399:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L428-L428

428:         _deployRemoteStandardizedToken(tokenId, name, symbol, decimals, distributor, operator, destinationChain, gasValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L484-L484

484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L486-L486

486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L520-L520

520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L522-L522

522:         emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L566-L566

566:         if (ITokenManager(implementation).implementationType() != uint256(tokenManagerType)) revert InvalidTokenManagerImplementation(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L600-L600

600:         (, bytes32 tokenId, bytes memory destinationAddressBytes, uint256 amount) = abi.decode(payload, (uint256, bytes32, bytes, uint256)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L658-L658

658:         IInterchainTokenExpressExecutable(destinationAddress).executeWithInterchainToken(sourceChain, sourceAddress, data, tokenId, amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L690-L690

690:         address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L757-L757

757:         emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L814-L814

814:             abi.encodeWithSelector(ITokenManagerDeployer.deployTokenManager.selector, tokenId, tokenManagerType, params) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L872-L872

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L14-L14

14: interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAxelarExecutable, IPausable, IMulticall { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L32-L32

32:     event TokenSent(bytes32 tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L41-L41

41:     event TokenReceived(bytes32 indexed tokenId, string sourceChain, address indexed destinationAddress, uint256 indexed amount); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L67-L67

67:     event TokenManagerDeployed(bytes32 indexed tokenId, TokenManagerType indexed tokenManagerType, bytes params); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L145-L145

145:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) external pure returns (bytes memory params); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L153-L153

153:     function getParamsMintBurn(bytes memory operator, address tokenAddress) external pure returns (bytes memory params); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L22-L22

22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L24-L24

24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L34-L34

34:         address impl = _getImplementation(IInterchainTokenService(interchainTokenServiceAddress_), implementationType_); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L36-L36

36:         (bool success, ) = impl.delegatecall(abi.encodeWithSelector(TokenManagerProxy.setup.selector, params)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L54-L54

54:     function _getImplementation(IInterchainTokenService interchainTokenServiceAddress_, uint256 implementationType_) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L30-L30

30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString()))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L41-L41

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[])); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L69-L69

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) { // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L25-L25

25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L54-L54

54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L63-L63

63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L22-L22

22:     uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L48-L48

48:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.burn.selector, from, amount)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L62-L62

62:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.mint.selector, to, amount)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L19-L19

19:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L15-L15

15:     uint256 internal constant DISTRIBUTOR_SLOT = 0x71c5a35e45a25c49e8f747acd4bcb869814b3d104c492d2554f4c46e12371f56; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L14-L14

14:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN = 0x67c7b41c1cb0375e36084c4ec399d005168e83425fa471b9224f6115af865619; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L16-L16

16:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA = 0x3e607cc12a253b1d9f677a03d298ad869a90a8ba4bd0fb5739e7d79db7cdeaad; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L32-L32

32:         slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L137-L137

137:         emit ExpressReceiveWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, expressCaller); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L14-L14

14:     uint256 internal constant FLOW_LIMIT_SLOT = 0x201b7a0b7c19aaddc4ce9579b7df8d2db123805861bc7763627f13e04d8af42f; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L15-L15

15:     uint256 internal constant OPERATOR_SLOT = 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d7; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L31-L31

31:         if (deployer_ == address(0) || implementationLockUnlockAddress_ == address(0) || implementationMintBurnAddress_ == address(0)) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L60-L60

60:         address implementationAddress = distributor == tokenManager ? implementationMintBurnAddress : implementationLockUnlockAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L62-L62

62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L63-L63

63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params)); // <= FOUND

[NC-12] Use newer solidity versions

Number of instances found

145

Resolution

Newer solidity versions have new functionality and are generally more gas efficient too (0.8.19) as such it makes sense to use them provided it is safe to do so

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L3-L3

3: pragma solidity ^0.8.0; // <= FOUND
3: pragma solidity ^0.8.9;

[NC-13] Explicitly define visibility of state variables to prevent misconceptions on what can access the variable

Number of instances found

1

Resolution

Such state variables should be marked as private as this is the default visibility

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L14-L14

14: ExpressCallHandler,

[NC-14] Function names should differ to make the code more readable

Number of instances found

48

Resolution

In Solidity, while function overriding allows for functions with the same name to coexist, it is advisable to avoid this practice to enhance code readability and maintainability. Having multiple functions with the same name, even with different parameters or in inherited contracts, can cause confusion and increase the likelihood of errors during development, testing, and debugging. Using distinct and descriptive function names not only clarifies the purpose and behavior of each function, but also helps prevent unintended function calls or incorrect overriding. By adopting a clear and consistent naming convention, developers can create more comprehensible and maintainable smart contracts.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L113-L113

113:     function _processCommand( // <= FOUND
114:         uint256 commandId,
115:         address target,
116:         bytes memory callData,
117:         uint256 nativeValue,
118:         uint256 eta
119:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L72

72:     function _processCommand( // <= FOUND
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L30-L30

30:     function execute( // <= FOUND
31:         address target,
32:         bytes calldata callData,
33:         uint256 nativeValue
34:     ) external payable onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L322

322:     function execute(bytes calldata input) external override  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L41-L41

41:     function _execute( // <= FOUND
42:         string calldata sourceChain,
43:         string calldata sourceAddress,
44:         bytes calldata payload
45:     ) internal override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L575-L575

575:     function _execute( // <= FOUND
576:         string calldata sourceChain,
577:         string calldata sourceAddress,
578:         bytes calldata payload
579:     ) internal override onlyRemoteService(sourceChain, sourceAddress) notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L24-L24

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L29-L29

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L21-L21

21:     function deploy(bytes memory bytecode) external  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L51-L51

51:     function deploy(bytes32 salt, bytes memory bytecode) internal returns (address deployed)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L42-L42

42:     function deployAndInit( // <= FOUND
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L58

58:     function deployedAddress( // <= FOUND
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L67-L67

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L71

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L227-L227

227:     function implementation() public view override returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L22-L22

22:     function implementation() public view virtual returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L39-L39

39:     function implementation() public view returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L37-L37

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L44-L44

44:     function implementation() public view returns (address impl)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external override  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L78-L78

78:     function setup(bytes calldata data) external override onlyProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external override onlyProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L245-L245

245:     function contractId() public pure returns (bytes32)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L39-L39

39:     function contractId() internal pure virtual returns (bytes32)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L36-L36

36:     function contractId() external pure returns (bytes32)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L30-L30

30:     function contractId() internal pure override returns (bytes32)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L279-L279

279:     function upgrade( // <= FOUND
280:         address newImplementation,
281:         bytes32 newImplementationCodeHash,
282:         bytes calldata setupParams
283:     ) external override onlyGovernance 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L52-L52

52:     function upgrade( // <= FOUND
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L40-L40

40:     function _setup(bytes calldata params) internal override  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L8-L8

8:     function tokenManagerRequiresApproval() public pure override returns (bool)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L96-L96

96:     function sendToken( // <= FOUND
97:         string calldata destinationChain,
98:         string calldata destinationAddress,
99:         string calldata symbol,
100:         uint256 amount
101:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L83-L83

83:     function sendToken( // <= FOUND
84:         string calldata destinationChain,
85:         bytes calldata destinationAddress,
86:         uint256 amount,
87:         bytes calldata metadata
88:     ) external payable virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L534-L534

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L171-L171

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L643-L643

643:     function _setTokenAddress(string memory symbol, address tokenAddress) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L38-L38

38:     function _setTokenAddress(address tokenAddress_) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L24-L24

24:     function implementationType() external pure returns (uint256)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L44-L44

44:     function _takeToken(address from, uint256 amount) internal override returns (uint256)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L60-L60

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L275-L275

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L24-L24

24:     function getFlowLimit() public view returns (uint256 flowLimit)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L285-L285

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L63-L63

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L295-L295

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L75-L75

75:     function getFlowInAmount() external view returns (uint256 flowInAmount)  // <= FOUND

[NC-15] Functions should not be longer than 50 lines

Number of instances found

1

Resolution

Overly complex code can make understanding functionality more difficult, try to further modularise your code to ensure readability

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L322

322:     function execute(bytes calldata input) external override  // <= FOUND

[NC-16] It is standard for all external and public functions to be override from an interface

Number of instances found

67

Resolution

This is to ensure the whole API is extracted in a interface

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L52-L52

52:     function getProposalEta(
53:         address target,
54:         bytes calldata callData,
55:         uint256 nativeValue
56:     ) external view returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L68-L68

68:     function executeProposal(
69:         address target,
70:         bytes calldata callData,
71:         uint256 nativeValue
72:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L48

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L142-L142

142:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L30-L30

30:     function execute(
31:         address target,
32:         bytes calldata callData,
33:         uint256 nativeValue
34:     ) external payable onlySigners 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L96-L96

96:     function sendToken(
97:         string calldata destinationChain,
98:         string calldata destinationAddress,
99:         string calldata symbol,
100:         uint256 amount
101:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L106-L106

106:     function callContract(
107:         string calldata destinationChain,
108:         string calldata destinationContractAddress,
109:         bytes calldata payload
110:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L114-L114

114:     function callContractWithToken(
115:         string calldata destinationChain,
116:         string calldata destinationContractAddress,
117:         bytes calldata payload,
118:         string calldata symbol,
119:         uint256 amount
120:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L384-L384

384:     function deployToken(bytes calldata params, bytes32) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L420-L420

420:     function mintToken(bytes calldata params, bytes32) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L426-L426

426:     function burnToken(bytes calldata params, bytes32) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L454-L454

454:     function approveContractCall(bytes calldata params, bytes32 commandId) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L468-L468

468:     function approveContractCallWithMint(bytes calldata params, bytes32 commandId) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L494-L494

494:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L24-L24

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L42-L42

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L58

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L29-L29

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L67-L67

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L21-L21

21:     function deploy(bytes memory bytecode) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L35-L35

35:     function init(
36:         address implementationAddress,
37:         address newOwner,
38:         bytes memory params
39:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L43-L43

43:     function interchainTransfer(
44:         string calldata destinationChain,
45:         bytes calldata recipient,
46:         uint256 amount,
47:         bytes calldata metadata
48:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L79-L79

79:     function interchainTransferFrom(
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L36-L36

36:     function contractId() external pure returns (bytes32) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L180-L180

180:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L223-L223

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L275-L275

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L285-L285

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L295-L295

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L309-L309

309:     function registerCanonicalToken(address tokenAddress) external payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L365-L365

365:     function deployRemoteCustomTokenManager(
366:         bytes32 salt,
367:         string calldata destinationChain,
368:         TokenManagerType tokenManagerType,
369:         bytes calldata params,
370:         uint256 gasValue
371:     ) external payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L388-L388

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name,
391:         string calldata symbol,
392:         uint8 decimals,
393:         uint256 mintAmount,
394:         address distributor
395:     ) external payable notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L417-L417

417:     function deployAndRegisterRemoteStandardizedToken(
418:         bytes32 salt,
419:         string calldata name,
420:         string calldata symbol,
421:         uint8 decimals,
422:         bytes memory distributor,
423:         bytes memory operator,
424:         string calldata destinationChain,
425:         uint256 gasValue
426:     ) external payable notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L439

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L467

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L502-L502

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L534-L534

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L547-L547

547:     function setPaused(bool paused) external onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L69-L69

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L95-L95

95:     function removeTrustedAddress(string calldata chain) external onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L106-L106

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L119-L119

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L133-L133

133:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L76-L76

76:     function mint(address account, uint256 amount) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L86-L86

86:     function burn(address account, uint256 amount) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L83-L83

83:     function sendToken(
84:         string calldata destinationChain,
85:         bytes calldata destinationAddress,
86:         uint256 amount,
87:         bytes calldata metadata
88:     ) external payable virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L109-L109

109:     function callContractWithInterchainToken(
110:         string calldata destinationChain,
111:         bytes calldata destinationAddress,
112:         uint256 amount,
113:         bytes calldata data
114:     ) external payable virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L136-L136

136:     function transmitInterchainTransfer(
137:         address sender,
138:         string calldata destinationChain,
139:         bytes calldata destinationAddress,
140:         uint256 amount,
141:         bytes calldata metadata
142:     ) external payable virtual onlyToken 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L161-L161

161:     function giveToken(address destinationAddress, uint256 amount) external onlyService returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L171-L171

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L24-L24

24:     function implementationType() external pure returns (uint256) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67-L67

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L51-L51

51:     function setDistributor(address distr) external onlyDistributor 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L63-L63

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L75-L75

75:     function getFlowInAmount() external view returns (uint256 flowInAmount) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L49-L49

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name,
54:         string calldata symbol,
55:         uint8 decimals,
56:         uint256 mintAmount,
57:         address mintTo
58:     ) external payable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L33-L33

33:     function deployTokenManager(
34:         bytes32 tokenId,
35:         uint256 implementationType,
36:         bytes calldata params
37:     ) external payable 

[NC-17] Functions within contracts are not ordered according to the solidity style guide

Number of instances found

11

Resolution

The following order should be used within contracts

constructor

receive function (if exists)

fallback function (if exists)

external

public

internal

private

Rearrange the contract functions and contructors to fit this ordering

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L15-L15

15: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L17-L17

17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L22-L22

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L17-L17

17: contract FinalProxy is Proxy, IFinalProxy  // <= FOUND
37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L13-L13

13: contract TokenManagerProxy is ITokenManagerProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L12-L12

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L17-L17

17: contract TokenManagerLiquidityPool is TokenManagerAddressStorage  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L13-L13

13: contract Distributable is IDistributable  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L12-L12

12: contract ExpressCallHandler is IExpressCallHandler  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L12-L12

12: contract FlowLimit is IFlowLimit  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L13-L13

13: contract Operatable is IOperatable  // <= FOUND

[NC-18] Emits without msg.sender parameter

Number of instances found

13

Resolution

If msg.sender play a part in the functionality of a function, any emits of this function should include msg.sender to ensure transparency with users

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L30-L33

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {
30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); // <= FOUND
31:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
32: 
33:         emit Deployed(keccak256(bytecode), salt, deployedAddress_); // <= FOUND
34:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L47-L47

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) {
47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt))); // <= FOUND
48: 
49:         
50:         (bool success, ) = deployedAddress_.call(init);
51:         if (!success) revert FailedInit();
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L54-L60

49:     function deployAndInit(
50:         bytes memory bytecode,
51:         bytes32 salt,
52:         bytes calldata init
53:     ) external returns (address deployedAddress_) {
54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); // <= FOUND
55:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
56: 
57:         (bool success, ) = deployedAddress_.call(init);
58:         if (!success) revert FailedInit();
59: 
60:         emit Deployed(keccak256(bytecode), salt, deployedAddress_); // <= FOUND
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L348-L351

343:     function deployCustomTokenManager(
344:         bytes32 salt,
345:         TokenManagerType tokenManagerType,
346:         bytes memory params
347:     ) public payable notPaused returns (bytes32 tokenId) {
348:         address deployer_ = msg.sender; // <= FOUND
349:         tokenId = getCustomTokenId(deployer_, salt);
350:         _deployTokenManager(tokenId, tokenManagerType, params);
351:         emit CustomTokenIdClaimed(tokenId, deployer_, salt); // <= FOUND
352:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L372-L375

365:     function deployRemoteCustomTokenManager(
366:         bytes32 salt,
367:         string calldata destinationChain,
368:         TokenManagerType tokenManagerType,
369:         bytes calldata params,
370:         uint256 gasValue
371:     ) external payable notPaused returns (bytes32 tokenId) {
372:         address deployer_ = msg.sender; // <= FOUND
373:         tokenId = getCustomTokenId(deployer_, salt);
374:         _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params);
375:         emit CustomTokenIdClaimed(tokenId, deployer_, salt); // <= FOUND
376:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L756-L757

748:     function _deployRemoteTokenManager(
749:         bytes32 tokenId,
750:         string calldata destinationChain,
751:         uint256 gasValue,
752:         TokenManagerType tokenManagerType,
753:         bytes memory params
754:     ) internal {
755:         bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params);
756:         _callContract(destinationChain, payload, gasValue, msg.sender); // <= FOUND
757:         emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params); // <= FOUND
758:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L789-L790

770:     function _deployRemoteStandardizedToken(
771:         bytes32 tokenId,
772:         string memory name,
773:         string memory symbol,
774:         uint8 decimals,
775:         bytes memory distributor,
776:         bytes memory operator,
777:         string calldata destinationChain,
778:         uint256 gasValue
779:     ) internal {
780:         bytes memory payload = abi.encode(
781:             SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN,
782:             tokenId,
783:             name,
784:             symbol,
785:             decimals,
786:             distributor,
787:             operator
788:         );
789:         _callContract(destinationChain, payload, gasValue, msg.sender); // <= FOUND
790:         emit RemoteStandardizedTokenAndManagerDeploymentInitialized( // <= FOUND
791:             tokenId,
792:             name,
793:             symbol,
794:             decimals,
795:             distributor,
796:             operator,
797:             destinationChain,
798:             gasValue
799:         );
800:     }

[NC-19] Functions with array parameters should have length checks in place

Number of instances found

3

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L142-L142

142:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners {
143:         _rotateSigners(newAccounts, newThreshold);
144:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L80-L80

80:     function sendProposal(
81:         string memory destinationChain,
82:         string memory destinationContract,
83:         InterchainCalls.Call[] calldata calls
84:     ) external payable override {
85:         _sendProposal(InterchainCalls.InterchainCall(destinationChain, destinationContract, msg.value, calls));
86:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType)
560:         internal
561:         pure
562:         returns (address implementation)
563:     {
564:         implementation = implementaions[uint256(tokenManagerType)];
565:         if (implementation == address(0)) revert ZeroAddress();
566:         if (ITokenManager(implementation).implementationType() != uint256(tokenManagerType)) revert InvalidTokenManagerImplementation();
567:     }

[NC-20] Interface imports should be declared first

Number of instances found

76

Resolution

Amend the ordering of imports to import interfaces first followed by other imports

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L7-L11

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol'; // <= FOUND
8: 
9: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol'; // <= FOUND
10: 
11: import { StandardizedTokenProxy } from '../proxies/StandardizedTokenProxy.sol'; // <= FOUND
12: 
13: 
14: 
15: 
16: 
17: contract StandardizedTokenDeployer is IStandardizedTokenDeployer {
18:     Create3Deployer public immutable deployer;
19:     address public immutable implementationMintBurnAddress;
20:     address public immutable implementationLockUnlockAddress;
21: 
22:     
23: 
24: 
25: 
26: 
27: 
28:     constructor(
29:         address deployer_,
30:         address implementationLockUnlockAddress_,
31:         address implementationMintBurnAddress_
32:     ) {
33:         if (deployer_ == address(0) || implementationLockUnlockAddress_ == address(0) || implementationMintBurnAddress_ == address(0))
34:             revert AddressZero();
35:         deployer = Create3Deployer(deployer_);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L7-L14

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { ITokenManager } from '../interfaces/ITokenManager.sol'; // <= FOUND
8: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol'; // <= FOUND
9: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol'; // <= FOUND
10: 
11: import { Operatable } from '../utils/Operatable.sol'; // <= FOUND
12: import { FlowLimit } from '../utils/FlowLimit.sol'; // <= FOUND
13: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol'; // <= FOUND
14: import { Implementation } from '../utils/Implementation.sol'; // <= FOUND
15: 
16: 
17: 
18: 
19: 
20: abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implementation {
21:     using AddressBytesUtils for bytes;
22: 
23:     IInterchainTokenService public immutable interchainTokenService;
24: 
25:     
26: 
27: 
28: 
29:     constructor(address interchainTokenService_) {
30:         if (interchainTokenService_ == address(0)) revert TokenLinkerZeroAddress();
31:         interchainTokenService = IInterchainTokenService(interchainTokenService_);
32:     }
33: 
34:     
35: 
36: 
37:     modifier onlyService() {
38:         if (msg.sender != address(interchainTokenService)) revert NotService();

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L5-L9

2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; // <= FOUND
6: import { StringToAddress } from '../gmp-sdk/util/AddressString.sol'; // <= FOUND
7: import { AxelarExecutable } from '../gmp-sdk/executable/AxelarExecutable.sol'; // <= FOUND
8: import { IInterchainProposalExecutor } from './interfaces/IInterchainProposalExecutor.sol'; // <= FOUND
9: import { InterchainCalls } from './lib/InterchainCalls.sol'; // <= FOUND
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {
24:     
25:     mapping(string => mapping(address => bool)) public whitelistedCallers;
26: 
27:     
28:     mapping(string => mapping(address => bool)) public whitelistedSenders;
29: 
30:     constructor(address _gateway, address _owner) AxelarExecutable(_gateway) {
31:         _transferOwnership(_owner);
32:     }
33: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L7-L10

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol'; // <= FOUND
8: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
9: 
10: import { SafeTokenTransferFrom, SafeTokenTransfer } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: contract TokenManagerLockUnlock is TokenManagerAddressStorage {
19:     
20: 
21: 
22: 
23: 
24:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}
25: 
26:     function implementationType() external pure returns (uint256) {
27:         return 0;
28:     }
29: 
30:     
31: 
32: 
33: 
34:     function _setup(bytes calldata params) internal override {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L7-L11

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol'; // <= FOUND
8: 
9: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol'; // <= FOUND
10: 
11: import { TokenManagerProxy } from '../proxies/TokenManagerProxy.sol'; // <= FOUND
12: 
13: 
14: 
15: 
16: 
17: contract TokenManagerDeployer is ITokenManagerDeployer {
18:     Create3Deployer public immutable deployer;
19: 
20:     
21: 
22: 
23: 
24:     constructor(address deployer_) {
25:         if (deployer_ == address(0)) revert AddressZero();
26:         deployer = Create3Deployer(deployer_);
27:     }
28: 
29:     
30: 
31: 
32: 
33: 
34: 
35:     function deployTokenManager(

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L7-L10

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol'; // <= FOUND
8: import { TimeLock } from '../../gmp-sdk/util/TimeLock.sol'; // <= FOUND
9: import { IInterchainGovernance } from '../interfaces/IInterchainGovernance.sol'; // <= FOUND
10: import { Caller } from '../util/Caller.sol'; // <= FOUND
11: 
12: 
13: 
14: 
15: 
16: 
17: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance {
18:     enum GovernanceCommand {
19:         ScheduleTimeLockProposal,
20:         CancelTimeLockProposal
21:     }
22: 
23:     string public governanceChain;
24:     string public governanceAddress;
25:     bytes32 public immutable governanceChainHash;
26:     bytes32 public immutable governanceAddressHash;
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L7-L31

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { IAxelarGateway } from '../../gmp-sdk/interfaces/IAxelarGateway.sol'; // <= FOUND
8: import { IAxelarGasService } from '../../gmp-sdk/interfaces/IAxelarGasService.sol'; // <= FOUND
9: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol'; // <= FOUND
10: import { SafeTokenTransferFrom } from '../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND
11: import { IERC20 } from '../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
12: 
13: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol'; // <= FOUND
14: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol'; // <= FOUND
15: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol'; // <= FOUND
16: import { IRemoteAddressValidator } from '../interfaces/IRemoteAddressValidator.sol'; // <= FOUND
17: import { IInterchainTokenExpressExecutable } from '../interfaces/IInterchainTokenExpressExecutable.sol'; // <= FOUND
18: import { ITokenManager } from '../interfaces/ITokenManager.sol'; // <= FOUND
19: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol'; // <= FOUND
20: import { IERC20Named } from '../interfaces/IERC20Named.sol'; // <= FOUND
21: 
22: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol'; // <= FOUND
23: import { StringToBytes32, Bytes32ToString } from '../../gmp-sdk/util/Bytes32String.sol'; // <= FOUND
24: 
25: import { Upgradable } from '../../gmp-sdk/upgradable/Upgradable.sol'; // <= FOUND
26: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol'; // <= FOUND
27: 
28: import { ExpressCallHandler } from '../utils/ExpressCallHandler.sol'; // <= FOUND
29: import { Pausable } from '../utils/Pausable.sol'; // <= FOUND
30: import { Operatable } from '../utils/Operatable.sol'; // <= FOUND
31: import { Multicall } from '../utils/Multicall.sol'; // <= FOUND
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: contract InterchainTokenService is
40:     IInterchainTokenService,
41:     AxelarExecutable,
42:     Upgradable,
43:     Operatable,
44:     ExpressCallHandler,
45:     Pausable,
46:     Multicall
47: {
48:     using StringToBytes32 for string;
49:     using Bytes32ToString for bytes32;
50:     using AddressBytesUtils for bytes;
51:     using AddressBytesUtils for address;
52: 
53:     address internal immutable implementationLockUnlock;
54:     address internal immutable implementationMintBurn;
55:     address internal immutable implementationLiquidityPool;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L7-L17

3: 
4: 
5: pragma solidity ^0.8.9;
6: 
7: import { SafeTokenCall, SafeTokenTransfer, SafeTokenTransferFrom } from '../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND
8: import { IERC20 } from '../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
9: import { IAxelarGateway } from './interfaces/IAxelarGateway.sol'; // <= FOUND
10: import { IGovernable } from './interfaces/IGovernable.sol'; // <= FOUND
11: import { IAxelarAuth } from './interfaces/IAxelarAuth.sol'; // <= FOUND
12: import { IBurnableMintableCappedERC20 } from './interfaces/IBurnableMintableCappedERC20.sol'; // <= FOUND
13: import { ITokenDeployer } from './interfaces/ITokenDeployer.sol'; // <= FOUND
14: 
15: import { ECDSA } from './ECDSA.sol'; // <= FOUND
16: import { DepositHandler } from './DepositHandler.sol'; // <= FOUND
17: import { AdminMultisigBase } from './AdminMultisigBase.sol'; // <= FOUND
18: 
19: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase {
20:     using SafeTokenCall for IERC20;
21:     using SafeTokenTransfer for IERC20;
22:     using SafeTokenTransferFrom for IERC20;
23: 
24:     error InvalidImplementation();
25: 
26:     enum TokenType {
27:         InternalBurnable,
28:         InternalBurnableFrom,
29:         External
30:     }
31: 
32:     
33:     
34:     
35: 
36:     
37:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);
38: 
39:     
40:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909);
41: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L7-L11

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol'; // <= FOUND
8: import { IERC20BurnableMintable } from '../../interfaces/IERC20BurnableMintable.sol'; // <= FOUND
9: 
10: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
11: import { SafeTokenCall } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: contract TokenManagerMintBurn is TokenManagerAddressStorage {
20:     
21: 
22: 
23: 
24: 
25:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}
26: 
27:     function implementationType() external pure returns (uint256) {
28:         return 1;
29:     }
30: 
31:     
32: 
33: 
34: 
35:     function _setup(bytes calldata params) internal override {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L7-L14

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol'; // <= FOUND
8: 
9: import { InterchainToken } from '../interchain-token/InterchainToken.sol'; // <= FOUND
10: import { ERC20Permit } from '../token-implementations/ERC20Permit.sol'; // <= FOUND
11: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol'; // <= FOUND
12: import { ITokenManager } from '../interfaces/ITokenManager.sol'; // <= FOUND
13: import { Implementation } from '../utils/Implementation.sol'; // <= FOUND
14: import { Distributable } from '../utils/Distributable.sol'; // <= FOUND
15: 
16: 
17: 
18: 
19: 
20: 
21: abstract contract StandardizedToken is InterchainToken, ERC20Permit, Implementation, Distributable {
22:     using AddressBytesUtils for bytes;
23: 
24:     address public tokenManager;
25:     string public name;
26:     string public symbol;
27:     uint8 public decimals;
28: 
29:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token');
30: 
31:     
32: 
33: 
34:     function contractId() external pure returns (bytes32) {
35:         return CONTRACT_ID;
36:     }
37: 
38:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L7-L9

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { TokenManager } from '../TokenManager.sol'; // <= FOUND
8: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
9: import { IAxelarGateway } from '../../../gmp-sdk/interfaces/IAxelarGateway.sol'; // <= FOUND
10: 
11: 
12: 
13: 
14: 
15: 
16: abstract contract TokenManagerAddressStorage is TokenManager {
17:     
18: 
19: 
20: 
21:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {}
22: 
23:     
24:     uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba;
25: 
26:     
27: 
28: 
29: 
30:     function tokenAddress() public view override returns (address tokenAddress_) {
31:         assembly {
32:             tokenAddress_ := sload(TOKEN_ADDRESS_SLOT)
33:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L7-L10

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol'; // <= FOUND
8: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND
9: 
10: import { SafeTokenTransferFrom } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: contract TokenManagerLiquidityPool is TokenManagerAddressStorage {
20:     
21:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807;
22: 
23:     
24: 
25: 
26: 
27: 
28:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}
29: 
30:     function implementationType() external pure returns (uint256) {
31:         return 2;
32:     }
33: 
34:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L7-L9

3: 
4: 
5: pragma solidity ^0.8.0;
6: 
7: import { FixedProxy } from '../../gmp-sdk/upgradable/FixedProxy.sol'; // <= FOUND
8: import { IStandardizedToken } from '../interfaces/IStandardizedToken.sol'; // <= FOUND
9: import { IStandardizedTokenProxy } from '../interfaces/IStandardizedTokenProxy.sol'; // <= FOUND
10: 
11: 
12: 
13: 
14: 
15: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy {
16:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token');
17: 
18:     
19: 
20: 
21: 
22: 
23:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) {
24:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();
25: 
26:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
27:         if (!success) revert SetupFailed();
28:     }
29: 
30:     
31: 
32: 
33:     function contractId() external pure returns (bytes32) {

[NC-21] Upgradable contract contractors should have the initialize modifier

Number of instances found

2

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L83-L83

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: {
46:     using StringToBytes32 for string;
47:     using Bytes32ToString for bytes32;
48:     using AddressBytesUtils for bytes;
49:     using AddressBytesUtils for address;
50: 
51:     address internal immutable implementationLockUnlock;
52:     address internal immutable implementationMintBurn;
53:     address internal immutable implementationLiquidityPool;
54:     IAxelarGasService public immutable gasService;
55:     IRemoteAddressValidator public immutable remoteAddressValidator;
56:     address public immutable tokenManagerDeployer;
57:     address public immutable standardizedTokenDeployer;
58:     Create3Deployer internal immutable deployer;
59:     bytes32 internal immutable chainNameHash;
60:     bytes32 internal immutable chainName;
61: 
62:     bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id');
63:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id');
64:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt');
65: 
66:     uint256 private constant SELECTOR_SEND_TOKEN = 1;
67:     uint256 private constant SELECTOR_SEND_TOKEN_WITH_DATA = 2;
68:     uint256 private constant SELECTOR_DEPLOY_TOKEN_MANAGER = 3;
69:     uint256 private constant SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN = 4;
70: 
71:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
72: 
73:     
74: 
75: 
76: 
77: 
78: 
79: 
80: 
81: 
82: 
83:     constructor( // <= FOUND
84:         address tokenManagerDeployer_,
85:         address standardizedTokenDeployer_,
86:         address gateway_,
87:         address gasService_,
88:         address remoteAddressValidator_,
89:         address[] memory tokenManagerImplementations,
90:         string memory chainName_
91:     ) AxelarExecutable(gateway_) {
92:         if (
93:             remoteAddressValidator_ == address(0) ||
94:             gasService_ == address(0) ||
95:             tokenManagerDeployer_ == address(0) ||
96:             standardizedTokenDeployer_ == address(0)
97:         ) revert ZeroAddress();
98:         remoteAddressValidator = IRemoteAddressValidator(remoteAddressValidator_);
99:         gasService = IAxelarGasService(gasService_);
100:         tokenManagerDeployer = tokenManagerDeployer_;
101:         standardizedTokenDeployer = standardizedTokenDeployer_;
102:         deployer = ITokenManagerDeployer(tokenManagerDeployer_).deployer();
103: 
104:         if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();
105: 
106:         implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK);
107:         implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L27-L27

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
13:     using AddressToString for address;
14: 
15:     mapping(string => bytes32) public remoteAddressHashes;
16:     mapping(string => string) public remoteAddresses;
17:     address public immutable interchainTokenServiceAddress;
18:     bytes32 public immutable interchainTokenServiceAddressHash;
19:     mapping(string => bool) public supportedByGateway;
20: 
21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
22: 
23:     
24: 
25: 
26: 
27:     constructor(address _interchainTokenServiceAddress) { // <= FOUND
28:         if (_interchainTokenServiceAddress == address(0)) revert ZeroAddress();
29:         interchainTokenServiceAddress = _interchainTokenServiceAddress;
30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString())));
31:     }
32: 
33:     
34: 
35: 
36:     function contractId() external pure returns (bytes32) {
37:         return CONTRACT_ID;
38:     }
39: 
40:     function _setup(bytes calldata params) internal override {
41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));
42:         uint256 length = trustedChainNames.length;
43:         if (length != trustedAddresses.length) revert LengthMismatch();
44:         for (uint256 i; i < length; ++i) {
45:             addTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
46:         }
47:     }
48: 
49:     
50: 
51: 

[NC-22] A function which defines named returns in it's declaration doesn't need to use return

Number of instances found

4

Resolution

Remove the return statement once ensuring it is safe to do so

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L227-L231

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) {
224:         
225:         
226:         if (TokenManagerType(tokenManagerType) == TokenManagerType.LOCK_UNLOCK) {
227:             return implementationLockUnlock; // <= FOUND
228:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.MINT_BURN) {
229:             return implementationMintBurn; // <= FOUND
230:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.LIQUIDITY_POOL) {
231:             return implementationLiquidityPool; // <= FOUND
232:         }
233:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L828-L828

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt) {
828:         return keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_SALT, tokenId)); // <= FOUND
829:     }

[NC-23] Constant state variables defined more than once

Number of instances found

8

Resolution

Rather than redefining state variable constant, consider utilising a library to store all constants as this will prevent data redundancy

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L71-L71

71: bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

12: bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L27-L27

27: bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L14-L14

14: bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L16-L16

16: bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L22-L22

22: uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L15-L15

15: address internal immutable implementationAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L13-L13

13: address private immutable implementationAddress; // <= FOUND

[NC-24] Multiple mappings can be replaced with a single struct mapping

Number of instances found

6

Resolution

Using a single struct mapping in place of multiple defined mappings in a Solidity contract can lead to improved code organization, better readability, and easier maintainability. By consolidating related data into a single struct, developers can create a more cohesive data structure that logically groups together relevant pieces of information, thus reducing redundancy and clutter. This approach simplifies the codebase, making it easier to understand, navigate, and modify. Additionally, it can result in more efficient gas usage when accessing or updating multiple related data points simultaneously.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L20-L20

12: contract MultisigBase is IMultisigBase {
13: 
14: 
15: 
16: 
17:     Signers public signers;
18:     uint256 public signerEpoch;
19:     
20:     mapping(uint256 => mapping(bytes32 => Voting)) public votingPerTopic; // <= FOUND
21: 
22:     
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30:     
31: 
32: 
33: 
34: 
35: 
36: 
37:     
38: 
39: 
40: 
41:     
42: 
43: 
44: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L24-L27

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {
23:     
24:     mapping(string => mapping(address => bool)) public whitelistedCallers; // <= FOUND
25: 
26:     
27:     mapping(string => mapping(address => bool)) public whitelistedSenders; // <= FOUND
28: 
29: 
30: 
31:     
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41:     
42: 
43: 
44: 
45: 
46: 
47:     
48: 
49: 
50: 
51: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L15-L19

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
13:     using AddressToString for address;
14: 
15:     mapping(string => bytes32) public remoteAddressHashes; // <= FOUND
16:     mapping(string => string) public remoteAddresses; // <= FOUND
17:     address public immutable interchainTokenServiceAddress;
18:     bytes32 public immutable interchainTokenServiceAddressHash;
19:     mapping(string => bool) public supportedByGateway; // <= FOUND
20: 
21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
22: 
23:     
24: 
25: 
26: 
27: 
28: 
29:     
30: 
31: 
32: 
33: 
34: 
35: 
36:     
37: 
38: 
39: 
40: 
41: 
42: 
43:     

[NC-25] Using abi.encodePacked can result in hash collision when used in hashing functions

Number of instances found

21

Resolution

Consider using abi.encode as this pads data to 32 byte segments

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L68-L73

68:     function executeProposal(
69:         address target,
70:         bytes calldata callData,
71:         uint256 nativeValue
72:     ) external payable {
73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
74: 
75:         _finalizeTimeLock(proposalHash);
76:         _call(target, callData, nativeValue);
77: 
78:         emit ProposalExecuted(proposalHash, target, callData, nativeValue, block.timestamp);
79:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L143-L148

143:     function _getProposalHash(
144:         address target,
145:         bytes memory callData,
146:         uint256 nativeValue
147:     ) internal pure returns (bytes32) {
148:         return keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L53

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners {
53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
54: 
55:         if (!multisigApprovals[proposalHash]) revert NotApproved();
56: 
57:         multisigApprovals[proposalHash] = false;
58: 
59:         _call(target, callData, nativeValue);
60: 
61:         emit MultisigExecuted(proposalHash, target, callData, nativeValue);
62:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L84

72:     function _processCommand(
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override {
79:         if (commandId > uint256(type(ServiceGovernanceCommand).max)) {
80:             revert InvalidCommand();
81:         }
82: 
83:         ServiceGovernanceCommand command = ServiceGovernanceCommand(commandId);
84:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
85: 
86:         if (command == ServiceGovernanceCommand.ScheduleTimeLockProposal) {
87:             eta = _scheduleTimeLock(proposalHash, eta);
88: 
89:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);
90:             return;
91:         } else if (command == ServiceGovernanceCommand.CancelTimeLockProposal) {
92:             _cancelTimeLock(proposalHash);
93: 
94:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
95:             return;
96:         } else if (command == ServiceGovernanceCommand.ApproveMultisigProposal) {
97:             multisigApprovals[proposalHash] = true;
98: 
99:             emit MultisigApproved(proposalHash, target, callData, nativeValue);
100:             return;
101:         } else if (command == ServiceGovernanceCommand.CancelMultisigApproval) {
102:             multisigApprovals[proposalHash] = false;
103: 
104:             emit MultisigCancelled(proposalHash, target, callData, nativeValue);
105:             return;
106:         }
107:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L92-L93

92:     function _getTimeLockEta(bytes32 hash) internal view returns (uint256 eta) {
93:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash)); // <= FOUND
94: 
95:         assembly {
96:             eta := sload(key)
97:         }
98:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L103-L104

103:     function _setTimeLockEta(bytes32 hash, uint256 eta) private {
104:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash)); // <= FOUND
105: 
106:         assembly {
107:             sstore(key, eta)
108:         }
109:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L349

322:     function execute(bytes calldata input) external override {
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data)); // <= FOUND
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i])); // <= FOUND
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (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#L384-L395

384:     function deployToken(bytes calldata params, bytes32) external onlySelf {
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol);
392: 
393:         if (tokenAddress == address(0)) {
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol)); // <= FOUND
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt)
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol);
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom);
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);
409: 
410:             
411:             _setTokenType(symbol, TokenType.External);
412:         }
413: 
414:         _setTokenAddress(symbol, tokenAddress);
415:         _setTokenMintLimit(symbol, mintLimit);
416: 
417:         emit TokenDeployed(symbol, tokenAddress);
418:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L426-L434

426:     function burnToken(bytes calldata params, bytes32) external onlySelf {
427:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));
428: 
429:         address tokenAddress = tokenAddresses(symbol);
430: 
431:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
432: 
433:         if (_getTokenType(symbol) == TokenType.External) {
434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode))); // <= FOUND
435: 
436:             if (_hasCode(depositHandlerAddress)) return;
437: 
438:             DepositHandler depositHandler = new DepositHandler{ salt: salt }();
439: 
440:             (bool success, bytes memory returnData) = depositHandler.execute(
441:                 tokenAddress,
442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler)))
443:             );
444: 
445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
446: 
447:             
448:             depositHandler.destroy(address(this));
449:         } else {
450:             IBurnableMintableCappedERC20(tokenAddress).burn(salt);
451:         }
452:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L555-L556

555:     function _getTokenMintLimitKey(string memory symbol) internal pure returns (bytes32) {
556:         return keccak256(abi.encodePacked(PREFIX_TOKEN_MINT_LIMIT, symbol)); // <= FOUND
557:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L564-L565

564:     function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) {
565:         return keccak256(abi.encodePacked(PREFIX_TOKEN_TYPE, symbol)); // <= FOUND
566:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L568-L569

568:     function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {
569:         return keccak256(abi.encodePacked(PREFIX_TOKEN_ADDRESS, symbol)); // <= FOUND
570:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L572-L573

572:     function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {
573:         return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId)); // <= FOUND
574:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L614-L615

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND
616:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L72

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) {
63:         bytes32 newSalt = keccak256(abi.encode(sender, salt)); // <= FOUND
64:         deployedAddress_ = address(
65:             uint160(
66:                 uint256(
67:                     keccak256( // <= FOUND
68:                         abi.encodePacked( // <= FOUND
69:                             hex'ff',
70:                             address(this),
71:                             newSalt,
72:                             keccak256(bytecode)  // <= FOUND
73:                         )
74:                     )
75:                 )
76:             )
77:         );
78:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L74

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND
73: 
74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND
75:     }

[NC-26] Constants should be on the left side of the

Number of instances found

11

Resolution

Putting constants on the left side of a comparison operator like == or < is a best practice known as "Yoda conditions", which can help prevent accidental assignment instead of comparison. In some programming languages, if a variable is mistakenly put on the left with a single = instead of ==, it assigns the constant's value to the variable without any compiler error. However, doing this with the constant on the left would generate an error, as constants cannot be assigned values. Although Solidity's static typing system prevents accidental assignments within conditionals, adopting this practice enhances code readability and consistency, especially when developers are working across multiple languages that support this convention.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L80-L80

80:         if (setupParams.length != 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L315-L315

315:         if (newOperatorsData.length != 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L57-L57

57:         if (params.length != 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L135-L135

135:         if (bytes(remoteAddress).length == 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L68-L68

68:         if (operatorBytes.length == 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L91-L91

91:         if (interchainCall.gas > 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L161-L161

161:         if (result.length > 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L60-L60

60:         if (params.length > 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L714-L714

714:         if (gasValue > 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L64-L64

64:             if (mintAmount > 0)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L511-L511

511:         if (metadata.length < 4)  // <= FOUND

[NC-27] Defined named returns not used within function

Number of instances found

30

Resolution

Such instances can be replaced with unnamed returns

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L92-L92

92:     function _getTimeLockEta(bytes32 hash) internal view returns (uint256 eta)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L22-L22

22:     function implementation() public view virtual returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L39-L39

39:     function implementation() public view returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L37-L37

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L44-L44

44:     function implementation() public view returns (address impl)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L202-L202

202:     function getCanonicalTokenId(address tokenAddress) public view returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L213-L213

213:     function getCustomTokenId(address sender, bytes32 salt) public pure returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L223-L223

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L275-L275

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L24-L24

24:     function getFlowLimit() public view returns (uint256 flowLimit)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L285-L285

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L63-L63

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L295-L295

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L75-L75

75:     function getFlowInAmount() external view returns (uint256 flowInAmount)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L309-L309

309:     function registerCanonicalToken(address tokenAddress) external payable notPaused returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L343-L347

343:     function deployCustomTokenManager( // <= FOUND
344:         bytes32 salt, // <= FOUND
345:         TokenManagerType tokenManagerType, // <= FOUND
346:         bytes memory params // <= FOUND
347:     ) public payable notPaused returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L365-L371

365:     function deployRemoteCustomTokenManager( // <= FOUND
366:         bytes32 salt, // <= FOUND
367:         string calldata destinationChain, // <= FOUND
368:         TokenManagerType tokenManagerType, // <= FOUND
369:         bytes calldata params, // <= FOUND
370:         uint256 gasValue // <= FOUND
371:     ) external payable notPaused returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L827-L827

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L204-L204

204:     function _getTokenId() internal view returns (bytes32 tokenId)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L57-L57

57:     function liquidityPool() public view returns (address liquidityPool_)  // <= FOUND

[NC-28] Both immutable and constant state variables should be CONSTANT_CASE

Number of instances found

19

Resolution

Make found instants CAPITAL_CASE

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L23-L23

23: bytes32 public immutable governanceChainHash; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L24-L24

24: bytes32 public immutable governanceAddressHash; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L15-L15

15: uint256 internal immutable _minimumTimeLockDelay; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L17-L17

17: address public immutable implementation; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L51-L51

51: address internal immutable implementationLockUnlock; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L52-L52

52: address internal immutable implementationMintBurn; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L53-L53

53: address internal immutable implementationLiquidityPool; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L56-L56

56: address public immutable tokenManagerDeployer; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L57-L57

57: address public immutable standardizedTokenDeployer; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L59-L59

59: bytes32 internal immutable chainNameHash; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L60-L60

60: bytes32 internal immutable chainName; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L15-L15

15: uint256 public immutable implementationType; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L17-L17

17: address public immutable interchainTokenServiceAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L18-L18

18: bytes32 public immutable interchainTokenServiceAddressHash; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L17-L17

17: address public immutable implementationMintBurnAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L18-L18

18: address public immutable implementationLockUnlockAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L15-L15

15: address internal immutable implementationAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L13-L13

13: address private immutable implementationAddress; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L16-L16

16: bytes32 public immutable tokenId; // <= FOUND

[NC-29] Consider using named mappings

Number of instances found

6

Resolution

In Solidity version 0.8.18 and beyond mapping parameters can be named. This makes the purpose and function of a given mapping far clearer which in turn improves readability.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L22-L22

22:     mapping(bytes32 => bool) public multisigApprovals; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L24-L24

24:     mapping(string => mapping(address => bool)) public whitelistedCallers; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L27-L27

27:     mapping(string => mapping(address => bool)) public whitelistedSenders; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L19-L19

19:     mapping(string => bool) public supportedByGateway; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L16-L16

16:     mapping(string => string) public remoteAddresses; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L15-L15

15:     mapping(string => bytes32) public remoteAddressHashes; // <= FOUND

[NC-30] Use a single file for system wide constants

Number of instances found

40

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L13-L13

12: contract TimeLock is ITimeLock {
13:     bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock'); // <= FOUND
14: 
15:     uint256 internal immutable _minimumTimeLockDelay;
16: 
17:     
18: 
19: 
20: 
21: 
22: 
23:     
24: 
25: 
26: 
27: 
28: 
29:     
30: 
31: 
32: 
33: 
34: 
35: 
36:     
37: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L35-L57

17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase {
18:     using SafeTokenCall for IERC20;
19:     using SafeTokenTransfer for IERC20;
20:     using SafeTokenTransferFrom for IERC20;
21: 
22:     error InvalidImplementation();
23: 
24:     enum TokenType {
25:         InternalBurnable,
26:         InternalBurnableFrom,
27:         External
28:     }
29: 
30:     
31:     
32:     
33: 
34:     
35:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); // <= FOUND
36: 
37:     
38:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909); // <= FOUND
39: 
40:     
41:     bytes32 internal constant KEY_MINT_LIMITER = bytes32(0x627f0c11732837b3240a2de89c0b6343512886dd50978b99c76a68c6416a4d92); // <= FOUND
42: 
43:     
44:     bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); // <= FOUND
45:     bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); // <= FOUND
46:     bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); // <= FOUND
47:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); // <= FOUND
48:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND
49:     bytes32 internal constant PREFIX_TOKEN_MINT_LIMIT = keccak256('token-mint-limit'); // <= FOUND
50:     bytes32 internal constant PREFIX_TOKEN_MINT_AMOUNT = keccak256('token-mint-amount'); // <= FOUND
51: 
52:     bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken'); // <= FOUND
53:     bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); // <= FOUND
54:     bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); // <= FOUND
55:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); // <= FOUND
56:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND
57:     bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship'); // <= FOUND
58: 
59:     
60:     address internal immutable AUTH_MODULE;
61:     
62:     address internal immutable TOKEN_DEPLOYER_IMPLEMENTATION;
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70:     
71: 
72: 
73: 
74:     
75: 
76: 
77: 
78: 
79: 
80: 
81: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L18-L18

17: contract FinalProxy is Proxy, IFinalProxy {
18:     bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation'); // <= FOUND
19: 
20:     
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34: 
35:     
36: 
37: 
38: 
39: 
40: 
41:     
42: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L62-L71

37: contract InterchainTokenService is
38:     IInterchainTokenService,
39:     AxelarExecutable,
40:     Upgradable,
41:     Operatable,
42:     ExpressCallHandler,
43:     Pausable,
44:     Multicall
45: {
46:     using StringToBytes32 for string;
47:     using Bytes32ToString for bytes32;
48:     using AddressBytesUtils for bytes;
49:     using AddressBytesUtils for address;
50: 
51:     address internal immutable implementationLockUnlock;
52:     address internal immutable implementationMintBurn;
53:     address internal immutable implementationLiquidityPool;
54:     IAxelarGasService public immutable gasService;
55:     IRemoteAddressValidator public immutable remoteAddressValidator;
56:     address public immutable tokenManagerDeployer;
57:     address public immutable standardizedTokenDeployer;
58:     Create3Deployer internal immutable deployer;
59:     bytes32 internal immutable chainNameHash;
60:     bytes32 internal immutable chainName;
61: 
62:     bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id'); // <= FOUND
63:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id'); // <= FOUND
64:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt'); // <= FOUND
65: 
66:     uint256 private constant SELECTOR_SEND_TOKEN = 1; // <= FOUND
67:     uint256 private constant SELECTOR_SEND_TOKEN_WITH_DATA = 2; // <= FOUND
68:     uint256 private constant SELECTOR_DEPLOY_TOKEN_MANAGER = 3; // <= FOUND
69:     uint256 private constant SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN = 4; // <= FOUND
70: 
71:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND
72: 
73:     
74: 
75: 
76: 
77: 
78: 
79: 
80: 
81: 
82: 
83: 
84: 
85:     
86: 
87: 
88: 
89:     
90: 
91: 
92: 
93: 
94: 
95: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L12-L12

11: contract InterchainTokenServiceProxy is FinalProxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND
13: 
14:     
15: 
16: 
17: 
18: 
19: 
20: 
21:     
22: 
23: 
24: 
25: 
26: }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

11: contract RemoteAddressValidatorProxy is Proxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND
13: 
14:     
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22:     
23: 
24: 
25: 
26: 
27: }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L14-L14

13: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy {
14:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND
15: 
16:     
17: 
18: 
19: 
20: 
21: 
22: 
23:     
24: 
25: 
26: 
27: }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L21-L21

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
13:     using AddressToString for address;
14: 
15:     mapping(string => bytes32) public remoteAddressHashes;
16:     mapping(string => string) public remoteAddresses;
17:     address public immutable interchainTokenServiceAddress;
18:     bytes32 public immutable interchainTokenServiceAddressHash;
19:     mapping(string => bool) public supportedByGateway;
20: 
21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND
22: 
23:     
24: 
25: 
26: 
27: 
28: 
29:     
30: 
31: 
32: 
33: 
34: 
35: 
36:     
37: 
38: 
39: 
40: 
41: 
42: 
43:     
44: 
45: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L19-L19

17: contract TokenManagerLiquidityPool is TokenManagerAddressStorage {
18:     
19:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807; // <= FOUND
20: 
21:     
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30:     
31: 
32: 
33: 
34: 
35: 
36:     
37: 
38: 
39: 
40: 
41: 
42:     
43: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L15-L15

13: contract Distributable is IDistributable {
14:     
15:     uint256 internal constant DISTRIBUTOR_SLOT = 0x71c5a35e45a25c49e8f747acd4bcb869814b3d104c492d2554f4c46e12371f56; // <= FOUND
16: 
17:     
18: 
19: 
20: 
21: 
22:     
23: 
24: 
25: 
26: 
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34:     
35: 
36: 
37: 
38: 
39: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L14-L16

12: contract ExpressCallHandler is IExpressCallHandler {
13:     
14:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN = 0x67c7b41c1cb0375e36084c4ec399d005168e83425fa471b9224f6115af865619; // <= FOUND
15:     
16:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA = 0x3e607cc12a253b1d9f677a03d298ad869a90a8ba4bd0fb5739e7d79db7cdeaad; // <= FOUND
17: 
18:     
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L14-L18

12: contract FlowLimit is IFlowLimit {
13:     
14:     uint256 internal constant FLOW_LIMIT_SLOT = 0x201b7a0b7c19aaddc4ce9579b7df8d2db123805861bc7763627f13e04d8af42f; // <= FOUND
15:     uint256 internal constant PREFIX_FLOW_OUT_AMOUNT = uint256(keccak256('prefix-flow-out-amount')); // <= FOUND
16:     uint256 internal constant PREFIX_FLOW_IN_AMOUNT = uint256(keccak256('prefix-flow-in-amount')); // <= FOUND
17: 
18:     uint256 internal constant EPOCH_TIME = 6 hours; // <= FOUND
19: 
20:     
21: 
22: 
23: 
24: 
25: 
26:     
27: 
28: 
29: 
30: 
31: 
32:     
33: 
34: 
35: 
36: 
37: 
38: 
39:     
40: 
41: 
42: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L15-L15

13: contract Operatable is IOperatable {
14:     
15:     uint256 internal constant OPERATOR_SLOT = 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d7; // <= FOUND
16: 
17:     
18: 
19: 
20: 
21: 
22:     
23: 
24: 
25: 
26: 
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34:     
35: 
36: 
37: 
38: 
39: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L14-L14

12: contract Pausable is IPausable {
13:     
14:     uint256 internal constant PAUSE_SLOT = 0xee35723ac350a69d2a92d3703f17439cbaadf2f093a21ba5bf5f1a53eb2a14d8; // <= FOUND
15: 
16:     
17: 
18: 
19: 
20: 
21: 
22:     
23: 
24: 
25: 
26: 
27: 
28:     
29: 
30: 
31: 
32: 
33: 
34: 
35: }

[NC-31] Functions with unused parameters

Number of instances found

13

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L155-L155

155:     function _executeWithToken( // <= FOUND
156:         string calldata, 
157:         string calldata, 
158:         bytes calldata, 
159:         string calldata, 
160:         uint256 
161:     ) internal pure override {
162:         revert TokenNotSupported();
163:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L223-L223

223:     function admins(uint256) external pure override returns (address[] memory) { // <= FOUND
224:         return new address[](0);
225:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L208-L208

208:     function allTokensFrozen() external pure override returns (bool) { // <= FOUND
209:         return false;
210:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L237-L237

237:     function tokenFrozen(string memory) external pure override returns (bool) { // <= FOUND
238:         return false;
239:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L420-L420

420:     function mintToken(bytes calldata params, bytes32) external onlySelf { // <= FOUND
421:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));
422: 
423:         _mintToken(symbol, account, amount);
424:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L494-L494

494:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf { // <= FOUND
495:         IAxelarAuth(AUTH_MODULE).transferOperatorship(newOperatorsData);
496: 
497:         emit OperatorshipTransferred(newOperatorsData);
498:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L126-L126

126:     function _beforeProposalExecuted( // <= FOUND
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         bytes calldata payload
130:     ) internal virtual {
131:         
132:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L142-L142

142:     function _onProposalExecuted( // <= FOUND
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual {
148:         
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual { // <= FOUND
179:         
180:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L156-L156

156:     function _onTargetExecutionFailed( // <= FOUND
157:         InterchainCalls.Call memory, 
158:         bytes memory result
159:     ) internal virtual {
160:         
161:         if (result.length > 0) {
162:             
163:             assembly {
164:                 revert(add(32, result), mload(result))
165:             }
166:         } else {
167:             
168:             revert ProposalExecuteFailed();
169:         }
170:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L32-L32

32:     function setup(bytes calldata params) external {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual {} // <= FOUND

[NC-32] Default address(0) can be returned

Number of instances found

30

Resolution

Allowing a function in Solidity to return the default address (address(0)) can be problematic as it can represent uninitialized or invalid addresses. If such an address is utilized in transfer operations or other sensitive actions, it could lead to loss of funds or unpredicted behavior. It's prudent to include checks in your functions to prevent the return of the zero address, enhancing contract security.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L182-L182

182:     function authModule() public view override returns (address) {
183:         return AUTH_MODULE;
184:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L186-L186

186:     function governance() public view override returns (address) {
187:         return getAddress(KEY_GOVERNANCE);
188:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L190-L190

190:     function mintLimiter() public view override returns (address) {
191:         return getAddress(KEY_MINT_LIMITER);
192:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L194-L194

194:     function tokenDeployer() public view returns (address) {
195:         return TOKEN_DEPLOYER_IMPLEMENTATION;
196:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L227-L227

227:     function implementation() public view override returns (address) {
228:         return getAddress(KEY_IMPLEMENTATION);
229:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L231-L231

231:     function tokenAddresses(string memory symbol) public view override returns (address) {
232:         return getAddress(_getTokenAddressKey(symbol));
233:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L614-L614

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash)))));
616:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L24-L24

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {
25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L58

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) {
63:         bytes32 newSalt = keccak256(abi.encode(sender, salt));
64:         deployedAddress_ = address(
65:             uint160(
66:                 uint256(
67:                     keccak256(
68:                         abi.encodePacked(
69:                             hex'ff',
70:                             address(this),
71:                             newSalt,
72:                             keccak256(bytecode) 
73:                         )
74:                     )
75:                 )
76:             )
77:         );
78:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L29-L29

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {
30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));
31:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
32: 
33:         emit Deployed(keccak256(bytecode), salt, deployedAddress_);
34:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L67-L67

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) {
68:         bytes32 deploySalt = keccak256(abi.encode(sender, salt));
69:         return Create3.deployedAddress(address(this), deploySalt);
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L71

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH)))));
73: 
74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01')))));
75:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L22-L22

22:     function implementation() public view virtual returns (address implementation_) {
23:         assembly {
24:             implementation_ := sload(_IMPLEMENTATION_SLOT)
25:         }
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L39-L39

39:     function implementation() public view returns (address implementation_) {
40:         assembly {
41:             implementation_ := sload(_IMPLEMENTATION_SLOT)
42:         }
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L37-L37

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_) {
38:         implementation_ = _finalImplementation();
39:         if (implementation_ == address(0)) {
40:             implementation_ = super.implementation();
41:         }
42:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L57-L57

57:     function _finalImplementation() internal view virtual returns (address implementation_) {
58:         
59: 
60: 
61:         implementation_ = Create3.deployedAddress(address(this), FINAL_IMPLEMENTATION_SALT);
62: 
63:         if (implementation_.code.length == 0) implementation_ = address(0);
64:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L161-L161

161:     function getTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {
162:         tokenManagerAddress = deployer.deployedAddress(address(this), tokenId);
163:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L180-L180

180:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress) {
181:         address tokenManagerAddress = getValidTokenManagerAddress(tokenId);
182:         tokenAddress = ITokenManager(tokenManagerAddress).tokenAddress();
183:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L191-L191

191:     function getStandardizedTokenAddress(bytes32 tokenId) public view returns (address tokenAddress) {
192:         tokenId = _getStandardizedTokenSalt(tokenId);
193:         tokenAddress = deployer.deployedAddress(address(this), tokenId);
194:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L223-L223

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) {
224:         
225:         
226:         if (TokenManagerType(tokenManagerType) == TokenManagerType.LOCK_UNLOCK) {
227:             return implementationLockUnlock;
228:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.MINT_BURN) {
229:             return implementationMintBurn;
230:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.LIQUIDITY_POOL) {
231:             return implementationLiquidityPool;
232:         }
233:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L44-L44

44:     function implementation() public view returns (address impl) {
45:         impl = _getImplementation(interchainTokenServiceAddress, implementationType);
46:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L54-L54

54:     function _getImplementation(IInterchainTokenService interchainTokenServiceAddress_, uint256 implementationType_)
55:         internal
56:         view
57:         returns (address impl)
58:     {
59:         impl = interchainTokenServiceAddress_.getImplementation(implementationType_);
60:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L28-L28

28:     function tokenAddress() public view override returns (address tokenAddress_) {
29:         assembly {
30:             tokenAddress_ := sload(TOKEN_ADDRESS_SLOT)
31:         }
32:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L57-L57

57:     function liquidityPool() public view returns (address liquidityPool_) {
58:         assembly {
59:             liquidityPool_ := sload(LIQUIDITY_POOL_SLOT)
60:         }
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L29-L29

29:     function distributor() public view returns (address distr) {
30:         assembly {
31:             distr := sload(DISTRIBUTOR_SLOT)
32:         }
33:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L148-L148

148:     function getExpressReceiveToken(
149:         bytes32 tokenId,
150:         address destinationAddress,
151:         uint256 amount,
152:         bytes32 commandId
153:     ) public view returns (address expressCaller) {
154:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
155:         assembly {
156:             expressCaller := sload(slot)
157:         }
158:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L171-L171

171:     function getExpressReceiveTokenWithData(
172:         bytes32 tokenId,
173:         string memory sourceChain,
174:         bytes memory sourceAddress,
175:         address destinationAddress,
176:         uint256 amount,
177:         bytes calldata data,
178:         bytes32 commandId
179:     ) public view returns (address expressCaller) {
180:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
181:             tokenId,
182:             sourceChain,
183:             sourceAddress,
184:             destinationAddress,
185:             amount,
186:             data,
187:             commandId
188:         );
189:         assembly {
190:             expressCaller := sload(slot)
191:         }
192:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L202-L202

202:     function _popExpressReceiveToken(
203:         bytes32 tokenId,
204:         address destinationAddress,
205:         uint256 amount,
206:         bytes32 commandId
207:     ) internal returns (address expressCaller) {
208:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
209:         assembly {
210:             expressCaller := sload(slot)
211:         }
212:         if (expressCaller != address(0)) {
213:             assembly {
214:                 sstore(slot, 0)
215:             }
216:             emit ExpressExecutionFulfilled(tokenId, destinationAddress, amount, commandId, expressCaller);
217:         }
218:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L231-L231

231:     function _popExpressReceiveTokenWithData(
232:         bytes32 tokenId,
233:         string memory sourceChain,
234:         bytes memory sourceAddress,
235:         address destinationAddress,
236:         uint256 amount,
237:         bytes memory data,
238:         bytes32 commandId
239:     ) internal returns (address expressCaller) {
240:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
241:             tokenId,
242:             sourceChain,
243:             sourceAddress,
244:             destinationAddress,
245:             amount,
246:             data,
247:             commandId
248:         );
249:         assembly {
250:             expressCaller := sload(slot)
251:         }
252:         if (expressCaller != address(0)) {
253:             assembly {
254:                 sstore(slot, 0)
255:             }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L29-L29

29:     function operator() public view returns (address operator_) {
30:         assembly {
31:             operator_ := sload(OPERATOR_SLOT)
32:         }
33:     }

[NC-33] Critical functions should be a two step procedure

Number of instances found

33

Resolution

Critical functions in Solidity contracts should follow a two-step procedure to enhance security, minimize human error, and ensure proper access control. By dividing sensitive operations into distinct phases, such as initiation and confirmation, developers can introduce a safeguard against unintended actions or unauthorized access.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L265-L265

265:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external override  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L92

92:     function setWhitelistedProposalCaller( // <= FOUND
93:         string calldata sourceChain,
94:         address sourceCaller,
95:         bool whitelisted
96:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L107

107:     function setWhitelistedProposalSender( // <= FOUND
108:         string calldata sourceChain,
109:         address sourceSender,
110:         bool whitelisted
111:     ) external override onlyOwner 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L78-L78

78:     function setup(bytes calldata data) external override onlyProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L534-L534

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L547-L547

547:     function setPaused(bool paused) external onlyOwner  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L61-L61

61:     function setup(bytes calldata params) external override onlyProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L171-L171

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67-L67

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L51-L51

51:     function setDistributor(address distr) external onlyDistributor  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L103-L103

103:     function _setTimeLockEta(bytes32 hash, uint256 eta) private  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L626-L626

626:     function _setTokenMintLimit(string memory symbol, uint256 limit) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L632-L632

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L639-L639

639:     function _setTokenType(string memory symbol, TokenType tokenType) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L643-L643

643:     function _setTokenAddress(string memory symbol, address tokenAddress) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L647-L647

647:     function _setCommandExecuted(bytes32 commandId, bool executed) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved( // <= FOUND
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint( // <= FOUND
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L676-L676

676:     function _setImplementation(address newImplementation) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L40-L40

40:     function _setup(bytes calldata params) internal override  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L38-L38

38:     function _setTokenAddress(address tokenAddress_) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L47-L47

47:     function _setLiquidityPool(address liquidityPool_) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L39-L39

39:     function _setDistributor(address distributor_) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L79-L79

79:     function _setExpressReceiveToken( // <= FOUND
80:         bytes32 tokenId,
81:         address destinationAddress,
82:         uint256 amount,
83:         bytes32 commandId,
84:         address expressCaller
85:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L110-L110

110:     function _setExpressReceiveTokenWithData( // <= FOUND
111:         bytes32 tokenId,
112:         string memory sourceChain,
113:         bytes memory sourceAddress,
114:         address destinationAddress,
115:         uint256 amount,
116:         bytes calldata data,
117:         bytes32 commandId,
118:         address expressCaller
119:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L34-L34

34:     function _setFlowLimit(uint256 flowLimit) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L39-L39

39:     function _setOperator(address operator_) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L41-L41

41:     function _setPaused(bool paused) internal  // <= FOUND

[NC-34] Variables should be used in place of magic numbers to improve readability

Number of instances found

2

Resolution

Magic numbers should be avoided in Solidity code to enhance readability, maintainability, and reduce the likelihood of errors. Magic numbers are hard-coded values with no clear meaning or context, which can create confusion and make the code harder to understand for developers. Using well-defined constants or variables with descriptive names instead of magic numbers not only clarifies the purpose and significance of the value but also simplifies code updates and modifications.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L203-L203

202:     function tokenMintAmount(string memory symbol) public view override returns (uint256) {
203:         return getUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours)); // <= FOUND
204:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L636-L636

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {
633:         uint256 limit = tokenMintLimit(symbol);
634:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
635: 
636:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount); // <= FOUND
637:     }

[NC-35] Utility contracts can be made into libraries

Number of instances found

6

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L15-L15

15: contract Proxy is BaseProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L11-L11

11: contract InterchainTokenServiceProxy is FinalProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L11-L11

11: contract RemoteAddressValidatorProxy is Proxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L13-L13

13: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenLockUnlock.sol#L7-L7

7: contract StandardizedTokenLockUnlock is StandardizedToken  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L7-L7

7: contract StandardizedTokenMintBurn is StandardizedToken  // <= FOUND

[NC-36] Address values should be used through variables rather than used as literals

Number of instances found

4

Resolution

Assigning such addresses during construction is preferred as this allows flexibility when deploying to other EVM chains

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L504-L508

504:     function _hasCode(address addr) internal view returns (bool) { // <= FOUND
505:         bytes32 codehash = addr.codehash;
506: 
507:         
508:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // <= FOUND
509:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L614-L615

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) { // <= FOUND
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND
616:     }

[NC-37] Use immutable not constant for keccak state variables

Number of instances found

21

Resolution

It's crucial to leverage the right features for the appropriate contexts in Solidity, despite the compiler's ability to correct common developer mistakes. Both constant and immutable variables have distinct uses. Constant variables are best suited for hard-coded, literal values within your contract, where the value doesn't need to be computed or modified.

On the other hand, immutable variables are ideal for situations where the value might be the result of an expression or received from a constructor. While both serve to define unchanging variables, they function differently and their proper utilization contributes to clearer, more efficient code. Remember, even if the compiler can correct certain mistakes, best practices dictate using the correct feature for the task at hand.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L13-L13

13: bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L44-L44

44: bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L45-L45

45: bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L46-L46

46: bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L47-L47

47: bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L48-L48

48: bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L49-L49

49: bytes32 internal constant PREFIX_TOKEN_MINT_LIMIT = keccak256('token-mint-limit'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L50-L50

50: bytes32 internal constant PREFIX_TOKEN_MINT_AMOUNT = keccak256('token-mint-amount'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L52-L52

52: bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L53-L53

53: bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L54-L54

54: bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L55-L55

55: bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L56-L56

56: bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L57-L57

57: bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L18-L18

18: bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L62-L62

62: bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L63-L63

63: bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L64-L64

64: bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L71-L71

71: bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

12: bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L27-L27

27: bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND

[NC-38] Unused errors present

Number of instances found

1

Resolution

If these serve no purpose, they should be safely removed

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L13-L13

13: error MulticallFailed(bytes err); // <= FOUND

[NC-39] Consider adding emergency-stop functionality

Number of instances found

35

Resolution

In the event of a security breach or any unforeseen emergency, swiftly suspending all protocol operations becomes crucial. Having a mechanism in place to halt all functions collectively, instead of pausing individual contracts separately, substantially enhances the efficiency of mitigating ongoing attacks or vulnerabilities. This not only quickens the response time to potential threats but also reduces operational stress during these critical periods. Therefore, consider integrating a 'circuit breaker' or 'emergency stop' function into the smart contract system architecture. Such a feature would provide the capability to suspend the entire protocol instantly, which could prove invaluable during a time-sensitive crisis management situation.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L15-L15

15: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L14-L14

14: contract AxelarServiceGovernance is InterchainGovernance, MultisigBase, IAxelarServiceGovernance 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L12-L12

12: contract MultisigBase is IMultisigBase 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L13-L13

13: contract Multisig is Caller, MultisigBase, IMultisig 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L12-L12

12: contract TimeLock is ITimeLock 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L7-L7

7: contract Caller is ICaller 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L17-L17

17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L38-L38

38: contract InterchainProposalSender is IInterchainProposalSender 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L22-L22

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L5-L5

5: contract ConstAddressDeployer 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L12-L12

12: contract Create3Deployer 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L16-L16

16: contract CreateDeployer 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L15-L15

15: contract Proxy is BaseProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L16-L16

16: contract InitProxy is BaseProxy, IInitProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L17-L17

17: contract FinalProxy is Proxy, IFinalProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L12-L12

12: contract FixedProxy is IProxy 
contract InterchainTokenService is IInterchainTokenService, AxelarExecutable, Upgradable, Operatable, ExpressCallHandler, Pausable, Multicall 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L11-L11

11: contract InterchainTokenServiceProxy is FinalProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L11-L11

11: contract RemoteAddressValidatorProxy is Proxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L13-L13

13: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L13-L13

13: contract TokenManagerProxy is ITokenManagerProxy 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L12-L12

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenLockUnlock.sol#L7-L7

7: contract StandardizedTokenLockUnlock is StandardizedToken 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L7-L7

7: contract StandardizedTokenMintBurn is StandardizedToken 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L16-L16

16: contract TokenManagerLockUnlock is TokenManagerAddressStorage 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L17-L17

17: contract TokenManagerMintBurn is TokenManagerAddressStorage 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L17-L17

17: contract TokenManagerLiquidityPool is TokenManagerAddressStorage 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L13-L13

13: contract Distributable is IDistributable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L12-L12

12: contract ExpressCallHandler is IExpressCallHandler 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L12-L12

12: contract FlowLimit is IFlowLimit 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L12-L12

12: contract Multicall is IMulticall 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L13-L13

13: contract Operatable is IOperatable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L12-L12

12: contract Pausable is IPausable 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L15-L15

15: contract StandardizedTokenDeployer is IStandardizedTokenDeployer 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L15-L15

15: contract TokenManagerDeployer is ITokenManagerDeployer 

[NC-40] Employ Explicit Casting to Bytes or Bytes32 for Enhanced Code Clarity and Meaning

Number of instances found

18

Resolution

Smart contracts are complex entities, and clarity in their operations is fundamental to ensure that they function as intended. Casting a single argument instead of utilizing 'abi.encodePacked()' improves the transparency of the operation. It elucidates the intent of the code, reducing ambiguity and making it easier for auditors and developers to understand the code’s purpose. Such practices promote readability and maintainability, thus reducing the likelihood of errors and misunderstandings. Therefore, it's recommended to employ explicit casts for single arguments where possible, to increase the contract's comprehensibility and ensure a smoother review process.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L73-L73

73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L148-L148

148:         return keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L93-L93

93:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L349-L349

349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i])); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L395-L395

395:             bytes32 salt = keccak256(abi.encodePacked(symbol)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L434-L434

434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L556-L556

556:         return keccak256(abi.encodePacked(PREFIX_TOKEN_MINT_LIMIT, symbol)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L565-L565

565:         return keccak256(abi.encodePacked(PREFIX_TOKEN_TYPE, symbol)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L569-L569

569:         return keccak256(abi.encodePacked(PREFIX_TOKEN_ADDRESS, symbol)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L573-L573

573:         return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L68-L68

68:                         abi.encodePacked( // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L72

72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L74-L74

74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L23-L23

23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {} // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L125-L125

125:             abi.encodePacked(version, data) // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L63-L63

63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L39-L39

39:         bytes memory bytecode = abi.encodePacked(type(TokenManagerProxy).creationCode, args); // <= FOUND

[NC-41] Custom error has no error details

Number of instances found

4

Resolution

In Solidity, the use of custom error messages provides a valuable method of conveying meaningful information about failures during execution. In the current implementation, the custom errors lack specifics, making it challenging to understand the root cause of a failure. It's advisable to incorporate parameters into your error messages to indicate which user action or specific value caused the exception. This not only enhances error transparency but also aids debugging and fosters a more robust and maintainable codebase. Providing such precise error context greatly helps developers identify and resolve issues faster.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IUpgradable.sol#L10-L10

10: error InvalidImplementation(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L8-L8

8: error EmptyBytecode(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L7-L7

7: error FailedDeploy(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L8-L8

8: error FailedInit(); // <= FOUND

[NC-42] Strings should use double quotes rather than single quotes

Number of instances found

138

Resolution

Change found instances to use double quotes

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L6-L6

6: import { IAxelarExecutable } from '../../gmp-sdk/interfaces/IAxelarExecutable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IMultisig.sol#L6-L6

6: import { ICaller } from './ICaller.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L5-L5

5: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L6-L6

6: import { TimeLock } from '../../gmp-sdk/util/TimeLock.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L7-L7

7: import { IInterchainGovernance } from '../interfaces/IInterchainGovernance.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L7-L7

7: import { Caller } from '../util/Caller.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IAxelarServiceGovernance.sol#L5-L5

5: import { IInterchainGovernance } from './IInterchainGovernance.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IMultisig.sol#L5-L5

5: import { IMultisigBase } from './IMultisigBase.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L5-L5

5: import { IAxelarServiceGovernance } from '../interfaces/IAxelarServiceGovernance.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L6-L6

6: import { InterchainGovernance } from './InterchainGovernance.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L6-L6

6: import { MultisigBase } from '../auth/MultisigBase.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L5-L5

5: import { IMultisigBase } from '../interfaces/IMultisigBase.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L5-L5

5: import { IMultisig } from '../interfaces/IMultisig.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L5-L5

5: import { ITimeLock } from '../interfaces/ITimeLock.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L13-L13

13:     bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L5-L5

5: import { ICaller } from '../interfaces/ICaller.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L5-L5

5: import { SafeTokenCall, SafeTokenTransfer, SafeTokenTransferFrom } from '../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L6-L6

6: import { IERC20 } from '../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L7-L7

7: import { IAxelarGateway } from './interfaces/IAxelarGateway.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L8-L8

8: import { IGovernable } from './interfaces/IGovernable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L9-L9

9: import { IAxelarAuth } from './interfaces/IAxelarAuth.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L10-L10

10: import { IBurnableMintableCappedERC20 } from './interfaces/IBurnableMintableCappedERC20.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L11-L11

11: import { ITokenDeployer } from './interfaces/ITokenDeployer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L13-L13

13: import { ECDSA } from './ECDSA.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L14-L14

14: import { DepositHandler } from './DepositHandler.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L15-L15

15: import { AdminMultisigBase } from './AdminMultisigBase.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L44-L44

44:     bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L45-L45

45:     bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L46-L46

46:     bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L47-L47

47:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L48-L48

48:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L49-L49

49:     bytes32 internal constant PREFIX_TOKEN_MINT_LIMIT = keccak256('token-mint-limit'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L50-L50

50:     bytes32 internal constant PREFIX_TOKEN_MINT_AMOUNT = keccak256('token-mint-amount'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L52-L52

52:     bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L53-L53

53:     bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L54-L54

54:     bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L55-L55

55:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L56-L56

56:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L57-L57

57:     bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L246-L246

246:         return keccak256('axelar-gateway'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L5-L5

5: import { IAxelarGateway } from '../gmp-sdk/interfaces/IAxelarGateway.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L6-L6

6: import { IAxelarGasService } from '../gmp-sdk/interfaces/IAxelarGasService.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L7-L7

7: import { IInterchainProposalSender } from './interfaces/IInterchainProposalSender.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L8-L8

8: import { InterchainCalls } from './lib/InterchainCalls.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol#L5-L5

5: import { InterchainCalls } from '../lib/InterchainCalls.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L4-L4

4: import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L5-L5

5: import { StringToAddress } from '../gmp-sdk/util/AddressString.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L6-L6

6: import { AxelarExecutable } from '../gmp-sdk/executable/AxelarExecutable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L7-L7

7: import { IInterchainProposalExecutor } from './interfaces/IInterchainProposalExecutor.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L69-L69

69:                             hex'ff', // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L5-L5

5: import { Create3 } from './Create3.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L5-L5

5: import { ContractAddress } from '../util/ContractAddress.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L72

72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L74-L74

74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L5-L5

5: import { IProxy } from '../interfaces/IProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L5-L5

5: import { IUpgradable } from '../interfaces/IUpgradable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L8-L8

8: import { BaseProxy } from './BaseProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L6-L6

6: import { Ownable } from '../util/Ownable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IUpgradable.sol#L5-L5

5: import { IOwnable } from './IOwnable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L5-L5

5: import { IInitProxy } from '../interfaces/IInitProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IFinalProxy.sol#L5-L5

5: import { IProxy } from './IProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L6-L6

6: import { IFinalProxy } from '../interfaces/IFinalProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L7-L7

7: import { Create3 } from '../deploy/Create3.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L9-L9

9: import { Proxy } from './Proxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L18-L18

18:     bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L5-L5

5: import { IInterchainToken } from '../interfaces/IInterchainToken.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L5-L5

5: import { ITokenManager } from '../interfaces/ITokenManager.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L7-L7

7: import { ERC20 } from '../token-implementations/ERC20.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainToken.sol#L5-L5

5: import { IERC20 } from '../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L5-L5

5: import { IAxelarGateway } from '../../gmp-sdk/interfaces/IAxelarGateway.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L6-L6

6: import { IAxelarGasService } from '../../gmp-sdk/interfaces/IAxelarGasService.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L8-L8

8: import { SafeTokenTransferFrom } from '../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L6-L6

6: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L7-L7

7: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L7-L7

7: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L4-L4

4: import { IRemoteAddressValidator } from '../interfaces/IRemoteAddressValidator.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L15-L15

15: import { IInterchainTokenExpressExecutable } from '../interfaces/IInterchainTokenExpressExecutable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L7-L7

7: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L18-L18

18: import { IERC20Named } from '../interfaces/IERC20Named.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L11-L11

11: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L21-L21

21: import { StringToBytes32, Bytes32ToString } from '../../gmp-sdk/util/Bytes32String.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L6-L6

6: import { Upgradable } from '../../gmp-sdk/upgradable/Upgradable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L5-L5

5: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L26-L26

26: import { ExpressCallHandler } from '../utils/ExpressCallHandler.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L27-L27

27: import { Pausable } from '../utils/Pausable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L9-L9

9: import { Operatable } from '../utils/Operatable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L29-L29

29: import { Multicall } from '../utils/Multicall.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L62-L62

62:     bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L63-L63

63:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L64-L64

64:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L71-L71

71:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L334-L334

334:         _deployRemoteStandardizedToken(tokenId, tokenName, tokenSymbol, tokenDecimals, '', '', destinationChain, gasValue); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L8-L8

8: import { IExpressCallHandler } from './IExpressCallHandler.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L9-L9

9: import { ITokenManagerDeployer } from './ITokenManagerDeployer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManager.sol#L5-L5

5: import { ITokenManagerType } from './ITokenManagerType.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L11-L11

11: import { IPausable } from './IPausable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L12-L12

12: import { IMulticall } from './IMulticall.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L5-L5

5: import { FinalProxy } from '../../gmp-sdk/upgradable/FinalProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L5-L5

5: import { Proxy } from '../../gmp-sdk/upgradable/Proxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L5-L5

5: import { FixedProxy } from '../../gmp-sdk/upgradable/FixedProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L6-L6

6: import { IStandardizedToken } from '../interfaces/IStandardizedToken.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L7-L7

7: import { IStandardizedTokenProxy } from '../interfaces/IStandardizedTokenProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L27-L27

27:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L5-L5

5: import { AddressToString } from '../../gmp-sdk/util/AddressString.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L98-L98

98:         remoteAddresses[chain] = ''; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L5-L5

5: import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L7-L7

7: import { InterchainToken } from '../interchain-token/InterchainToken.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L8-L8

8: import { ERC20Permit } from '../token-implementations/ERC20Permit.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L12-L12

12: import { Implementation } from '../utils/Implementation.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L12-L12

12: import { Distributable } from '../utils/Distributable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L5-L5

5: import { StandardizedToken } from './StandardizedToken.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedToken.sol#L5-L5

5: import { IInterchainToken } from './IInterchainToken.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedToken.sol#L6-L6

6: import { IDistributable } from './IDistributable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedToken.sol#L7-L7

7: import { IERC20BurnableMintable } from './IERC20BurnableMintable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L10-L10

10: import { FlowLimit } from '../utils/FlowLimit.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L5-L5

5: import { TokenManager } from '../TokenManager.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L6-L6

6: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L7-L7

7: import { IAxelarGateway } from '../../../gmp-sdk/interfaces/IAxelarGateway.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L5-L5

5: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L8-L8

8: import { SafeTokenTransferFrom, SafeTokenTransfer } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L6-L6

6: import { IERC20BurnableMintable } from '../../interfaces/IERC20BurnableMintable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L9-L9

9: import { SafeTokenCall } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L8-L8

8: import { SafeTokenTransferFrom } from '../../../gmp-sdk/util/SafeTransfer.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManager.sol#L6-L6

6: import { IOperatable } from './IOperatable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManager.sol#L7-L7

7: import { IFlowLimit } from './IFlowLimit.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManager.sol#L8-L8

8: import { IImplementation } from './IImplementation.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L5-L5

5: import { IDistributable } from '../interfaces/IDistributable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L5-L5

5: import { IExpressCallHandler } from '../interfaces/IExpressCallHandler.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L5-L5

5: import { IFlowLimit } from '../interfaces/IFlowLimit.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L15-L15

15:     uint256 internal constant PREFIX_FLOW_OUT_AMOUNT = uint256(keccak256('prefix-flow-out-amount')); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L16-L16

16:     uint256 internal constant PREFIX_FLOW_IN_AMOUNT = uint256(keccak256('prefix-flow-in-amount')); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L5-L5

5: import { IImplementation } from '../interfaces/IImplementation.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L5-L5

5: import { IMulticall } from '../interfaces/IMulticall.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L5-L5

5: import { IOperatable } from '../interfaces/IOperatable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L5-L5

5: import { IPausable } from '../interfaces/IPausable.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L9-L9

9: import { StandardizedTokenProxy } from '../proxies/StandardizedTokenProxy.sol'; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L9-L9

9: import { TokenManagerProxy } from '../proxies/TokenManagerProxy.sol'; // <= FOUND

[NC-43] Large or complicated code bases should implement invariant tests

Number of instances found

1

Resolution

Reason: Contracts with large codebases, complex inline-assembly, intricate math, or multifaceted inter-contract interactions can harbor elusive bugs, even with full code coverage. These bugs can surface depending on the sequence of operations performed by the user.

Resolution: Implement invariant fuzzing tests using tools like Echidna. Define comprehensive invariants – conditions that must always hold true – and let the fuzzer generate various input and function call sequences to test them. This way, you can significantly mitigate the risks posed by unexplored operation orders and bolster the contract's robustness.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L322

322:     function execute(bytes calldata input) external override  // <= FOUND

[NC-44] Some if-statement can be converted to a ternary

Number of instances found

1

Resolution

Improving code readability and compactness is an integral part of optimal programming practices. The use of ternary operators in place of if-else conditions is one such measure. Ternary operators allow us to write conditional statements in a more concise manner, thereby enhancing readability and simplicity. They follow the syntax condition ? exprIfTrue : exprIfFalse, which interprets as "if the condition is true, evaluate to exprIfTrue, else evaluate to exprIfFalse". By adopting this approach, we make our code more streamlined and intuitive, which could potentially aid in better understanding and maintenance of the codebase.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L59-L61

59:         if (voteCount < signers.threshold) {
60:             
61:             voting.voteCount = voteCount; // <= FOUND
62:             return;
63:         }

[NC-45] File is missing NatSpec

Number of instances found

20

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Proxy } from '../../gmp-sdk/upgradable/Proxy.sol';
6: 
7: /**
8:  * @title RemoteAddressValidatorProxy
9:  * @dev Proxy contract for the RemoteAddressValidator contract. Inherits from the Proxy contract.
10:  */
11: contract RemoteAddressValidatorProxy is Proxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
13: 
14:     /**
15:      * @dev Constructs the RemoteAddressValidatorProxy contract.
16:      * @param implementationAddress Address of the RemoteAddressValidator implementation
17:      * @param owner Address of the owner of the proxy
18:      * @param params The params to be passed to the _setup function of the implementation.
19:      */
20:     constructor(
21:         address implementationAddress,
22:         address owner,
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title AddressBytesUtils
7:  * @dev This library provides utility functions to convert between `address` and `bytes`.
8:  */
9: library AddressBytesUtils {
10:     error InvalidBytesLength(bytes bytesAddress);
11: 
12:     /**
13:      * @dev Converts a bytes address to an address type.
14:      * @param bytesAddress The bytes representation of an address
15:      * @return addr The converted address
16:      */
17:     function toAddress(bytes memory bytesAddress) internal pure returns (address addr) {
18:         if (bytesAddress.length != 20) revert InvalidBytesLength(bytesAddress);
19: 
20:         assembly {
21:             addr := mload(add(bytesAddress, 20))
22:         }
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IImplementation.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IImplementation {
6:     error NotProxy();
7: }
8: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IFinalProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from './IProxy.sol';
6: 
7: // General interface for upgradable contracts
8: interface IFinalProxy is IProxy {
9:     function isFinal() external view returns (bool);
10: 
11:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) external returns (address);
12: }
13: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/ICaller.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface ICaller {
6:     error InsufficientBalance();
7:     error ExecutionFailed();
8: }
9: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { StandardizedToken } from './StandardizedToken.sol';
6: 
7: contract StandardizedTokenMintBurn is StandardizedToken {
8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
9:         return false;
10:     }
11: }
12: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IUpgradable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IOwnable } from './IOwnable.sol';
6: 
7: // General interface for upgradable contracts
8: interface IUpgradable is IOwnable {
9:     error InvalidCodeHash();
10:     error InvalidImplementation();
11:     error SetupFailed();
12:     error NotProxy();
13: 
14:     event Upgraded(address indexed newImplementation);
15: 
16:     function implementation() external view returns (address);
17: 
18:     function upgrade(
19:         address newImplementation,
20:         bytes32 newImplementationCodeHash,
21:         bytes calldata params
22:     ) external;
23: 
24:     function setup(bytes calldata data) external;
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: contract ConstAddressDeployer {
6:     error EmptyBytecode();
7:     error FailedDeploy();
8:     error FailedInit();
9: 
10:     event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);
11: 
12:     /**
13:      * @dev Deploys a contract using `CREATE2`. The address where the contract
14:      * will be deployed can be known in advance via {deployedAddress}.
15:      *
16:      * The bytecode for a contract can be obtained from Solidity with
17:      * `type(contractName).creationCode`.
18:      *
19:      * Requirements:
20:      *
21:      * - `bytecode` must not be empty.
22:      * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
23:      */
24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {
25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenLockUnlock.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { StandardizedToken } from './StandardizedToken.sol';
6: 
7: contract StandardizedTokenLockUnlock is StandardizedToken {
8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
9:         return true;
10:     }
11: }
12: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarGateway } from '../gmp-sdk/interfaces/IAxelarGateway.sol';
6: import { IAxelarGasService } from '../gmp-sdk/interfaces/IAxelarGasService.sol';
7: import { IInterchainProposalSender } from './interfaces/IInterchainProposalSender.sol';
8: import { InterchainCalls } from './lib/InterchainCalls.sol';
9: 
10: /**
11:  * @title InterchainProposalSender
12:  * @dev This contract is responsible for facilitating the execution of approved proposals across multiple chains.
13:  * It achieves this by working in conjunction with the AxelarGateway and AxelarGasService contracts.
14:  *
15:  * The contract allows for the sending of a single proposal to multiple destination chains. This is achieved
16:  * through the `sendProposals` function, which takes in arrays representing the destination chains,
17:  * destination contracts, fees, target contracts, amounts of tokens to send, function signatures, and encoded
18:  * function arguments.
19:  *
20:  * Each destination chain has a unique corresponding set of contracts to call, amounts of native tokens to send,
21:  * function signatures to call, and encoded function arguments. This information is provided in a 2D array where
22:  * the first dimension is the destination chain index, and the second dimension corresponds to the specific details
23:  * for each chain.
24:  *
25:  * In addition, the contract also allows for the execution of a single proposal at a single destination chain

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/lib/InterchainCalls.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: library InterchainCalls {
6:     /**
7:      * @dev An interchain call to be executed at the destination chain
8:      * @param destinationChain destination chain
9:      * @param destinationContract destination contract
10:      * @param gas The amount of native token to transfer to the target contract as gas payment for the interchain call
11:      * @param calls An array of calls to be executed at the destination chain
12:      */
13:     struct InterchainCall {
14:         string destinationChain;
15:         string destinationContract;
16:         uint256 gas;
17:         Call[] calls;
18:     }
19: 
20:     /**
21:      * @dev A call to be executed at the destination chain
22:      * @param target The address of the contract to call
23:      * @param value The amount of native token to transfer to the target contract
24:      * @param callData The data to pass to the target contract
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: pragma solidity ^0.8.0;
3: 
4: import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';
5: import { StringToAddress } from '../gmp-sdk/util/AddressString.sol';
6: import { AxelarExecutable } from '../gmp-sdk/executable/AxelarExecutable.sol';
7: import { IInterchainProposalExecutor } from './interfaces/IInterchainProposalExecutor.sol';
8: import { InterchainCalls } from './lib/InterchainCalls.sol';
9: 
10: /**
11:  * @title InterchainProposalExecutor
12:  * @dev This contract is intended to be the destination contract for `InterchainProposalSender` contract.
13:  * The proposal will be finally executed from this contract on the destination chain.
14:  *
15:  * The contract maintains whitelists for proposal senders and proposal callers. Proposal senders
16:  * are InterchainProposalSender contracts at the source chain and proposal callers are contracts
17:  * that call the InterchainProposalSender at the source chain.
18:  * For most governance system, the proposal caller should be the Timelock contract.
19:  *
20:  * This contract is abstract and some of its functions need to be implemented in a derived contract.
21:  */
22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {
23:     // Whitelisted proposal callers. The proposal caller is the contract that calls the `InterchainProposalSender` at the source chain.
24:     mapping(string => mapping(address => bool)) public whitelistedCallers;
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IInitProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from './IProxy.sol';
6: 
7: // General interface for upgradable contracts
8: interface IInitProxy is IProxy {
9:     function init(
10:         address implementationAddress,
11:         address newOwner,
12:         bytes memory params
13:     ) external;
14: }
15: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { InterchainCalls } from '../lib/InterchainCalls.sol';
6: 
7: interface IInterchainProposalSender {
8:     // An error emitted when the given gas is invalid
9:     error InvalidFee();
10: 
11:     /**
12:      * @dev Broadcast the proposal to be executed at multiple destination chains
13:      * @param calls An array of calls to be executed at the destination chain
14:      */
15:     function sendProposals(InterchainCalls.InterchainCall[] memory calls) external payable;
16: 
17:     /**
18:      * @dev Broadcast the proposal to be executed at single destination chain
19:      * @param destinationChain destination chain
20:      * @param destinationContract destination contract
21:      * @param calls An array of calls to be executed at the destination chain
22:      */
23:     function sendProposal(
24:         string calldata destinationChain,
25:         string calldata destinationContract,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.9;
4: 
5: import { SafeTokenCall, SafeTokenTransfer, SafeTokenTransferFrom } from '../gmp-sdk/util/SafeTransfer.sol';
6: import { IERC20 } from '../gmp-sdk/interfaces/IERC20.sol';
7: import { IAxelarGateway } from './interfaces/IAxelarGateway.sol';
8: import { IGovernable } from './interfaces/IGovernable.sol';
9: import { IAxelarAuth } from './interfaces/IAxelarAuth.sol';
10: import { IBurnableMintableCappedERC20 } from './interfaces/IBurnableMintableCappedERC20.sol';
11: import { ITokenDeployer } from './interfaces/ITokenDeployer.sol';
12: 
13: import { ECDSA } from './ECDSA.sol';
14: import { DepositHandler } from './DepositHandler.sol';
15: import { AdminMultisigBase } from './AdminMultisigBase.sol';
16: 
17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase {
18:     using SafeTokenCall for IERC20;
19:     using SafeTokenTransfer for IERC20;
20:     using SafeTokenTransferFrom for IERC20;
21: 
22:     error InvalidImplementation();
23: 
24:     enum TokenType {
25:         InternalBurnable,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';
6: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol';
7: 
8: /**
9:  * @title TokenManagerProxy
10:  * @dev This contract is a proxy for token manager contracts. It implements ITokenManagerProxy and
11:  * inherits from FixedProxy from the gmp sdk repo
12:  */
13: contract TokenManagerProxy is ITokenManagerProxy {
14:     IInterchainTokenService public immutable interchainTokenServiceAddress;
15:     uint256 public immutable implementationType;
16:     bytes32 public immutable tokenId;
17: 
18:     /**
19:      * @dev Constructs the TokenManagerProxy contract.
20:      * @param interchainTokenServiceAddress_ The address of the interchain token service
21:      * @param implementationType_ The token manager type
22:      * @param tokenId_ The identifier for the token
23:      * @param params The initialization parameters for the token manager contract
24:      */
25:     constructor(

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: // General interface for upgradable contracts
6: interface IProxy {
7:     error InvalidOwner();
8:     error InvalidImplementation();
9:     error SetupFailed();
10:     error NotOwner();
11:     error AlreadyInitialized();
12: 
13:     function implementation() external view returns (address implementation_);
14: 
15:     function setup(bytes calldata setupParams) external;
16: }
17: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ICaller } from '../interfaces/ICaller.sol';
6: 
7: contract Caller is ICaller {
8:     /**
9:      * @dev Calls a target address with specified calldata and optionally sends value.
10:      */
11:     function _call(
12:         address target,
13:         bytes calldata callData,
14:         uint256 nativeValue
15:     ) internal {
16:         if (nativeValue > address(this).balance) revert InsufficientBalance();
17: 
18:         (bool success, ) = target.call{ value: nativeValue }(callData);
19:         if (!success) {
20:             revert ExecutionFailed();
21:         }
22:     }
23: }
24: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from '../interfaces/IProxy.sol';
6: 
7: /**
8:  * @title BaseProxy Contract
9:  * @dev This abstract contract implements a basic proxy that stores an implementation address. Fallback function
10:  * calls are delegated to the implementation. This contract is meant to be inherited by other proxy contracts.
11:  */
12: abstract contract BaseProxy is IProxy {
13:     // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
15:     // keccak256('owner')
16:     bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
17: 
18:     /**
19:      * @dev Returns the current implementation address.
20:      * @return implementation_ The address of the current implementation contract
21:      */
22:     function implementation() public view virtual returns (address implementation_) {
23:         assembly {
24:             implementation_ := sload(_IMPLEMENTATION_SLOT)
25:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { FinalProxy } from '../../gmp-sdk/upgradable/FinalProxy.sol';
6: 
7: /**
8:  * @title InterchainTokenServiceProxy
9:  * @dev Proxy contract for interchain token service contracts. Inherits from the FinalProxy contract.
10:  */
11: contract InterchainTokenServiceProxy is FinalProxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
13: 
14:     /**
15:      * @dev Constructs the InterchainTokenServiceProxy contract.
16:      * @param implementationAddress Address of the interchain token service implementation
17:      * @param owner Address of the owner of the proxy
18:      */
19:     constructor(
20:         address implementationAddress,
21:         address owner,
22:         address operator
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}
24: 
25:     /**

[NC-46] Addresses shouldn't be hard-coded

Number of instances found

5

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L35-L35

35:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L38-L38

38:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L41-L41

41:     bytes32 internal constant KEY_MINT_LIMITER = bytes32(0x627f0c11732837b3240a2de89c0b6343512886dd50978b99c76a68c6416a4d92); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L508-L508

508:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND

[NC-47] Empty bytes check is missing

Number of instances found

99

Resolution

When developing smart contracts in Solidity, it's crucial to validate the inputs of your functions. This includes ensuring that the bytes parameters are not empty, especially when they represent crucial data such as addresses, identifiers, or raw data that the contract needs to process.

Missing empty bytes checks can lead to unexpected behaviour in your contract. For instance, certain operations might fail, produce incorrect results, or consume unnecessary gas when performed with empty bytes. Moreover, missing input validation can potentially expose your contract to malicious activity, including exploitation of unhandled edge cases.

To mitigate these issues, always validate that bytes parameters are not empty when the logic of your contract requires it.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L52-L52

52:     function getProposalEta(
53:         address target,
54:         bytes calldata callData,
55:         uint256 nativeValue
56:     ) external view returns (uint256) {
57:         return _getTimeLockEta(_getProposalHash(target, callData, nativeValue));
58:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L68-L68

68:     function executeProposal(
69:         address target,
70:         bytes calldata callData,
71:         uint256 nativeValue
72:     ) external payable {
73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
74: 
75:         _finalizeTimeLock(proposalHash);
76:         _call(target, callData, nativeValue);
77: 
78:         emit ProposalExecuted(proposalHash, target, callData, nativeValue, block.timestamp);
79:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L87-L87

87:     function _execute(
88:         string calldata sourceChain,
89:         string calldata sourceAddress,
90:         bytes calldata payload
91:     ) internal override {
92:         if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash)
93:             revert NotGovernance();
94: 
95:         (uint256 command, address target, bytes memory callData, uint256 nativeValue, uint256 eta) = abi.decode(
96:             payload,
97:             (uint256, address, bytes, uint256, uint256)
98:         );
99: 
100:         if (target == address(0)) revert InvalidTarget();
101: 
102:         _processCommand(command, target, callData, nativeValue, eta);
103:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L113-L113

113:     function _processCommand(
114:         uint256 commandId,
115:         address target,
116:         bytes memory callData,
117:         uint256 nativeValue,
118:         uint256 eta
119:     ) internal virtual {
120:         if (commandId > uint256(type(GovernanceCommand).max)) {
121:             revert InvalidCommand();
122:         }
123: 
124:         GovernanceCommand command = GovernanceCommand(commandId);
125:         bytes32 proposalHash = _getProposalHash(target, callData, nativeValue);
126: 
127:         if (command == GovernanceCommand.ScheduleTimeLockProposal) {
128:             eta = _scheduleTimeLock(proposalHash, eta);
129: 
130:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);
131:             return;
132:         } else if (command == GovernanceCommand.CancelTimeLockProposal) {
133:             _cancelTimeLock(proposalHash);
134: 
135:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
136:             return;
137:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L143-L143

143:     function _getProposalHash(
144:         address target,
145:         bytes memory callData,
146:         uint256 nativeValue
147:     ) internal pure returns (bytes32) {
148:         return keccak256(abi.encodePacked(target, callData, nativeValue));
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L155-L155

155:     function _executeWithToken(
156:         string calldata, 
157:         string calldata, 
158:         bytes calldata, 
159:         string calldata, 
160:         uint256 
161:     ) internal pure override {
162:         revert TokenNotSupported();
163:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L48

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners {
53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
54: 
55:         if (!multisigApprovals[proposalHash]) revert NotApproved();
56: 
57:         multisigApprovals[proposalHash] = false;
58: 
59:         _call(target, callData, nativeValue);
60: 
61:         emit MultisigExecuted(proposalHash, target, callData, nativeValue);
62:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L72

72:     function _processCommand(
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override {
79:         if (commandId > uint256(type(ServiceGovernanceCommand).max)) {
80:             revert InvalidCommand();
81:         }
82: 
83:         ServiceGovernanceCommand command = ServiceGovernanceCommand(commandId);
84:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
85: 
86:         if (command == ServiceGovernanceCommand.ScheduleTimeLockProposal) {
87:             eta = _scheduleTimeLock(proposalHash, eta);
88: 
89:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);
90:             return;
91:         } else if (command == ServiceGovernanceCommand.CancelTimeLockProposal) {
92:             _cancelTimeLock(proposalHash);
93: 
94:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
95:             return;
96:         } else if (command == ServiceGovernanceCommand.ApproveMultisigProposal) {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L111-L111

111:     function hasSignerVoted(address account, bytes32 topic) external view override returns (bool) {
112:         return votingPerTopic[signerEpoch][topic].hasVoted[account];
113:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L30-L30

30:     function execute(
31:         address target,
32:         bytes calldata callData,
33:         uint256 nativeValue
34:     ) external payable onlySigners {
35:         _call(target, callData, nativeValue);
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L38-L38

38:     function getTimeLock(bytes32 hash) external view override returns (uint256) {
39:         return _getTimeLockEta(hash);
40:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L50-L50

50:     function _scheduleTimeLock(bytes32 hash, uint256 eta) internal returns (uint256) {
51:         if (hash == 0) revert InvalidTimeLockHash();
52:         if (_getTimeLockEta(hash) != 0) revert TimeLockAlreadyScheduled();
53: 
54:         uint256 minimumEta = block.timestamp + _minimumTimeLockDelay;
55: 
56:         if (eta < minimumEta) eta = minimumEta;
57: 
58:         _setTimeLockEta(hash, eta);
59: 
60:         return eta;
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L67-L67

67:     function _cancelTimeLock(bytes32 hash) internal {
68:         if (hash == 0) revert InvalidTimeLockHash();
69: 
70:         _setTimeLockEta(hash, 0);
71:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L79-L79

79:     function _finalizeTimeLock(bytes32 hash) internal {
80:         uint256 eta = _getTimeLockEta(hash);
81: 
82:         if (hash == 0 || eta == 0) revert InvalidTimeLockHash();
83: 
84:         if (block.timestamp < eta) revert TimeLockNotReady();
85: 
86:         _setTimeLockEta(hash, 0);
87:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L92-L92

92:     function _getTimeLockEta(bytes32 hash) internal view returns (uint256 eta) {
93:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash));
94: 
95:         assembly {
96:             eta := sload(key)
97:         }
98:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L103-L103

103:     function _setTimeLockEta(bytes32 hash, uint256 eta) private {
104:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash));
105: 
106:         assembly {
107:             sstore(key, eta)
108:         }
109:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L11-L11

11:     function _call(
12:         address target,
13:         bytes calldata callData,
14:         uint256 nativeValue
15:     ) internal {
16:         if (nativeValue > address(this).balance) revert InsufficientBalance();
17: 
18:         (bool success, ) = target.call{ value: nativeValue }(callData);
19:         if (!success) {
20:             revert ExecutionFailed();
21:         }
22:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L106-L106

106:     function callContract(
107:         string calldata destinationChain,
108:         string calldata destinationContractAddress,
109:         bytes calldata payload
110:     ) external {
111:         emit ContractCall(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload);
112:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L114-L114

114:     function callContractWithToken(
115:         string calldata destinationChain,
116:         string calldata destinationContractAddress,
117:         bytes calldata payload,
118:         string calldata symbol,
119:         uint256 amount
120:     ) external {
121:         _burnTokenFrom(msg.sender, symbol, amount);
122:         emit ContractCallWithToken(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload, symbol, amount);
123:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L125-L125

125:     function isContractCallApproved(
126:         bytes32 commandId,
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         address contractAddress,
130:         bytes32 payloadHash
131:     ) external view override returns (bool) {
132:         return getBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash));
133:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L135-L135

135:     function isContractCallAndMintApproved(
136:         bytes32 commandId,
137:         string calldata sourceChain,
138:         string calldata sourceAddress,
139:         address contractAddress,
140:         bytes32 payloadHash,
141:         string calldata symbol,
142:         uint256 amount
143:     ) external view override returns (bool) {
144:         return
145:             getBool(
146:                 _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount)
147:             );
148:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L150-L150

150:     function validateContractCall(
151:         bytes32 commandId,
152:         string calldata sourceChain,
153:         string calldata sourceAddress,
154:         bytes32 payloadHash
155:     ) external override returns (bool valid) {
156:         bytes32 key = _getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash);
157:         valid = getBool(key);
158:         if (valid) _setBool(key, false);
159:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L161-L161

161:     function validateContractCallAndMint(
162:         bytes32 commandId,
163:         string calldata sourceChain,
164:         string calldata sourceAddress,
165:         bytes32 payloadHash,
166:         string calldata symbol,
167:         uint256 amount
168:     ) external override returns (bool valid) {
169:         bytes32 key = _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash, symbol, amount);
170:         valid = getBool(key);
171:         if (valid) {
172:             
173:             _setBool(key, false);
174:             _mintToken(symbol, msg.sender, amount);
175:         }
176:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L241-L241

241:     function isCommandExecuted(bytes32 commandId) public view override returns (bool) {
242:         return getBool(_getIsCommandExecutedKey(commandId));
243:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L420-L420

420:     function mintToken(bytes calldata params, bytes32) external onlySelf {
421:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));
422: 
423:         _mintToken(symbol, account, amount);
424:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L454-L454

454:     function approveContractCall(bytes calldata params, bytes32 commandId) external onlySelf {
455:         (
456:             string memory sourceChain,
457:             string memory sourceAddress,
458:             address contractAddress,
459:             bytes32 payloadHash,
460:             bytes32 sourceTxHash,
461:             uint256 sourceEventIndex
462:         ) = abi.decode(params, (string, string, address, bytes32, bytes32, uint256));
463: 
464:         _setContractCallApproved(commandId, sourceChain, sourceAddress, contractAddress, payloadHash);
465:         emit ContractCallApproved(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, sourceTxHash, sourceEventIndex);
466:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L468-L468

468:     function approveContractCallWithMint(bytes calldata params, bytes32 commandId) external onlySelf {
469:         (
470:             string memory sourceChain,
471:             string memory sourceAddress,
472:             address contractAddress,
473:             bytes32 payloadHash,
474:             string memory symbol,
475:             uint256 amount,
476:             bytes32 sourceTxHash,
477:             uint256 sourceEventIndex
478:         ) = abi.decode(params, (string, string, address, bytes32, string, uint256, bytes32, uint256));
479: 
480:         _setContractCallApprovedWithMint(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount);
481:         emit ContractCallApprovedWithMint(
482:             commandId,
483:             sourceChain,
484:             sourceAddress,
485:             contractAddress,
486:             payloadHash,
487:             symbol,
488:             amount,
489:             sourceTxHash,
490:             sourceEventIndex
491:         );
492:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L494-L494

494:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf {
495:         IAxelarAuth(AUTH_MODULE).transferOperatorship(newOperatorsData);
496: 
497:         emit OperatorshipTransferred(newOperatorsData);
498:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L572-L572

572:     function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {
573:         return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId));
574:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L576-L576

576:     function _getIsContractCallApprovedKey(
577:         bytes32 commandId,
578:         string memory sourceChain,
579:         string memory sourceAddress,
580:         address contractAddress,
581:         bytes32 payloadHash
582:     ) internal pure returns (bytes32) {
583:         return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash));
584:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L586-L586

586:     function _getIsContractCallApprovedWithMintKey(
587:         bytes32 commandId,
588:         string memory sourceChain,
589:         string memory sourceAddress,
590:         address contractAddress,
591:         bytes32 payloadHash,
592:         string memory symbol,
593:         uint256 amount
594:     ) internal pure returns (bytes32) {
595:         return
596:             keccak256(
597:                 abi.encode(
598:                     PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT,
599:                     commandId,
600:                     sourceChain,
601:                     sourceAddress,
602:                     contractAddress,
603:                     payloadHash,
604:                     symbol,
605:                     amount
606:                 )
607:             );
608:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L614-L614

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash)))));
616:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L647-L647

647:     function _setCommandExecuted(bytes32 commandId, bool executed) internal {
648:         _setBool(_getIsCommandExecutedKey(commandId), executed);
649:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved(
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal {
658:         _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true);
659:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint(
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal {
670:         _setBool(
671:             _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount),
672:             true
673:         );
674:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L41-L41

41:     function _execute(
42:         string calldata sourceChain,
43:         string calldata sourceAddress,
44:         bytes calldata payload
45:     ) internal override {
46:         _beforeProposalExecuted(sourceChain, sourceAddress, payload);
47: 
48:         
49:         if (!whitelistedSenders[sourceChain][StringToAddress.toAddress(sourceAddress)]) {
50:             revert NotWhitelistedSourceAddress();
51:         }
52: 
53:         
54:         (address interchainProposalCaller, InterchainCalls.Call[] memory calls) = abi.decode(payload, (address, InterchainCalls.Call[]));
55: 
56:         
57:         if (!whitelistedCallers[sourceChain][interchainProposalCaller]) {
58:             revert NotWhitelistedCaller();
59:         }
60: 
61:         
62:         _executeProposal(calls);
63: 
64:         _onProposalExecuted(sourceChain, sourceAddress, interchainProposalCaller, payload);
65: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L126-L126

126:     function _beforeProposalExecuted(
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         bytes calldata payload
130:     ) internal virtual {
131:         
132:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L142-L142

142:     function _onProposalExecuted(
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual {
148:         
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual {
179:         
180:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L24-L24

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {
25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L42-L42

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) {
47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));
48: 
49:         
50:         (bool success, ) = deployedAddress_.call(init);
51:         if (!success) revert FailedInit();
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L58-L58

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) {
63:         bytes32 newSalt = keccak256(abi.encode(sender, salt));
64:         deployedAddress_ = address(
65:             uint160(
66:                 uint256(
67:                     keccak256(
68:                         abi.encodePacked(
69:                             hex'ff',
70:                             address(this),
71:                             newSalt,
72:                             keccak256(bytecode) 
73:                         )
74:                     )
75:                 )
76:             )
77:         );
78:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L29-L29

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {
30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));
31:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
32: 
33:         emit Deployed(keccak256(bytecode), salt, deployedAddress_);
34:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L49-L49

49:     function deployAndInit(
50:         bytes memory bytecode,
51:         bytes32 salt,
52:         bytes calldata init
53:     ) external returns (address deployedAddress_) {
54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));
55:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
56: 
57:         (bool success, ) = deployedAddress_.call(init);
58:         if (!success) revert FailedInit();
59: 
60:         emit Deployed(keccak256(bytecode), salt, deployedAddress_);
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L67-L67

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) {
68:         bytes32 deploySalt = keccak256(abi.encode(sender, salt));
69:         return Create3.deployedAddress(address(this), deploySalt);
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L21-L21

21:     function deploy(bytes memory bytecode) external {
22:         address deployed;
23: 
24:         assembly {
25:             deployed := create(0, add(bytecode, 32), mload(bytecode))
26:             if iszero(deployed) {
27:                 revert(0, 0)
28:             }
29:         }
30:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L71-L71

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH)))));
73: 
74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01')))));
75:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L32-L32

32:     function setup(bytes calldata params) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L78-L78

78:     function setup(bytes calldata data) external override onlyProxy {
79:         _setup(data);
80:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L43-L43

43:     function interchainTransfer(
44:         string calldata destinationChain,
45:         bytes calldata recipient,
46:         uint256 amount,
47:         bytes calldata metadata
48:     ) external payable {
49:         address sender = msg.sender;
50:         ITokenManager tokenManager = getTokenManager();
51:         
52: 
53: 
54:         if (tokenManagerRequiresApproval()) {
55:             uint256 allowance_ = allowance[sender][address(tokenManager)];
56:             if (allowance_ != type(uint256).max) {
57:                 if (allowance_ > type(uint256).max - amount) {
58:                     allowance_ = type(uint256).max - amount;
59:                 }
60: 
61:                 _approve(sender, address(tokenManager), allowance_ + amount);
62:             }
63:         }
64: 
65:         
66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L79-L79

79:     function interchainTransferFrom(
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable {
86:         uint256 _allowance = allowance[sender][msg.sender];
87: 
88:         if (_allowance != type(uint256).max) {
89:             _approve(sender, msg.sender, _allowance - amount);
90:         }
91: 
92:         ITokenManager tokenManager = getTokenManager();
93:         if (tokenManagerRequiresApproval()) {
94:             uint256 allowance_ = allowance[sender][address(tokenManager)];
95:             if (allowance_ != type(uint256).max) {
96:                 if (allowance_ > type(uint256).max - amount) {
97:                     allowance_ = type(uint256).max - amount;
98:                 }
99: 
100:                 _approve(sender, address(tokenManager), allowance_ + amount);
101:             }
102:         }
103: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L161-L161

161:     function getTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {
162:         tokenManagerAddress = deployer.deployedAddress(address(this), tokenId);
163:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L170-L170

170:     function getValidTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {
171:         tokenManagerAddress = getTokenManagerAddress(tokenId);
172:         if (ITokenManagerProxy(tokenManagerAddress).tokenId() != tokenId) revert TokenManagerDoesNotExist(tokenId);
173:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L180-L180

180:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress) {
181:         address tokenManagerAddress = getValidTokenManagerAddress(tokenId);
182:         tokenAddress = ITokenManager(tokenManagerAddress).tokenAddress();
183:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L191-L191

191:     function getStandardizedTokenAddress(bytes32 tokenId) public view returns (address tokenAddress) {
192:         tokenId = _getStandardizedTokenSalt(tokenId);
193:         tokenAddress = deployer.deployedAddress(address(this), tokenId);
194:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L213-L213

213:     function getCustomTokenId(address sender, bytes32 salt) public pure returns (bytes32 tokenId) {
214:         tokenId = keccak256(abi.encode(PREFIX_CUSTOM_TOKEN_ID, sender, salt));
215:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L241-L241

241:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) {
242:         params = abi.encode(operator, tokenAddress);
243:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L251-L251

251:     function getParamsMintBurn(bytes memory operator, address tokenAddress) public pure returns (bytes memory params) {
252:         params = abi.encode(operator, tokenAddress);
253:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L262-L262

262:     function getParamsLiquidityPool(
263:         bytes memory operator,
264:         address tokenAddress,
265:         address liquidityPoolAddress
266:     ) public pure returns (bytes memory params) {
267:         params = abi.encode(operator, tokenAddress, liquidityPoolAddress);
268:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L275-L275

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit) {
276:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
277:         flowLimit = tokenManager.getFlowLimit();
278:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L285-L285

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount) {
286:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
287:         flowOutAmount = tokenManager.getFlowOutAmount();
288:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L295-L295

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount) {
296:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
297:         flowInAmount = tokenManager.getFlowInAmount();
298:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L325-L325

325:     function deployRemoteCanonicalToken(
326:         bytes32 tokenId,
327:         string calldata destinationChain,
328:         uint256 gasValue
329:     ) public payable notPaused {
330:         address tokenAddress = getValidTokenManagerAddress(tokenId);
331:         tokenAddress = ITokenManager(tokenAddress).tokenAddress();
332:         if (getCanonicalTokenId(tokenAddress) != tokenId) revert NotCanonicalTokenManager();
333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress);
334:         _deployRemoteStandardizedToken(tokenId, tokenName, tokenSymbol, tokenDecimals, '', '', destinationChain, gasValue);
335:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L343-L343

343:     function deployCustomTokenManager(
344:         bytes32 salt,
345:         TokenManagerType tokenManagerType,
346:         bytes memory params
347:     ) public payable notPaused returns (bytes32 tokenId) {
348:         address deployer_ = msg.sender;
349:         tokenId = getCustomTokenId(deployer_, salt);
350:         _deployTokenManager(tokenId, tokenManagerType, params);
351:         emit CustomTokenIdClaimed(tokenId, deployer_, salt);
352:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L365-L365

365:     function deployRemoteCustomTokenManager(
366:         bytes32 salt,
367:         string calldata destinationChain,
368:         TokenManagerType tokenManagerType,
369:         bytes calldata params,
370:         uint256 gasValue
371:     ) external payable notPaused returns (bytes32 tokenId) {
372:         address deployer_ = msg.sender;
373:         tokenId = getCustomTokenId(deployer_, salt);
374:         _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params);
375:         emit CustomTokenIdClaimed(tokenId, deployer_, salt);
376:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L388-L388

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name,
391:         string calldata symbol,
392:         uint8 decimals,
393:         uint256 mintAmount,
394:         address distributor
395:     ) external payable notPaused {
396:         bytes32 tokenId = getCustomTokenId(msg.sender, salt);
397:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, mintAmount, msg.sender);
398:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
399:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
400:         address tokenAddress = getStandardizedTokenAddress(tokenId);
401:         _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress));
402:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L417-L417

417:     function deployAndRegisterRemoteStandardizedToken(
418:         bytes32 salt,
419:         string calldata name,
420:         string calldata symbol,
421:         uint8 decimals,
422:         bytes memory distributor,
423:         bytes memory operator,
424:         string calldata destinationChain,
425:         uint256 gasValue
426:     ) external payable notPaused {
427:         bytes32 tokenId = getCustomTokenId(msg.sender, salt);
428:         _deployRemoteStandardizedToken(tokenId, name, symbol, decimals, distributor, operator, destinationChain, gasValue);
429:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L439

439:     function expressReceiveToken(
440:         bytes32 tokenId,
441:         address destinationAddress,
442:         uint256 amount,
443:         bytes32 commandId
444:     ) external {
445:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
446: 
447:         address caller = msg.sender;
448:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
449:         IERC20 token = IERC20(tokenManager.tokenAddress());
450: 
451:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);
452: 
453:         _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);
454:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L467

467:     function expressReceiveTokenWithData(
468:         bytes32 tokenId,
469:         string memory sourceChain,
470:         bytes memory sourceAddress,
471:         address destinationAddress,
472:         uint256 amount,
473:         bytes calldata data,
474:         bytes32 commandId
475:     ) external {
476:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
477: 
478:         address caller = msg.sender;
479:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
480:         IERC20 token = IERC20(tokenManager.tokenAddress());
481: 
482:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);
483: 
484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);
485: 
486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
487:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L555-L555

555:     function _setup(bytes calldata params) internal override {
556:         _setOperator(params.toAddress());
557:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L575-L575

575:     function _execute(
576:         string calldata sourceChain,
577:         string calldata sourceAddress,
578:         bytes calldata payload
579:     ) internal override onlyRemoteService(sourceChain, sourceAddress) notPaused {
580:         uint256 selector = abi.decode(payload, (uint256));
581:         if (selector == SELECTOR_SEND_TOKEN) {
582:             _processSendTokenPayload(sourceChain, payload);
583:         } else if (selector == SELECTOR_SEND_TOKEN_WITH_DATA) {
584:             _processSendTokenWithDataPayload(sourceChain, payload);
585:         } else if (selector == SELECTOR_DEPLOY_TOKEN_MANAGER) {
586:             _processDeployTokenManagerPayload(payload);
587:         } else if (selector == SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN) {
588:             _processDeployStandardizedTokenAndManagerPayload(payload);
589:         } else {
590:             revert SelectorUnknown();
591:         }
592:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L599-L599

599:     function _processSendTokenPayload(string calldata sourceChain, bytes calldata payload) internal {
600:         (, bytes32 tokenId, bytes memory destinationAddressBytes, uint256 amount) = abi.decode(payload, (uint256, bytes32, bytes, uint256));
601:         bytes32 commandId;
602: 
603:         assembly {
604:             commandId := calldataload(4)
605:         }
606:         address destinationAddress = destinationAddressBytes.toAddress();
607:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
608:         address expressCaller = _popExpressReceiveToken(tokenId, destinationAddress, amount, commandId);
609:         if (expressCaller == address(0)) {
610:             amount = tokenManager.giveToken(destinationAddress, amount);
611:             emit TokenReceived(tokenId, sourceChain, destinationAddress, amount);
612:         } else {
613:             amount = tokenManager.giveToken(expressCaller, amount);
614:         }
615:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L622-L622

622:     function _processSendTokenWithDataPayload(string calldata sourceChain, bytes calldata payload) internal {
623:         bytes32 tokenId;
624:         uint256 amount;
625:         bytes memory sourceAddress;
626:         bytes memory data;
627:         address destinationAddress;
628:         bytes32 commandId;
629: 
630:         assembly {
631:             commandId := calldataload(4)
632:         }
633:         {
634:             bytes memory destinationAddressBytes;
635:             (, tokenId, destinationAddressBytes, amount, sourceAddress, data) = abi.decode(
636:                 payload,
637:                 (uint256, bytes32, bytes, uint256, bytes, bytes)
638:             );
639:             destinationAddress = destinationAddressBytes.toAddress();
640:         }
641:         ITokenManager tokenManager = ITokenManager(getTokenManagerAddress(tokenId));
642:         {
643:             address expressCaller = _popExpressReceiveTokenWithData(
644:                 tokenId,
645:                 sourceChain,
646:                 sourceAddress,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L666-L666

666:     function _processDeployTokenManagerPayload(bytes calldata payload) internal {
667:         (, bytes32 tokenId, TokenManagerType tokenManagerType, bytes memory params) = abi.decode(
668:             payload,
669:             (uint256, bytes32, TokenManagerType, bytes)
670:         );
671:         _deployTokenManager(tokenId, tokenManagerType, params);
672:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L707-L707

707:     function _callContract(
708:         string calldata destinationChain,
709:         bytes memory payload,
710:         uint256 gasValue,
711:         address refundTo
712:     ) internal {
713:         string memory destinationAddress = remoteAddressValidator.getRemoteAddress(destinationChain);
714:         if (gasValue > 0) {
715:             gasService.payNativeGasForContractCall{ value: gasValue }(
716:                 address(this),
717:                 destinationChain,
718:                 destinationAddress,
719:                 payload,
720:                 refundTo
721:             );
722:         }
723:         gateway.callContract(destinationChain, destinationAddress, payload);
724:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L748-L748

748:     function _deployRemoteTokenManager(
749:         bytes32 tokenId,
750:         string calldata destinationChain,
751:         uint256 gasValue,
752:         TokenManagerType tokenManagerType,
753:         bytes memory params
754:     ) internal {
755:         bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params);
756:         _callContract(destinationChain, payload, gasValue, msg.sender);
757:         emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params);
758:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L770-L770

770:     function _deployRemoteStandardizedToken(
771:         bytes32 tokenId,
772:         string memory name,
773:         string memory symbol,
774:         uint8 decimals,
775:         bytes memory distributor,
776:         bytes memory operator,
777:         string calldata destinationChain,
778:         uint256 gasValue
779:     ) internal {
780:         bytes memory payload = abi.encode(
781:             SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN,
782:             tokenId,
783:             name,
784:             symbol,
785:             decimals,
786:             distributor,
787:             operator
788:         );
789:         _callContract(destinationChain, payload, gasValue, msg.sender);
790:         emit RemoteStandardizedTokenAndManagerDeploymentInitialized(
791:             tokenId,
792:             name,
793:             symbol,
794:             decimals,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L808-L808

808:     function _deployTokenManager(
809:         bytes32 tokenId,
810:         TokenManagerType tokenManagerType,
811:         bytes memory params
812:     ) internal {
813:         (bool success, ) = tokenManagerDeployer.delegatecall(
814:             abi.encodeWithSelector(ITokenManagerDeployer.deployTokenManager.selector, tokenId, tokenManagerType, params)
815:         );
816:         if (!success) {
817:             revert TokenManagerDeploymentFailed();
818:         }
819:         emit TokenManagerDeployed(tokenId, tokenManagerType, params);
820:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L827-L827

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt) {
828:         return keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_SALT, tokenId));
829:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L841-L841

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals,
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal {
850:         bytes32 salt = _getStandardizedTokenSalt(tokenId);
851:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
852: 
853:         (bool success, ) = standardizedTokenDeployer.delegatecall(
854:             abi.encodeWithSelector(
855:                 IStandardizedTokenDeployer.deployStandardizedToken.selector,
856:                 salt,
857:                 tokenManagerAddress,
858:                 distributor,
859:                 name,
860:                 symbol,
861:                 decimals,
862:                 mintAmount,
863:                 mintTo
864:             )
865:         );

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L880-L880

880:     function _expressExecuteWithInterchainTokenToken(
881:         bytes32 tokenId,
882:         address destinationAddress,
883:         string memory sourceChain,
884:         bytes memory sourceAddress,
885:         bytes calldata data,
886:         uint256 amount
887:     ) internal {
888:         IInterchainTokenExpressExecutable(destinationAddress).expressExecuteWithInterchainToken(
889:             sourceChain,
890:             sourceAddress,
891:             data,
892:             tokenId,
893:             amount
894:         );
895:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L49-L49

49:     function setup(bytes calldata params) external override onlyProxy {
50:         {
51:             address distributor_;
52:             address tokenManager_;
53:             string memory tokenName;
54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));
55:             _setDistributor(distributor_);
56:             tokenManager = tokenManager_;
57:             _setDomainTypeSignatureHash(tokenName);
58:             name = tokenName;
59:         }
60:         {
61:             uint256 mintAmount;
62:             address mintTo;
63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
64:             if (mintAmount > 0) {
65:                 _mint(mintTo, mintAmount);
66:             }
67:         }
68:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L83-L83

83:     function sendToken(
84:         string calldata destinationChain,
85:         bytes calldata destinationAddress,
86:         uint256 amount,
87:         bytes calldata metadata
88:     ) external payable virtual {
89:         address sender = msg.sender;
90:         amount = _takeToken(sender, amount);
91:         _addFlowOut(amount);
92:         interchainTokenService.transmitSendToken{ value: msg.value }(
93:             _getTokenId(),
94:             sender,
95:             destinationChain,
96:             destinationAddress,
97:             amount,
98:             metadata
99:         );
100:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L109-L109

109:     function callContractWithInterchainToken(
110:         string calldata destinationChain,
111:         bytes calldata destinationAddress,
112:         uint256 amount,
113:         bytes calldata data
114:     ) external payable virtual {
115:         address sender = msg.sender;
116:         amount = _takeToken(sender, amount);
117:         _addFlowOut(amount);
118:         uint32 version = 0;
119:         interchainTokenService.transmitSendToken{ value: msg.value }(
120:             _getTokenId(),
121:             sender,
122:             destinationChain,
123:             destinationAddress,
124:             amount,
125:             abi.encodePacked(version, data)
126:         );
127:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L136-L136

136:     function transmitInterchainTransfer(
137:         address sender,
138:         string calldata destinationChain,
139:         bytes calldata destinationAddress,
140:         uint256 amount,
141:         bytes calldata metadata
142:     ) external payable virtual onlyToken {
143:         amount = _takeToken(sender, amount);
144:         _addFlowOut(amount);
145:         interchainTokenService.transmitSendToken{ value: msg.value }(
146:             _getTokenId(),
147:             sender,
148:             destinationChain,
149:             destinationAddress,
150:             amount,
151:             metadata
152:         );
153:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L32-L32

32:     function _setup(bytes calldata params) internal override {
33:         
34:         (, address tokenAddress) = abi.decode(params, (bytes, address));
35:         _setTokenAddress(tokenAddress);
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L36-L36

36:     function _setup(bytes calldata params) internal override {
37:         
38:         (, address tokenAddress_, address liquidityPool_) = abi.decode(params, (bytes, address, address));
39:         _setTokenAddress(tokenAddress_);
40:         _setLiquidityPool(liquidityPool_);
41:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L26-L26

26:     function _getExpressReceiveTokenSlot(
27:         bytes32 tokenId,
28:         address destinationAddress,
29:         uint256 amount,
30:         bytes32 commandId
31:     ) internal pure returns (uint256 slot) {
32:         slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId)));
33:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L46-L46

46:     function _getExpressReceiveTokenWithDataSlot(
47:         bytes32 tokenId,
48:         string memory sourceChain,
49:         bytes memory sourceAddress,
50:         address destinationAddress,
51:         uint256 amount,
52:         bytes memory data,
53:         bytes32 commandId
54:     ) internal pure returns (uint256 slot) {
55:         slot = uint256(
56:             keccak256(
57:                 abi.encode(
58:                     PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA,
59:                     tokenId,
60:                     sourceChain,
61:                     sourceAddress,
62:                     destinationAddress,
63:                     amount,
64:                     data,
65:                     commandId
66:                 )
67:             )
68:         );
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L79-L79

79:     function _setExpressReceiveToken(
80:         bytes32 tokenId,
81:         address destinationAddress,
82:         uint256 amount,
83:         bytes32 commandId,
84:         address expressCaller
85:     ) internal {
86:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
87:         address prevExpressCaller;
88:         assembly {
89:             prevExpressCaller := sload(slot)
90:         }
91:         if (prevExpressCaller != address(0)) revert AlreadyExpressCalled();
92:         assembly {
93:             sstore(slot, expressCaller)
94:         }
95:         emit ExpressReceive(tokenId, destinationAddress, amount, commandId, expressCaller);
96:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L110-L110

110:     function _setExpressReceiveTokenWithData(
111:         bytes32 tokenId,
112:         string memory sourceChain,
113:         bytes memory sourceAddress,
114:         address destinationAddress,
115:         uint256 amount,
116:         bytes calldata data,
117:         bytes32 commandId,
118:         address expressCaller
119:     ) internal {
120:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
121:             tokenId,
122:             sourceChain,
123:             sourceAddress,
124:             destinationAddress,
125:             amount,
126:             data,
127:             commandId
128:         );
129:         address prevExpressCaller;
130:         assembly {
131:             prevExpressCaller := sload(slot)
132:         }
133:         if (prevExpressCaller != address(0)) revert AlreadyExpressCalled();
134:         assembly {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L148-L148

148:     function getExpressReceiveToken(
149:         bytes32 tokenId,
150:         address destinationAddress,
151:         uint256 amount,
152:         bytes32 commandId
153:     ) public view returns (address expressCaller) {
154:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
155:         assembly {
156:             expressCaller := sload(slot)
157:         }
158:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L171-L171

171:     function getExpressReceiveTokenWithData(
172:         bytes32 tokenId,
173:         string memory sourceChain,
174:         bytes memory sourceAddress,
175:         address destinationAddress,
176:         uint256 amount,
177:         bytes calldata data,
178:         bytes32 commandId
179:     ) public view returns (address expressCaller) {
180:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
181:             tokenId,
182:             sourceChain,
183:             sourceAddress,
184:             destinationAddress,
185:             amount,
186:             data,
187:             commandId
188:         );
189:         assembly {
190:             expressCaller := sload(slot)
191:         }
192:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L202-L202

202:     function _popExpressReceiveToken(
203:         bytes32 tokenId,
204:         address destinationAddress,
205:         uint256 amount,
206:         bytes32 commandId
207:     ) internal returns (address expressCaller) {
208:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);
209:         assembly {
210:             expressCaller := sload(slot)
211:         }
212:         if (expressCaller != address(0)) {
213:             assembly {
214:                 sstore(slot, 0)
215:             }
216:             emit ExpressExecutionFulfilled(tokenId, destinationAddress, amount, commandId, expressCaller);
217:         }
218:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L231-L231

231:     function _popExpressReceiveTokenWithData(
232:         bytes32 tokenId,
233:         string memory sourceChain,
234:         bytes memory sourceAddress,
235:         address destinationAddress,
236:         uint256 amount,
237:         bytes memory data,
238:         bytes32 commandId
239:     ) internal returns (address expressCaller) {
240:         uint256 slot = _getExpressReceiveTokenWithDataSlot(
241:             tokenId,
242:             sourceChain,
243:             sourceAddress,
244:             destinationAddress,
245:             amount,
246:             data,
247:             commandId
248:         );
249:         assembly {
250:             expressCaller := sload(slot)
251:         }
252:         if (expressCaller != address(0)) {
253:             assembly {
254:                 sstore(slot, 0)
255:             }

[NC-48] Consider adding a time delay to upgrade implementation functions

Number of instances found

2

Resolution

It's often considered a good practice to use a timelock on sensitive functions such as upgrading a contract, especially when these contracts handle user funds or critical system states.

A timelock is a delay period that must pass between when an action (like an upgrade) is scheduled and when it can be executed. This provides a window of time for users or governance participants to observe the proposed change and potentially respond if they disagree with the action.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L279-L279

279:     function upgrade( // <= FOUND
280:         address newImplementation,
281:         bytes32 newImplementationCodeHash,
282:         bytes calldata setupParams
283:     ) external override onlyGovernance {
284:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();
285: 
286:         if (AxelarGateway(newImplementation).contractId() != contractId()) revert InvalidImplementation();
287: 
288:         emit Upgraded(newImplementation);
289: 
290:         
291:         
292:         if (setupParams.length != 0) {
293:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(IAxelarGateway.setup.selector, setupParams));
294: 
295:             if (!success) revert SetupFailed();
296:         }
297: 
298:         _setImplementation(newImplementation);
299:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L52-L52

52:     function upgrade( // <= FOUND
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner {
57:         if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation();
58:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();
59: 
60:         if (params.length > 0) {
61:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params));
62: 
63:             if (!success) revert SetupFailed();
64:         }
65: 
66:         emit Upgraded(newImplementation);
67: 
68:         assembly {
69:             sstore(_IMPLEMENTATION_SLOT, newImplementation)
70:         }
71:     }

[GAS-1] The use of a logical AND in place of double if is slightly less gas efficient in instances where there isn't a corresponding else statement for the given if statement

Number of instances found

5

Resolution

Using a double if statement instead of logical AND (&&) can provide similar short-circuiting behavior whereas double if is slightly more efficient.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L445-L445

426:     function burnToken(bytes calldata params, bytes32) external onlySelf {
427:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));
428: 
429:         address tokenAddress = tokenAddresses(symbol);
430: 
431:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
432: 
433:         if (_getTokenType(symbol) == TokenType.External) {
434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode)));
435: 
436:             if (_hasCode(depositHandlerAddress)) return;
437: 
438:             DepositHandler depositHandler = new DepositHandler{ salt: salt }();
439: 
440:             (bool success, bytes memory returnData) = depositHandler.execute(
441:                 tokenAddress,
442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler)))
443:             );
444: 
445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol); // <= FOUND
446: 
447:             
448:             depositHandler.destroy(address(this));
449:         } else {
450:             IBurnableMintableCappedERC20(tokenAddress).burn(salt);
451:         }
452:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L508-L508

504:     function _hasCode(address addr) internal view returns (bool) {
505:         bytes32 codehash = addr.codehash;
506: 
507:         
508:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // <= FOUND
509:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L634-L634

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {
633:         uint256 limit = tokenMintLimit(symbol);
634:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol); // <= FOUND
635: 
636:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount);
637:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L50-L50

35:     function init(
36:         address implementationAddress,
37:         address newOwner,
38:         bytes memory params
39:     ) external {
40:         address owner;
41: 
42:         assembly {
43:             owner := sload(_OWNER_SLOT)
44:         }
45: 
46:         if (msg.sender != owner) revert NotOwner();
47:         if (implementation() != address(0)) revert AlreadyInitialized();
48: 
49:         bytes32 id = contractId();
50:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation(); // <= FOUND
51: 
52:         assembly {
53:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
54:             sstore(_OWNER_SLOT, newOwner)
55:         }
56: 
57:         if (params.length != 0) {
58:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, params));
59:             if (!success) revert SetupFailed();
60:         }
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L58-L58

54:     function _lowerCase(string memory s) internal pure returns (string memory) {
55:         uint256 length = bytes(s).length;
56:         for (uint256 i; i < length; i++) {
57:             uint8 b = uint8(bytes(s)[i]);
58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32)); // <= FOUND
59:         }
60:         return s;
61:     }

[GAS-2] Calling .length in a for loop wastes gas

Number of instances found

3

Resolution

Rather than calling .length for an array in a for loop declaration, it is far more gas efficient to cache this length before and use that instead. This will prevent the array length from being called every loop iteration

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L63-L63

63: for (uint256 i = 0; i < interchainCalls.length; )  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L74-L74

74: for (uint256 i = 0; i < calls.length; i++)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L24-L24

24: for (uint256 i = 0; i < data.length; ++i)  // <= FOUND

[GAS-3] ++X costs slightly less gas than X++ (same with --)

Number of instances found

3

Resolution

Move the ++/-- action to the left of the variable

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L74-L74

73:     function _executeProposal(InterchainCalls.Call[] memory calls) internal {
74:         for (uint256 i = 0; i < calls.length; i++) { // <= FOUND
75:             InterchainCalls.Call memory call = calls[i];
76:             (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData);
77: 
78:             if (!success) {
79:                 _onTargetExecutionFailed(call, result);
80:             } else {
81:                 _onTargetExecuted(call, result);
82:             }
83:         }
84:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L56-L56

54:     function _lowerCase(string memory s) internal pure returns (string memory) {
55:         uint256 length = bytes(s).length;
56:         for (uint256 i; i < length; i++) { // <= FOUND
57:             uint8 b = uint8(bytes(s)[i]);
58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32));
59:         }
60:         return s;
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L124-L124

119:     function getSignerVotesCount(bytes32 topic) external view override returns (uint256) {
120:         uint256 length = signers.accounts.length;
121:         uint256 voteCount;
122:         for (uint256 i; i < length; ++i) {
123:             if (votingPerTopic[signerEpoch][topic].hasVoted[signers.accounts[i]]) {
124:                 voteCount++; // <= FOUND
125:             }
126:         }
127: 
128:         return voteCount;
129:     }

[GAS-4] Internal functions never used once can be removed

Number of instances found

4

Resolution

Internal functions which are never used use unnecessary gas and should be safely removed.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L41-L41

41:     function _execute( // <= FOUND
42:         string calldata sourceChain,
43:         string calldata sourceAddress,
44:         bytes calldata payload
45:     ) internal override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L575-L575

575:     function _execute( // <= FOUND
576:         string calldata sourceChain,
577:         string calldata sourceAddress,
578:         bytes calldata payload
579:     ) internal override onlyRemoteService(sourceChain, sourceAddress) notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L155-L155

155:     function _executeWithToken( // <= FOUND
156:         string calldata, 
157:         string calldata, 
158:         bytes calldata, 
159:         string calldata, 
160:         uint256 
161:     ) internal pure override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType) // <= FOUND
560:         internal
561:         pure
562:         returns (address implementation)
563:     

[GAS-5] Internal functions only used once can be inlined so save gas

Number of instances found

31

Resolution

If a internal function is only used once it doesn't make sense to modularise it unless the function which does call the function would be overly long and complex otherwise

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L113-L113

113:     function _processCommand( // <= FOUND
114:         uint256 commandId,
115:         address target,
116:         bytes memory callData,
117:         uint256 nativeValue,
118:         uint256 eta
119:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L72-L72

72:     function _processCommand( // <= FOUND
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L149

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L79-L79

79:     function _finalizeTimeLock(bytes32 hash) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L504-L504

504:     function _hasCode(address addr) internal view returns (bool)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L614-L614

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L632-L632

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved( // <= FOUND
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint( // <= FOUND
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L676-L676

676:     function _setImplementation(address newImplementation) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L73-L73

73:     function _executeProposal(InterchainCalls.Call[] memory calls) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L126-L126

126:     function _beforeProposalExecuted( // <= FOUND
127:         string calldata sourceChain,
128:         string calldata sourceAddress,
129:         bytes calldata payload
130:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L142-L142

142:     function _onProposalExecuted( // <= FOUND
143:         string calldata, 
144:         string calldata, 
145:         address, 
146:         bytes calldata payload
147:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L156-L156

156:     function _onTargetExecutionFailed( // <= FOUND
157:         InterchainCalls.Call memory, 
158:         bytes memory result
159:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L599-L599

599:     function _processSendTokenPayload(string calldata sourceChain, bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L622-L622

622:     function _processSendTokenWithDataPayload(string calldata sourceChain, bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L666-L666

666:     function _processDeployTokenManagerPayload(bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L678-L678

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L748-L748

748:     function _deployRemoteTokenManager( // <= FOUND
749:         bytes32 tokenId,
750:         string calldata destinationChain,
751:         uint256 gasValue,
752:         TokenManagerType tokenManagerType,
753:         bytes memory params
754:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L872-L872

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L880-L880

880:     function _expressExecuteWithInterchainTokenToken( // <= FOUND
881:         bytes32 tokenId,
882:         address destinationAddress,
883:         string memory sourceChain,
884:         bytes memory sourceAddress,
885:         bytes calldata data,
886:         uint256 amount
887:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L54-L54

54:     function _getImplementation(IInterchainTokenService interchainTokenServiceAddress_, uint256 implementationType_) // <= FOUND
55:         internal
56:         view
57:         returns (address impl)
58:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L60-L60

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L79-L79

79:     function _setExpressReceiveToken( // <= FOUND
80:         bytes32 tokenId,
81:         address destinationAddress,
82:         uint256 amount,
83:         bytes32 commandId,
84:         address expressCaller
85:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L110-L110

110:     function _setExpressReceiveTokenWithData( // <= FOUND
111:         bytes32 tokenId,
112:         string memory sourceChain,
113:         bytes memory sourceAddress,
114:         address destinationAddress,
115:         uint256 amount,
116:         bytes calldata data,
117:         bytes32 commandId,
118:         address expressCaller
119:     ) internal 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L202-L202

202:     function _popExpressReceiveToken( // <= FOUND
203:         bytes32 tokenId,
204:         address destinationAddress,
205:         uint256 amount,
206:         bytes32 commandId
207:     ) internal returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L231-L231

231:     function _popExpressReceiveTokenWithData( // <= FOUND
232:         bytes32 tokenId,
233:         string memory sourceChain,
234:         bytes memory sourceAddress,
235:         address destinationAddress,
236:         uint256 amount,
237:         bytes memory data,
238:         bytes32 commandId
239:     ) internal returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L34-L34

34:     function _setFlowLimit(uint256 flowLimit) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L124-L124

124:     function _addFlowIn(uint256 flowInAmount) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L41-L41

41:     function _setPaused(bool paused) internal  // <= FOUND

[GAS-6] Public functions not used internally can be marked as external to save gas

Number of instances found

15

Resolution

Public functions that aren't used internally in Solidity contracts should be made external to optimize gas usage and improve contract efficiency. External functions can only be called from outside the contract, and their arguments are directly read from the calldata, which is more gas-efficient than loading them into memory, as is the case for public functions. By using external visibility, developers can reduce gas consumption for external calls and ensure that the contract operates more cost-effectively for users. Moreover, setting the appropriate visibility level for functions also enhances code readability and maintainability, promoting a more secure and well-structured contract design.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L182-L182

182:     function authModule() public view override returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L186-L186

186:     function governance() public view override returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L190-L190

190:     function mintLimiter() public view override returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L194-L194

194:     function tokenDeployer() public view returns (address)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L48-L48

48:     function isFinal() public view returns (bool)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L72-L72

72:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) public returns (address finalImplementation_)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L152-L152

152:     function getChainName() public view returns (string memory name)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L241-L241

241:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) public pure returns (bytes memory params)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L251-L251

251:     function getParamsMintBurn(bytes memory operator, address tokenAddress) public pure returns (bytes memory params)  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L262-L262

262:     function getParamsLiquidityPool( // <= FOUND
263:         bytes memory operator,
264:         address tokenAddress,
265:         address liquidityPoolAddress
266:     ) public pure returns (bytes memory params) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L325-L325

325:     function deployRemoteCanonicalToken( // <= FOUND
326:         bytes32 tokenId,
327:         string calldata destinationChain,
328:         uint256 gasValue
329:     ) public payable notPaused 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L343-L343

343:     function deployCustomTokenManager( // <= FOUND
344:         bytes32 salt,
345:         TokenManagerType tokenManagerType,
346:         bytes memory params
347:     ) public payable notPaused returns (bytes32 tokenId) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L148-L148

148:     function getExpressReceiveToken( // <= FOUND
149:         bytes32 tokenId,
150:         address destinationAddress,
151:         uint256 amount,
152:         bytes32 commandId
153:     ) public view returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L171-L171

171:     function getExpressReceiveTokenWithData( // <= FOUND
172:         bytes32 tokenId,
173:         string memory sourceChain,
174:         bytes memory sourceAddress,
175:         address destinationAddress,
176:         uint256 amount,
177:         bytes calldata data,
178:         bytes32 commandId
179:     ) public view returns (address expressCaller) 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L22-L22

22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results)  // <= FOUND

[GAS-7] Solidity version 0.8.19 is more gas efficient

Number of instances found

73

Resolution

Solidity version 0.8.19 introduced a array of gas optimizations which make contracts which use it more efficient. Provided compatability it may be beneficial to upgrade to this version

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L3-L3

3: pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L3-L3

3: pragma solidity ^0.8.9;

[GAS-8] bytes.concat() can be used in place of abi.encodePacked

Number of instances found

3

Resolution

Given concatenation is not going to be used for hashing bytes.concat is the preferred method to use as its more gas efficient

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L125-L125

109:     function callContractWithInterchainToken(
110:         string calldata destinationChain,
111:         bytes calldata destinationAddress,
112:         uint256 amount,
113:         bytes calldata data
114:     ) external payable virtual {
115:         address sender = msg.sender;
116:         amount = _takeToken(sender, amount);
117:         _addFlowOut(amount);
118:         uint32 version = 0;
119:         interchainTokenService.transmitSendToken{ value: msg.value }(
120:             _getTokenId(),
121:             sender,
122:             destinationChain,
123:             destinationAddress,
124:             amount,
125:             abi.encodePacked(version, data) // <= FOUND
126:         );
127:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L63-L63

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name,
54:         string calldata symbol,
55:         uint8 decimals,
56:         uint256 mintAmount,
57:         address mintTo
58:     ) external payable {
59:         bytes memory bytecode;
60:         address implementationAddress = distributor == tokenManager ? implementationMintBurnAddress : implementationLockUnlockAddress;
61:         {
62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo);
63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params)); // <= FOUND
64:         }
65:         address tokenAddress = deployer.deploy(bytecode, salt);
66:         if (tokenAddress.code.length == 0) revert TokenDeploymentFailed();
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L39-L39

33:     function deployTokenManager(
34:         bytes32 tokenId,
35:         uint256 implementationType,
36:         bytes calldata params
37:     ) external payable {
38:         bytes memory args = abi.encode(address(this), implementationType, tokenId, params);
39:         bytes memory bytecode = abi.encodePacked(type(TokenManagerProxy).creationCode, args); // <= FOUND
40:         address tokenManagerAddress = deployer.deploy(bytecode, tokenId);
41:         if (tokenManagerAddress.code.length == 0) revert TokenManagerDeploymentFailed();
42:     }

[GAS-9] Constructors can be marked as payable to save deployment gas

Number of instances found

27

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L33-L33

33:     constructor(
34:         address gateway,
35:         string memory governanceChain_,
36:         string memory governanceAddress_,
37:         uint256 minimumTimeDelay
38:     ) AxelarExecutable(gateway) TimeLock(minimumTimeDelay) {
39:         governanceChain = governanceChain_;
40:         governanceAddress = governanceAddress_;
41:         governanceChainHash = keccak256(bytes(governanceChain_));
42:         governanceAddressHash = keccak256(bytes(governanceAddress_));
43:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L33-L33

33:     constructor(
34:         address gateway,
35:         string memory governanceChain,
36:         string memory governanceAddress,
37:         uint256 minimumTimeDelay,
38:         address[] memory cosigners,
39:         uint256 threshold
40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L35-L35

35:     constructor(address[] memory accounts, uint256 threshold) {
36:         _rotateSigners(accounts, threshold);
37:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L20-L20

20:     constructor(address[] memory accounts, uint256 threshold) MultisigBase(accounts, threshold) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L21-L21

21:     constructor(uint256 minimumTimeDelay) {
22:         _minimumTimeLockDelay = minimumTimeDelay;
23:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L64-L64

64:     constructor(address authModule_, address tokenDeployerImplementation_) {
65:         if (authModule_.code.length == 0) revert InvalidAuthModule();
66:         if (tokenDeployerImplementation_.code.length == 0) revert InvalidTokenDeployer();
67: 
68:         AUTH_MODULE = authModule_;
69:         TOKEN_DEPLOYER_IMPLEMENTATION = tokenDeployerImplementation_;
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L42-L42

42:     constructor(address _gateway, address _gasService) {
43:         gateway = IAxelarGateway(_gateway);
44:         gasService = IAxelarGasService(_gasService);
45:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L29-L29

29:     constructor(address _gateway, address _owner) AxelarExecutable(_gateway) {
30:         _transferOwnership(_owner);
31:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L25-L25

25:     constructor(
26:         address implementationAddress,
27:         address owner,
28:         bytes memory setupParams
29:     ) {
30:         if (owner == address(0)) revert InvalidOwner();
31: 
32:         bytes32 id = contractId();
33:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();
34: 
35:         assembly {
36:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
37:             sstore(_OWNER_SLOT, owner)
38:         }
39: 
40:         if (setupParams.length != 0) {
41:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, setupParams));
42:             if (!success) revert SetupFailed();
43:         }
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L22-L22

22:     constructor() {
23:         implementationAddress = address(this);
24:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L20-L20

20:     constructor() {
21:         assembly {
22:             sstore(_OWNER_SLOT, caller())
23:         }
24:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L26-L26

26:     constructor(
27:         address implementationAddress,
28:         address owner,
29:         bytes memory setupParams
30:     ) Proxy(implementationAddress, owner, setupParams) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L23-L23

23:     constructor(address implementationAddress) {
24:         implementation = implementationAddress;
25:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L83-L83

83:     constructor(
84:         address tokenManagerDeployer_,
85:         address standardizedTokenDeployer_,
86:         address gateway_,
87:         address gasService_,
88:         address remoteAddressValidator_,
89:         address[] memory tokenManagerImplementations,
90:         string memory chainName_
91:     ) AxelarExecutable(gateway_) {
92:         if (
93:             remoteAddressValidator_ == address(0) ||
94:             gasService_ == address(0) ||
95:             tokenManagerDeployer_ == address(0) ||
96:             standardizedTokenDeployer_ == address(0)
97:         ) revert ZeroAddress();
98:         remoteAddressValidator = IRemoteAddressValidator(remoteAddressValidator_);
99:         gasService = IAxelarGasService(gasService_);
100:         tokenManagerDeployer = tokenManagerDeployer_;
101:         standardizedTokenDeployer = standardizedTokenDeployer_;
102:         deployer = ITokenManagerDeployer(tokenManagerDeployer_).deployer();
103: 
104:         if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();
105: 
106:         implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK);
107:         implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L19-L19

19:     constructor(
20:         address implementationAddress,
21:         address owner,
22:         address operator
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L20-L20

20:     constructor(
21:         address implementationAddress,
22:         address owner,
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L21-L21

21:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) {
22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();
23: 
24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
25:         if (!success) revert SetupFailed();
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L25-L25

25:     constructor(
26:         address interchainTokenServiceAddress_,
27:         uint256 implementationType_,
28:         bytes32 tokenId_,
29:         bytes memory params
30:     ) {
31:         interchainTokenServiceAddress = IInterchainTokenService(interchainTokenServiceAddress_);
32:         implementationType = implementationType_;
33:         tokenId = tokenId_;
34:         address impl = _getImplementation(IInterchainTokenService(interchainTokenServiceAddress_), implementationType_);
35: 
36:         (bool success, ) = impl.delegatecall(abi.encodeWithSelector(TokenManagerProxy.setup.selector, params));
37:         if (!success) revert SetupFailed();
38:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L27-L27

27:     constructor(address _interchainTokenServiceAddress) {
28:         if (_interchainTokenServiceAddress == address(0)) revert ZeroAddress();
29:         interchainTokenServiceAddress = _interchainTokenServiceAddress;
30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString())));
31:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L27-L27

27:     constructor(address interchainTokenService_) {
28:         if (interchainTokenService_ == address(0)) revert TokenLinkerZeroAddress();
29:         interchainTokenService = IInterchainTokenService(interchainTokenService_);
30:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L19-L19

19:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L22-L22

22:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L26-L26

26:     constructor(
27:         address deployer_,
28:         address implementationLockUnlockAddress_,
29:         address implementationMintBurnAddress_
30:     ) {
31:         if (deployer_ == address(0) || implementationLockUnlockAddress_ == address(0) || implementationMintBurnAddress_ == address(0))
32:             revert AddressZero();
33:         deployer = Create3Deployer(deployer_);
34:         implementationLockUnlockAddress = implementationLockUnlockAddress_;
35:         implementationMintBurnAddress = implementationMintBurnAddress_;
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L22-L22

22:     constructor(address deployer_) {
23:         if (deployer_ == address(0)) revert AddressZero();
24:         deployer = Create3Deployer(deployer_);
25:     }

[GAS-10] Usage of smaller uint/int types causes overhead

Number of instances found

14

Resolution

When using a smaller int/uint type it first needs to be converted to it's 258 bit counterpart to be operated, this increases the gass cost and thus should be avoided. However it does make sense to use smaller int/uint values within structs provided you pack the struct properly.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L385-L385

384:     function deployToken(bytes calldata params, bytes32) external onlySelf {
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode( // <= FOUND
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol);
392: 
393:         if (tokenAddress == address(0)) {
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol));
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt)
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol);
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom);
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);
409: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L333-L333

325:     function deployRemoteCanonicalToken(
326:         bytes32 tokenId,
327:         string calldata destinationChain,
328:         uint256 gasValue
329:     ) public payable notPaused {
330:         address tokenAddress = getValidTokenManagerAddress(tokenId);
331:         tokenAddress = ITokenManager(tokenAddress).tokenAddress();
332:         if (getCanonicalTokenId(tokenAddress) != tokenId) revert NotCanonicalTokenManager();
333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress); // <= FOUND
334:         _deployRemoteStandardizedToken(tokenId, tokenName, tokenSymbol, tokenDecimals, '', '', destinationChain, gasValue);
335:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L392-L392

388:     function deployAndRegisterStandardizedToken(
389:         bytes32 salt,
390:         string calldata name,
391:         string calldata symbol,
392:         uint8 decimals, // <= FOUND
393:         uint256 mintAmount,
394:         address distributor
395:     ) external payable notPaused {
396:         bytes32 tokenId = getCustomTokenId(msg.sender, salt);
397:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, mintAmount, msg.sender);
398:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
399:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
400:         address tokenAddress = getStandardizedTokenAddress(tokenId);
401:         _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress));
402:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L421-L421

417:     function deployAndRegisterRemoteStandardizedToken(
418:         bytes32 salt,
419:         string calldata name,
420:         string calldata symbol,
421:         uint8 decimals, // <= FOUND
422:         bytes memory distributor,
423:         bytes memory operator,
424:         string calldata destinationChain,
425:         uint256 gasValue
426:     ) external payable notPaused {
427:         bytes32 tokenId = getCustomTokenId(msg.sender, salt);
428:         _deployRemoteStandardizedToken(tokenId, name, symbol, decimals, distributor, operator, destinationChain, gasValue);
429:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L684-L684

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal {
679:         (
680:             ,
681:             bytes32 tokenId,
682:             string memory name,
683:             string memory symbol,
684:             uint8 decimals, // <= FOUND
685:             bytes memory distributorBytes,
686:             bytes memory operatorBytes
687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));
688:         address tokenAddress = getStandardizedTokenAddress(tokenId);
689:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
690:         address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress;
691:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, 0, distributor);
692:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
693:         _deployTokenManager(
694:             tokenId,
695:             tokenManagerType,
696:             abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)
697:         );
698:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L731-L731

726:     function _validateToken(address tokenAddress)
727:         internal
728:         returns (
729:             string memory name,
730:             string memory symbol,
731:             uint8 decimals // <= FOUND
732:         )
733:     {
734:         IERC20Named token = IERC20Named(tokenAddress);
735:         name = token.name();
736:         symbol = token.symbol();
737:         decimals = token.decimals();
738:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L774-L774

770:     function _deployRemoteStandardizedToken(
771:         bytes32 tokenId,
772:         string memory name,
773:         string memory symbol,
774:         uint8 decimals, // <= FOUND
775:         bytes memory distributor,
776:         bytes memory operator,
777:         string calldata destinationChain,
778:         uint256 gasValue
779:     ) internal {
780:         bytes memory payload = abi.encode(
781:             SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN,
782:             tokenId,
783:             name,
784:             symbol,
785:             decimals,
786:             distributor,
787:             operator
788:         );
789:         _callContract(destinationChain, payload, gasValue, msg.sender);
790:         emit RemoteStandardizedTokenAndManagerDeploymentInitialized(
791:             tokenId,
792:             name,
793:             symbol,
794:             decimals,
795:             distributor,
796:             operator,
797:             destinationChain,
798:             gasValue

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L846-L846

841:     function _deployStandardizedToken(
842:         bytes32 tokenId,
843:         address distributor,
844:         string memory name,
845:         string memory symbol,
846:         uint8 decimals, // <= FOUND
847:         uint256 mintAmount,
848:         address mintTo
849:     ) internal {
850:         bytes32 salt = _getStandardizedTokenSalt(tokenId);
851:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
852: 
853:         (bool success, ) = standardizedTokenDeployer.delegatecall(
854:             abi.encodeWithSelector(
855:                 IStandardizedTokenDeployer.deployStandardizedToken.selector,
856:                 salt,
857:                 tokenManagerAddress,
858:                 distributor,
859:                 name,
860:                 symbol,
861:                 decimals,
862:                 mintAmount,
863:                 mintTo
864:             )
865:         );
866:         if (!success) {
867:             revert StandardizedTokenDeploymentFailed();
868:         }
869:         emit StandardizedTokenDeployed(tokenId, name, symbol, decimals, mintAmount, mintTo);
870:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L57-L57

54:     function _lowerCase(string memory s) internal pure returns (string memory) {
55:         uint256 length = bytes(s).length;
56:         for (uint256 i; i < length; i++) {
57:             uint8 b = uint8(bytes(s)[i]); // <= FOUND
58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32));
59:         }
60:         return s;
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L55-L55

49:     function deployStandardizedToken(
50:         bytes32 salt,
51:         address tokenManager,
52:         address distributor,
53:         string calldata name,
54:         string calldata symbol,
55:         uint8 decimals, // <= FOUND
56:         uint256 mintAmount,
57:         address mintTo
58:     ) external payable {
59:         bytes memory bytecode;
60:         address implementationAddress = distributor == tokenManager ? implementationMintBurnAddress : implementationLockUnlockAddress;
61:         {
62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo);
63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params));
64:         }
65:         address tokenAddress = deployer.deploy(bytecode, salt);
66:         if (tokenAddress.code.length == 0) revert TokenDeploymentFailed();
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L25-L25

25: uint8 public decimals; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L517-L517

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused {
510:         bytes memory payload;
511:         if (metadata.length < 4) {
512:             payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount);
513:             _callContract(destinationChain, payload, msg.value, sourceAddress);
514:             emit TokenSent(tokenId, destinationChain, destinationAddress, amount);
515:             return;
516:         }
517:         uint32 version; // <= FOUND
518:         (version, metadata) = _decodeMetadata(metadata);
519:         if (version > 0) revert InvalidMetadataVersion(version);
520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata);
521:         _callContract(destinationChain, payload, msg.value, sourceAddress);
522:         emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata);
523:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L872-L872

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data) { // <= FOUND
873:         assembly {
874:             data.length := sub(metadata.length, 4)
875:             data.offset := add(metadata.offset, 4)
876:             version := calldataload(sub(metadata.offset, 28))
877:         }
878:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L118-L118

109:     function callContractWithInterchainToken(
110:         string calldata destinationChain,
111:         bytes calldata destinationAddress,
112:         uint256 amount,
113:         bytes calldata data
114:     ) external payable virtual {
115:         address sender = msg.sender;
116:         amount = _takeToken(sender, amount);
117:         _addFlowOut(amount);
118:         uint32 version = 0; // <= FOUND
119:         interchainTokenService.transmitSendToken{ value: msg.value }(
120:             _getTokenId(),
121:             sender,
122:             destinationChain,
123:             destinationAddress,
124:             amount,
125:             abi.encodePacked(version, data)
126:         );
127:     }

[GAS-11] Avoid updating storage when the value hasn't changed

Number of instances found

32

Resolution

In Solidity, manipulating contract storage comes with significant gas costs. One can optimize gas usage by preventing unnecessary storage updates when the new value is the same as the existing one. If an existing value is the same as the new one, not reassigning it to the storage could potentially save substantial amounts of gas, notably 2900 gas for a 'Gsreset'. This saving may come at the expense of a cold storage load operation ('Gcoldsload'), which costs 2100 gas, or a warm storage access operation ('Gwarmaccess'), which costs 100 gas. Therefore, the gas efficiency of your contract can be significantly improved by adding a check that compares the new value with the current one before any storage update operation. If the values are the same, you can bypass the storage operation, thereby saving gas.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L92

92:     function setWhitelistedProposalCaller(
93:         string calldata sourceChain,
94:         address sourceCaller,
95:         bool whitelisted
96:     ) external override onlyOwner {
97:         whitelistedCallers[sourceChain][sourceCaller] = whitelisted;
98:         emit WhitelistedProposalCallerSet(sourceChain, sourceCaller, whitelisted);
99:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L107

107:     function setWhitelistedProposalSender(
108:         string calldata sourceChain,
109:         address sourceSender,
110:         bool whitelisted
111:     ) external override onlyOwner {
112:         whitelistedSenders[sourceChain][sourceSender] = whitelisted;
113:         emit WhitelistedProposalSenderSet(sourceChain, sourceSender, whitelisted);
114:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L32-L32

32:     function setup(bytes calldata params) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L78-L78

78:     function setup(bytes calldata data) external override onlyProxy {
79:         _setup(data);
80:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L31-L31

31:     function setup(bytes calldata setupParams) external {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L547-L547

547:     function setPaused(bool paused) external onlyOwner {
548:         _setPaused(paused);
549:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L49-L49

49:     function setup(bytes calldata params) external override onlyProxy {
50:         {
51:             address distributor_;
52:             address tokenManager_;
53:             string memory tokenName;
54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));
55:             _setDistributor(distributor_);
56:             tokenManager = tokenManager_;
57:             _setDomainTypeSignatureHash(tokenName);
58:             name = tokenName;
59:         }
60:         {
61:             uint256 mintAmount;
62:             address mintTo;
63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
64:             if (mintAmount > 0) {
65:                 _mint(mintTo, mintAmount);
66:             }
67:         }
68:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L171-L171

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator {
172:         _setFlowLimit(flowLimit);
173:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67-L67

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
68:         _setLiquidityPool(newLiquidityPool);
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L51-L51

51:     function setDistributor(address distr) external onlyDistributor {
52:         _setDistributor(distr);
53:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L51-L51

51:     function setOperator(address operator_) external onlyOperator {
52:         _setOperator(operator_);
53:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L103-L103

103:     function _setTimeLockEta(bytes32 hash, uint256 eta) private {
104:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash));
105: 
106:         assembly {
107:             sstore(key, eta)
108:         }
109:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L626-L626

626:     function _setTokenMintLimit(string memory symbol, uint256 limit) internal {
627:         _setUint(_getTokenMintLimitKey(symbol), limit);
628: 
629:         emit TokenMintLimitUpdated(symbol, limit);
630:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L632-L632

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {
633:         uint256 limit = tokenMintLimit(symbol);
634:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
635: 
636:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount);
637:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L639-L639

639:     function _setTokenType(string memory symbol, TokenType tokenType) internal {
640:         _setUint(_getTokenTypeKey(symbol), uint256(tokenType));
641:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L643-L643

643:     function _setTokenAddress(string memory symbol, address tokenAddress) internal {
644:         _setAddress(_getTokenAddressKey(symbol), tokenAddress);
645:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L647-L647

647:     function _setCommandExecuted(bytes32 commandId, bool executed) internal {
648:         _setBool(_getIsCommandExecutedKey(commandId), executed);
649:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L651-L651

651:     function _setContractCallApproved(
652:         bytes32 commandId,
653:         string memory sourceChain,
654:         string memory sourceAddress,
655:         address contractAddress,
656:         bytes32 payloadHash
657:     ) internal {
658:         _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true);
659:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L661-L661

661:     function _setContractCallApprovedWithMint(
662:         bytes32 commandId,
663:         string memory sourceChain,
664:         string memory sourceAddress,
665:         address contractAddress,
666:         bytes32 payloadHash,
667:         string memory symbol,
668:         uint256 amount
669:     ) internal {
670:         _setBool(
671:             _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount),
672:             true
673:         );
674:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L676-L676

676:     function _setImplementation(address newImplementation) internal {
677:         _setAddress(KEY_IMPLEMENTATION, newImplementation);
678:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L87-L87

87:     function _setup(bytes calldata data) internal virtual {}

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L555-L555

555:     function _setup(bytes calldata params) internal override {
556:         _setOperator(params.toAddress());
557:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L38-L38

38:     function _setTokenAddress(address tokenAddress_) internal {
39:         assembly {
40:             sstore(TOKEN_ADDRESS_SLOT, tokenAddress_)
41:         }
42:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L32-L32

32:     function _setup(bytes calldata params) internal override {
33:         
34:         (, address tokenAddress) = abi.decode(params, (bytes, address));
35:         _setTokenAddress(tokenAddress);
36:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L36-L36

36:     function _setup(bytes calldata params) internal override {
37:         
38:         (, address tokenAddress_, address liquidityPool_) = abi.decode(params, (bytes, address, address));
39:         _setTokenAddress(tokenAddress_);
40:         _setLiquidityPool(liquidityPool_);
41:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L47-L47

47:     function _setLiquidityPool(address liquidityPool_) internal {
48:         assembly {
49:             sstore(LIQUIDITY_POOL_SLOT, liquidityPool_)
50:         }
51:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L39-L39

39:     function _setDistributor(address distributor_) internal {
40:         assembly {
41:             sstore(DISTRIBUTOR_SLOT, distributor_)
42:         }
43:         emit DistributorChanged(distributor_);
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L34-L34

34:     function _setFlowLimit(uint256 flowLimit) internal {
35:         assembly {
36:             sstore(FLOW_LIMIT_SLOT, flowLimit)
37:         }
38:         emit FlowLimitSet(flowLimit);
39:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L39-L39

39:     function _setOperator(address operator_) internal {
40:         assembly {
41:             sstore(OPERATOR_SLOT, operator_)
42:         }
43:         emit OperatorChanged(operator_);
44:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L41-L41

41:     function _setPaused(bool paused) internal {
42:         assembly {
43:             sstore(PAUSE_SLOT, paused)
44:         }
45: 
46:         emit PausedSet(paused);
47:     }

[GAS-12] Use != 0 instead of > 0

Number of instances found

8

Resolution

Replace spotted instances with != 0 for uints as this uses less gas

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L634-L634

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {
633:         uint256 limit = tokenMintLimit(symbol);
634:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol); // <= FOUND
635: 
636:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount);
637:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L91-L91

88:     function _sendProposal(InterchainCalls.InterchainCall memory interchainCall) internal {
89:         bytes memory payload = abi.encode(msg.sender, interchainCall.calls);
90: 
91:         if (interchainCall.gas > 0) { // <= FOUND
92:             gasService.payNativeGasForContractCall{ value: interchainCall.gas }(
93:                 address(this),
94:                 interchainCall.destinationChain,
95:                 interchainCall.destinationContract,
96:                 payload,
97:                 msg.sender
98:             );
99:         }
100: 
101:         gateway.callContract(interchainCall.destinationChain, interchainCall.destinationContract, payload);
102:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L161-L161

156:     function _onTargetExecutionFailed(
157:         InterchainCalls.Call memory, 
158:         bytes memory result
159:     ) internal virtual {
160:         
161:         if (result.length > 0) { // <= FOUND
162:             
163:             assembly {
164:                 revert(add(32, result), mload(result))
165:             }
166:         } else {
167:             
168:             revert ProposalExecuteFailed();
169:         }
170:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L60-L60

52:     function upgrade(
53:         address newImplementation,
54:         bytes32 newImplementationCodeHash,
55:         bytes calldata params
56:     ) external override onlyOwner {
57:         if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation();
58:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();
59: 
60:         if (params.length > 0) { // <= FOUND
61:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params));
62: 
63:             if (!success) revert SetupFailed();
64:         }
65: 
66:         emit Upgraded(newImplementation);
67: 
68:         assembly {
69:             sstore(_IMPLEMENTATION_SLOT, newImplementation)
70:         }
71:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L519-L519

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused {
510:         bytes memory payload;
511:         if (metadata.length < 4) {
512:             payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount);
513:             _callContract(destinationChain, payload, msg.value, sourceAddress);
514:             emit TokenSent(tokenId, destinationChain, destinationAddress, amount);
515:             return;
516:         }
517:         uint32 version;
518:         (version, metadata) = _decodeMetadata(metadata);
519:         if (version > 0) revert InvalidMetadataVersion(version); // <= FOUND
520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata);
521:         _callContract(destinationChain, payload, msg.value, sourceAddress);
522:         emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata);
523:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L690-L690

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal {
679:         (
680:             ,
681:             bytes32 tokenId,
682:             string memory name,
683:             string memory symbol,
684:             uint8 decimals,
685:             bytes memory distributorBytes,
686:             bytes memory operatorBytes
687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));
688:         address tokenAddress = getStandardizedTokenAddress(tokenId);
689:         address tokenManagerAddress = getTokenManagerAddress(tokenId);
690:         address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress; // <= FOUND
691:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, 0, distributor);
692:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
693:         _deployTokenManager(
694:             tokenId,
695:             tokenManagerType,
696:             abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)
697:         );
698:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L714-L714

707:     function _callContract(
708:         string calldata destinationChain,
709:         bytes memory payload,
710:         uint256 gasValue,
711:         address refundTo
712:     ) internal {
713:         string memory destinationAddress = remoteAddressValidator.getRemoteAddress(destinationChain);
714:         if (gasValue > 0) { // <= FOUND
715:             gasService.payNativeGasForContractCall{ value: gasValue }(
716:                 address(this),
717:                 destinationChain,
718:                 destinationAddress,
719:                 payload,
720:                 refundTo
721:             );
722:         }
723:         gateway.callContract(destinationChain, destinationAddress, payload);
724:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L64-L64

49:     function setup(bytes calldata params) external override onlyProxy {
50:         {
51:             address distributor_;
52:             address tokenManager_;
53:             string memory tokenName;
54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));
55:             _setDistributor(distributor_);
56:             tokenManager = tokenManager_;
57:             _setDomainTypeSignatureHash(tokenName);
58:             name = tokenName;
59:         }
60:         {
61:             uint256 mintAmount;
62:             address mintTo;
63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
64:             if (mintAmount > 0) { // <= FOUND
65:                 _mint(mintTo, mintAmount);
66:             }
67:         }
68:     }

[GAS-13] Integer increments by one can be unchecked to save on gas fees

Number of instances found

14

Resolution

Using unchecked increments in Solidity can save on gas fees by bypassing built-in overflow checks, thus optimizing gas usage, but requires careful assessment of potential risks and edge cases to avoid unintended consequences.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L122-L124

119:     function getSignerVotesCount(bytes32 topic) external view override returns (uint256) {
120:         uint256 length = signers.accounts.length;
121:         uint256 voteCount;
122:         for (uint256 i; i < length; ++i) { // <= FOUND
123:             if (votingPerTopic[signerEpoch][topic].hasVoted[signers.accounts[i]]) {
124:                 voteCount++; // <= FOUND
125:             }
126:         }
127: 
128:         return voteCount;
129:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L153-L168

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
150:         uint256 length = signers.accounts.length;
151: 
152:         
153:         for (uint256 i; i < length; ++i) { // <= FOUND
154:             signers.isSigner[signers.accounts[i]] = false;
155:         }
156: 
157:         length = newAccounts.length;
158: 
159:         if (newThreshold > length) revert InvalidSigners();
160: 
161:         if (newThreshold == 0) revert InvalidSignerThreshold();
162: 
163:         ++signerEpoch; // <= FOUND
164: 
165:         signers.accounts = newAccounts;
166:         signers.threshold = newThreshold;
167: 
168:         for (uint256 i; i < length; ++i) { // <= FOUND
169:             address account = newAccounts[i];
170: 
171:             
172:             if (signers.isSigner[account]) revert DuplicateSigner(account);
173:             if (account == address(0)) revert InvalidSigners();
174: 
175:             signers.isSigner[account] = true;
176:         }
177: 
178:         emit SignersRotated(newAccounts, newThreshold);
179:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L269-L269

265:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {
266:         uint256 length = symbols.length;
267:         if (length != limits.length) revert InvalidSetMintLimitsParams();
268: 
269:         for (uint256 i; i < length; ++i) { // <= FOUND
270:             string memory symbol = symbols[i];
271:             uint256 limit = limits[i];
272: 
273:             if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol);
274: 
275:             _setTokenMintLimit(symbol, limit);
276:         }
277:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L343-L343

322:     function execute(bytes calldata input) external override {
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) { // <= FOUND
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L74-L74

73:     function _executeProposal(InterchainCalls.Call[] memory calls) internal {
74:         for (uint256 i = 0; i < calls.length; i++) { // <= FOUND
75:             InterchainCalls.Call memory call = calls[i];
76:             (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData);
77: 
78:             if (!success) {
79:                 _onTargetExecutionFailed(call, result);
80:             } else {
81:                 _onTargetExecuted(call, result);
82:             }
83:         }
84:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L537-L537

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {
535:         uint256 length = tokenIds.length;
536:         if (length != flowLimits.length) revert LengthMismatch();
537:         for (uint256 i; i < length; ++i) { // <= FOUND
538:             ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i]));
539:             tokenManager.setFlowLimit(flowLimits[i]);
540:         }
541:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L44-L44

40:     function _setup(bytes calldata params) internal override {
41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));
42:         uint256 length = trustedChainNames.length;
43:         if (length != trustedAddresses.length) revert LengthMismatch();
44:         for (uint256 i; i < length; ++i) { // <= FOUND
45:             addTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
46:         }
47:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L56-L56

54:     function _lowerCase(string memory s) internal pure returns (string memory) {
55:         uint256 length = bytes(s).length;
56:         for (uint256 i; i < length; i++) { // <= FOUND
57:             uint8 b = uint8(bytes(s)[i]);
58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32));
59:         }
60:         return s;
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L108-L108

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {
107:         uint256 length = chainNames.length;
108:         for (uint256 i; i < length; ++i) { // <= FOUND
109:             string calldata chainName = chainNames[i];
110:             supportedByGateway[chainName] = true;
111:             emit GatewaySupportedChainAdded(chainName);
112:         }
113:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L121-L121

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {
120:         uint256 length = chainNames.length;
121:         for (uint256 i; i < length; ++i) { // <= FOUND
122:             string calldata chainName = chainNames[i];
123:             supportedByGateway[chainName] = false;
124:             emit GatewaySupportedChainRemoved(chainName);
125:         }
126:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L24-L24

22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
23:         results = new bytes[](data.length);
24:         for (uint256 i = 0; i < data.length; ++i) { // <= FOUND
25:             (bool success, bytes memory result) = address(this).delegatecall(data[i]);
26: 
27:             if (!success) {
28:                 revert(string(result));
29:             }
30: 
31:             results[i] = result;
32:         }
33:     }

[GAS-14] Default bool values are manually reset

Number of instances found

8

Resolution

Using .delete is better than resetting a Solidity variable to its default value manually because it frees up storage space on the Ethereum blockchain, resulting in gas cost savings.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L57-L57

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners {
53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
54: 
55:         if (!multisigApprovals[proposalHash]) revert NotApproved();
56: 
57:         multisigApprovals[proposalHash] = false; // <= FOUND
58: 
59:         _call(target, callData, nativeValue);
60: 
61:         emit MultisigExecuted(proposalHash, target, callData, nativeValue);
62:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L102-L102

72:     function _processCommand(
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override {
79:         if (commandId > uint256(type(ServiceGovernanceCommand).max)) {
80:             revert InvalidCommand();
81:         }
82: 
83:         ServiceGovernanceCommand command = ServiceGovernanceCommand(commandId);
84:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
85: 
86:         if (command == ServiceGovernanceCommand.ScheduleTimeLockProposal) {
87:             eta = _scheduleTimeLock(proposalHash, eta);
88: 
89:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);
90:             return;
91:         } else if (command == ServiceGovernanceCommand.CancelTimeLockProposal) {
92:             _cancelTimeLock(proposalHash);
93: 
94:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
95:             return;
96:         } else if (command == ServiceGovernanceCommand.ApproveMultisigProposal) {
97:             multisigApprovals[proposalHash] = true;
98: 
99:             emit MultisigApproved(proposalHash, target, callData, nativeValue);
100:             return;
101:         } else if (command == ServiceGovernanceCommand.CancelMultisigApproval) {
102:             multisigApprovals[proposalHash] = false; // <= FOUND
103: 
104:             emit MultisigCancelled(proposalHash, target, callData, nativeValue);
105:             return;
106:         }
107:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L154

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal { // <= FOUND
150:         uint256 length = signers.accounts.length;
151: 
152:         
153:         for (uint256 i; i < length; ++i) {
154:             signers.isSigner[signers.accounts[i]] = false; // <= FOUND
155:         }
156: 
157:         length = newAccounts.length;
158: 
159:         if (newThreshold > length) revert InvalidSigners();
160: 
161:         if (newThreshold == 0) revert InvalidSignerThreshold();
162: 
163:         ++signerEpoch;
164: 
165:         signers.accounts = newAccounts;
166:         signers.threshold = newThreshold;
167: 
168:         for (uint256 i; i < length; ++i) {
169:             address account = newAccounts[i];
170: 
171:             
172:             if (signers.isSigner[account]) revert DuplicateSigner(account);
173:             if (account == address(0)) revert InvalidSigners();
174: 
175:             signers.isSigner[account] = true;
176:         }
177: 
178:         emit SignersRotated(newAccounts, newThreshold);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L364

322:     function execute(bytes calldata input) external override { // <= FOUND
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false; // <= FOUND
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId));
374: 
375:             if (success) emit Executed(commandId);
376:             else _setCommandExecuted(commandId, false);
377:         }
378:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L119-L123

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner { // <= FOUND
120:         uint256 length = chainNames.length;
121:         for (uint256 i; i < length; ++i) {
122:             string calldata chainName = chainNames[i];
123:             supportedByGateway[chainName] = false; // <= FOUND
124:             emit GatewaySupportedChainRemoved(chainName);
125:         }
126:     }

[GAS-15] <= or >= is more efficient than < or >

Number of instances found

1

Resolution

Make such found comparisons to the <=/>= equivalent when comparing against integer literals

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L511-L511

502:     function transmitSendToken(
503:         bytes32 tokenId,
504:         address sourceAddress,
505:         string calldata destinationChain,
506:         bytes memory destinationAddress,
507:         uint256 amount,
508:         bytes calldata metadata
509:     ) external payable onlyTokenManager(tokenId) notPaused {
510:         bytes memory payload;
511:         if (metadata.length < 4) { // <= FOUND
512:             payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount);
513:             _callContract(destinationChain, payload, msg.value, sourceAddress);
514:             emit TokenSent(tokenId, destinationChain, destinationAddress, amount);
515:             return;
516:         }
517:         uint32 version;
518:         (version, metadata) = _decodeMetadata(metadata);
519:         if (version > 0) revert InvalidMetadataVersion(version);
520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata);
521:         _callContract(destinationChain, payload, msg.value, sourceAddress);
522:         emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata);
523:     }

[GAS-16] State variables used within a function more than once should be cached to save gas

Number of instances found

34

Resolution

Cache such variables and perform operations on them, if operations include modifications to the state variable(s) then remember to equate the state variable to it's cached counterpart at the end

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L43-L66

43:     function interchainTransfer( // <= FOUND
44:         string calldata destinationChain,
45:         bytes calldata recipient,
46:         uint256 amount,
47:         bytes calldata metadata
48:     ) external payable {
49:         address sender = msg.sender;
50:         ITokenManager tokenManager = getTokenManager(); // <= FOUND
51:         
52: 
53: 
54:         if (tokenManagerRequiresApproval()) { // <= FOUND
55:             uint256 allowance_ = allowance[sender][address(tokenManager)]; // <= FOUND
56:             if (allowance_ != type(uint256).max) { // <= FOUND
57:                 if (allowance_ > type(uint256).max - amount) { // <= FOUND
58:                     allowance_ = type(uint256).max - amount; // <= FOUND
59:                 }
60: 
61:                 _approve(sender, address(tokenManager), allowance_ + amount); // <= FOUND
62:             }
63:         }
64: 
65:         
66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata); // <= FOUND
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L79-L104

79:     function interchainTransferFrom( // <= FOUND
80:         address sender,
81:         string calldata destinationChain,
82:         bytes calldata recipient,
83:         uint256 amount,
84:         bytes calldata metadata
85:     ) external payable {
86:         uint256 _allowance = allowance[sender][msg.sender];
87: 
88:         if (_allowance != type(uint256).max) { // <= FOUND
89:             _approve(sender, msg.sender, _allowance - amount);
90:         }
91: 
92:         ITokenManager tokenManager = getTokenManager(); // <= FOUND
93:         if (tokenManagerRequiresApproval()) { // <= FOUND
94:             uint256 allowance_ = allowance[sender][address(tokenManager)]; // <= FOUND
95:             if (allowance_ != type(uint256).max) { // <= FOUND
96:                 if (allowance_ > type(uint256).max - amount) { // <= FOUND
97:                     allowance_ = type(uint256).max - amount; // <= FOUND
98:                 }
99: 
100:                 _approve(sender, address(tokenManager), allowance_ + amount); // <= FOUND
101:             }
102:         }
103: 
104:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata); // <= FOUND
105:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L384-L417

384:     function deployToken(bytes calldata params, bytes32) external onlySelf { // <= FOUND
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode( // <= FOUND
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol); // <= FOUND
392: 
393:         if (tokenAddress == address(0)) {
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol)); // <= FOUND
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt) // <= FOUND
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol); // <= FOUND
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom); // <= FOUND
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);
409: 
410:             
411:             _setTokenType(symbol, TokenType.External); // <= FOUND
412:         }
413: 
414:         _setTokenAddress(symbol, tokenAddress); // <= FOUND
415:         _setTokenMintLimit(symbol, mintLimit); // <= FOUND
416: 
417:         emit TokenDeployed(symbol, tokenAddress); // <= FOUND
418:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L96-L103

96:     function sendToken( // <= FOUND
97:         string calldata destinationChain,
98:         string calldata destinationAddress,
99:         string calldata symbol, // <= FOUND
100:         uint256 amount
101:     ) external {
102:         _burnTokenFrom(msg.sender, symbol, amount); // <= FOUND
103:         emit TokenSent(msg.sender, destinationChain, destinationAddress, symbol, amount); // <= FOUND
104:     }

[GAS-17] Mappings used within a function more than once should be cached to save gas

Number of instances found

3

Resolution

Cache such mappings and perform operations on them, if operations include modifications to the mapping(s) then remember to equate the mapping to it's cached counterpart at the end

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L57

48:     function executeMultisigProposal( // <= FOUND
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners {
53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));
54: 
55:         if (!multisigApprovals[proposalHash]) revert NotApproved(); // <= FOUND
56: 
57:         multisigApprovals[proposalHash] = false; // <= FOUND
58: 
59:         _call(target, callData, nativeValue);
60: 
61:         emit MultisigExecuted(proposalHash, target, callData, nativeValue);
62:     }

[GAS-18] Use assembly to check for the zero address

Number of instances found

18

Resolution

Using assembly for address comparisons in Solidity can save gas because it allows for more direct access to the Ethereum Virtual Machine (EVM), reducing the overhead of higher-level operations. Solidity's high-level abstraction simplifies coding but can introduce additional gas costs. Using assembly for simple operations like address comparisons can be more gas-efficient.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L87-L100

87:     function _execute(
88:         string calldata sourceChain,
89:         string calldata sourceAddress,
90:         bytes calldata payload
91:     ) internal override {
92:         if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash)
93:             revert NotGovernance();
94: 
95:         (uint256 command, address target, bytes memory callData, uint256 nativeValue, uint256 eta) = abi.decode(
96:             payload,
97:             (uint256, address, bytes, uint256, uint256)
98:         );
99: 
100:         if (target == address(0)) revert InvalidTarget(); // <= FOUND
101: 
102:         _processCommand(command, target, callData, nativeValue, eta);
103:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L173

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
150:         uint256 length = signers.accounts.length;
151: 
152:         
153:         for (uint256 i; i < length; ++i) {
154:             signers.isSigner[signers.accounts[i]] = false;
155:         }
156: 
157:         length = newAccounts.length;
158: 
159:         if (newThreshold > length) revert InvalidSigners();
160: 
161:         if (newThreshold == 0) revert InvalidSignerThreshold();
162: 
163:         ++signerEpoch;
164: 
165:         signers.accounts = newAccounts;
166:         signers.threshold = newThreshold;
167: 
168:         for (uint256 i; i < length; ++i) {
169:             address account = newAccounts[i];
170: 
171:             
172:             if (signers.isSigner[account]) revert DuplicateSigner(account);
173:             if (account == address(0)) revert InvalidSigners(); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L253-L254

253:     function transferGovernance(address newGovernance) external override onlyGovernance {
254:         if (newGovernance == address(0)) revert InvalidGovernance(); // <= FOUND
255: 
256:         _transferGovernance(newGovernance);
257:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L259-L260

259:     function transferMintLimiter(address newMintLimiter) external override onlyMintLimiter {
260:         if (newMintLimiter == address(0)) revert InvalidMintLimiter(); // <= FOUND
261: 
262:         _transferMintLimiter(newMintLimiter);
263:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L265-L273

265:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {
266:         uint256 length = symbols.length;
267:         if (length != limits.length) revert InvalidSetMintLimitsParams();
268: 
269:         for (uint256 i; i < length; ++i) {
270:             string memory symbol = symbols[i];
271:             uint256 limit = limits[i];
272: 
273:             if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol); // <= FOUND
274: 
275:             _setTokenMintLimit(symbol, limit);
276:         }
277:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L306-L313

306:     function setup(bytes calldata params) external override {
307:         
308:         if (implementation() == address(0)) revert NotProxy(); // <= FOUND
309: 
310:         (address governance_, address mintLimiter_, bytes memory newOperatorsData) = abi.decode(params, (address, address, bytes));
311: 
312:         if (governance_ != address(0)) _transferGovernance(governance_); // <= FOUND
313:         if (mintLimiter_ != address(0)) _transferMintLimiter(mintLimiter_); // <= FOUND
314: 
315:         if (newOperatorsData.length != 0) {
316:             IAxelarAuth(AUTH_MODULE).transferOperatorship(newOperatorsData);
317: 
318:             emit OperatorshipTransferred(newOperatorsData);
319:         }
320:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L384-L393

384:     function deployToken(bytes calldata params, bytes32) external onlySelf {
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol); // <= FOUND
392: 
393:         if (tokenAddress == address(0)) { // <= FOUND
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol));
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt)
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol);
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom);
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L426-L431

426:     function burnToken(bytes calldata params, bytes32) external onlySelf {
427:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));
428: 
429:         address tokenAddress = tokenAddresses(symbol);
430: 
431:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); // <= FOUND
432: 
433:         if (_getTokenType(symbol) == TokenType.External) {
434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode)));
435: 
436:             if (_hasCode(depositHandlerAddress)) return;
437: 
438:             DepositHandler depositHandler = new DepositHandler{ salt: salt }();
439: 
440:             (bool success, bytes memory returnData) = depositHandler.execute(
441:                 tokenAddress,
442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler)))
443:             );
444: 
445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
446: 
447:             
448:             depositHandler.destroy(address(this));
449:         } else {
450:             IBurnableMintableCappedERC20(tokenAddress).burn(salt);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L511-L518

511:     function _mintToken(
512:         string memory symbol,
513:         address account,
514:         uint256 amount
515:     ) internal {
516:         address tokenAddress = tokenAddresses(symbol);
517: 
518:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); // <= FOUND
519: 
520:         _setTokenMintAmount(symbol, tokenMintAmount(symbol) + amount);
521: 
522:         if (_getTokenType(symbol) == TokenType.External) {
523:             IERC20(tokenAddress).safeTransfer(account, amount);
524:         } else {
525:             IBurnableMintableCappedERC20(tokenAddress).mint(account, amount);
526:         }
527:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L529-L536

529:     function _burnTokenFrom(
530:         address sender,
531:         string memory symbol,
532:         uint256 amount
533:     ) internal {
534:         address tokenAddress = tokenAddresses(symbol);
535: 
536:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol); // <= FOUND
537:         if (amount == 0) revert InvalidAmount();
538: 
539:         TokenType tokenType = _getTokenType(symbol);
540: 
541:         if (tokenType == TokenType.External) {
542:             IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount);
543:         } else if (tokenType == TokenType.InternalBurnableFrom) {
544:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount));
545:         } else {
546:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount);
547:             IBurnableMintableCappedERC20(tokenAddress).burn(bytes32(0));
548:         }
549:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L51-L60

51:     function deploy(bytes32 salt, bytes memory bytecode) internal returns (address deployed) {
52:         deployed = deployedAddress(address(this), salt);
53: 
54:         if (deployed.isContract()) revert AlreadyDeployed();
55:         if (bytecode.length == 0) revert EmptyBytecode();
56: 
57:         
58:         CreateDeployer deployer = new CreateDeployer{ salt: salt }();
59: 
60:         if (address(deployer) == address(0)) revert DeployFailed(); // <= FOUND
61: 
62:         deployer.deploy(bytecode);
63:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L37-L39

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_) {
38:         implementation_ = _finalImplementation();
39:         if (implementation_ == address(0)) { // <= FOUND
40:             implementation_ = super.implementation();
41:         }
42:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L48-L49

48:     function isFinal() public view returns (bool) {
49:         return _finalImplementation() != address(0); // <= FOUND
50:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L57-L63

57:     function _finalImplementation() internal view virtual returns (address implementation_) {
58:         
59: 
60: 
61:         implementation_ = Create3.deployedAddress(address(this), FINAL_IMPLEMENTATION_SALT);
62: 
63:         if (implementation_.code.length == 0) implementation_ = address(0); // <= FOUND
64:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L565

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType)
560:         internal
561:         pure
562:         returns (address implementation)
563:     {
564:         implementation = implementaions[uint256(tokenManagerType)];
565:         if (implementation == address(0)) revert ZeroAddress(); // <= FOUND
566:         if (ITokenManager(implementation).implementationType() != uint256(tokenManagerType)) revert InvalidTokenManagerImplementation();
567:     }

[GAS-19] Use storage instead of memory for structs/arrays

Number of instances found

7

Resolution

In Solidity, using storage instead of memory for structs and arrays in function parameters can result in gas savings. When data is passed as a storage reference, the function operates directly on the original data stored in contract storage, without needing to create a copy. Conversely, when memory is used, a copy of the data is created, which incurs additional gas costs. However, it's essential to note that while using storage references can save gas, it also means that any changes made to the data inside the function will modify the original data stored in the contract, which may not always be the desired behavior. Therefore, developers should carefully consider the implications of using storage versus memory based on the specific requirements of their functions.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L142-L142

142:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L149

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L73-L73

73:     function _executeProposal(InterchainCalls.Call[] memory calls) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L559-L559

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType) // <= FOUND
560:         internal
561:         pure
562:         returns (address implementation)
563:     

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L88-L88

88:     function _sendProposal(InterchainCalls.InterchainCall memory interchainCall) internal  // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L157-L157

156:     function _onTargetExecutionFailed(
157:         InterchainCalls.Call memory,  // <= FOUND
158:         bytes memory result
159:     ) internal virtual 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L178-L178

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual  // <= FOUND

[GAS-20] Divisions which do not divide by -X cannot overflow or overflow so such operations can be unchecked to save gas

Number of instances found

6

Resolution

Make such found divisions are unchecked when ensured it is safe to do so

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L203-L203

202:     function tokenMintAmount(string memory symbol) public view override returns (uint256) {
203:         return getUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours)); // <= FOUND
204:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L636-L636

632:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {
633:         uint256 limit = tokenMintLimit(symbol);
634:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
635: 
636:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount); // <= FOUND
637:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L64-L64

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount) {
64:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
65:         uint256 slot = _getFlowOutSlot(epoch);
66:         assembly {
67:             flowOutAmount := sload(slot)
68:         }
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L76-L76

75:     function getFlowInAmount() external view returns (uint256 flowInAmount) {
76:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
77:         uint256 slot = _getFlowInSlot(epoch);
78:         assembly {
79:             flowInAmount := sload(slot)
80:         }
81:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L114-L114

111:     function _addFlowOut(uint256 flowOutAmount) internal {
112:         uint256 flowLimit = getFlowLimit();
113:         if (flowLimit == 0) return;
114:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
115:         uint256 slotToAdd = _getFlowOutSlot(epoch);
116:         uint256 slotToCompare = _getFlowInSlot(epoch);
117:         _addFlow(flowLimit, slotToAdd, slotToCompare, flowOutAmount);
118:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L127-L127

124:     function _addFlowIn(uint256 flowInAmount) internal {
125:         uint256 flowLimit = getFlowLimit();
126:         if (flowLimit == 0) return;
127:         uint256 epoch = block.timestamp / EPOCH_TIME; // <= FOUND
128:         uint256 slotToAdd = _getFlowInSlot(epoch);
129:         uint256 slotToCompare = _getFlowOutSlot(epoch);
130:         _addFlow(flowLimit, slotToAdd, slotToCompare, flowInAmount);
131:     }

[GAS-21] State variables which are not modified within functions should be set as constants or immutable for values set at deployment

Number of instances found

3

Resolution

Set state variables listed below as constant or immutable for values set at deployment. Ensure it is safe to do so

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L21-L21

21: string public governanceChain;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L22-L22

22: string public governanceAddress;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L14-L14

14: ExpressCallHandler,

[GAS-22] Use assembly to calculate hashes to save gas

Number of instances found

42

Resolution

Using assembly to calculate hashes can save 80 gas per instance

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L73-L73

68:     function executeProposal(
69:         address target,
70:         bytes calldata callData,
71:         uint256 nativeValue
72:     ) external payable {
73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
74: 
75:         _finalizeTimeLock(proposalHash);
76:         _call(target, callData, nativeValue);
77: 
78:         emit ProposalExecuted(proposalHash, target, callData, nativeValue, block.timestamp);
79:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L92-L92

87:     function _execute(
88:         string calldata sourceChain,
89:         string calldata sourceAddress,
90:         bytes calldata payload
91:     ) internal override {
92:         if (keccak256(bytes(sourceChain)) != governanceChainHash || keccak256(bytes(sourceAddress)) != governanceAddressHash) // <= FOUND
93:             revert NotGovernance();
94: 
95:         (uint256 command, address target, bytes memory callData, uint256 nativeValue, uint256 eta) = abi.decode(
96:             payload,
97:             (uint256, address, bytes, uint256, uint256)
98:         );
99: 
100:         if (target == address(0)) revert InvalidTarget();
101: 
102:         _processCommand(command, target, callData, nativeValue, eta);
103:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L148-L148

143:     function _getProposalHash(
144:         address target,
145:         bytes memory callData,
146:         uint256 nativeValue
147:     ) internal pure returns (bytes32) {
148:         return keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
149:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L53-L53

48:     function executeMultisigProposal(
49:         address target,
50:         bytes calldata callData,
51:         uint256 nativeValue
52:     ) external payable onlySigners {
53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
54: 
55:         if (!multisigApprovals[proposalHash]) revert NotApproved();
56: 
57:         multisigApprovals[proposalHash] = false;
58: 
59:         _call(target, callData, nativeValue);
60: 
61:         emit MultisigExecuted(proposalHash, target, callData, nativeValue);
62:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L84-L84

72:     function _processCommand(
73:         uint256 commandId,
74:         address target,
75:         bytes memory callData,
76:         uint256 nativeValue,
77:         uint256 eta
78:     ) internal override {
79:         if (commandId > uint256(type(ServiceGovernanceCommand).max)) {
80:             revert InvalidCommand();
81:         }
82: 
83:         ServiceGovernanceCommand command = ServiceGovernanceCommand(commandId);
84:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND
85: 
86:         if (command == ServiceGovernanceCommand.ScheduleTimeLockProposal) {
87:             eta = _scheduleTimeLock(proposalHash, eta);
88: 
89:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);
90:             return;
91:         } else if (command == ServiceGovernanceCommand.CancelTimeLockProposal) {
92:             _cancelTimeLock(proposalHash);
93: 
94:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
95:             return;
96:         } else if (command == ServiceGovernanceCommand.ApproveMultisigProposal) {
97:             multisigApprovals[proposalHash] = true;
98: 
99:             emit MultisigApproved(proposalHash, target, callData, nativeValue);
100:             return;
101:         } else if (command == ServiceGovernanceCommand.CancelMultisigApproval) {
102:             multisigApprovals[proposalHash] = false;
103: 
104:             emit MultisigCancelled(proposalHash, target, callData, nativeValue);
105:             return;
106:         }
107:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L111-L111

106:     function callContract(
107:         string calldata destinationChain,
108:         string calldata destinationContractAddress,
109:         bytes calldata payload
110:     ) external {
111:         emit ContractCall(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload); // <= FOUND
112:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L122-L122

114:     function callContractWithToken(
115:         string calldata destinationChain,
116:         string calldata destinationContractAddress,
117:         bytes calldata payload,
118:         string calldata symbol,
119:         uint256 amount
120:     ) external {
121:         _burnTokenFrom(msg.sender, symbol, amount);
122:         emit ContractCallWithToken(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload, symbol, amount); // <= FOUND
123:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L246-L246

245:     function contractId() public pure returns (bytes32) {
246:         return keccak256('axelar-gateway'); // <= FOUND
247:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L325-L349

322:     function execute(bytes calldata input) external override {
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data)); // <= FOUND
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i])); // <= FOUND
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (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#L395-L395

384:     function deployToken(bytes calldata params, bytes32) external onlySelf {
385:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(
386:             params,
387:             (string, string, uint8, uint256, address, uint256)
388:         );
389: 
390:         
391:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol);
392: 
393:         if (tokenAddress == address(0)) {
394:             
395:             bytes32 salt = keccak256(abi.encodePacked(symbol)); // <= FOUND
396: 
397:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(
398:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt)
399:             );
400: 
401:             if (!success) revert TokenDeployFailed(symbol);
402: 
403:             tokenAddress = abi.decode(data, (address));
404: 
405:             _setTokenType(symbol, TokenType.InternalBurnableFrom);
406:         } else {
407:             
408:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);
409: 
410:             
411:             _setTokenType(symbol, TokenType.External);
412:         }
413: 
414:         _setTokenAddress(symbol, tokenAddress);
415:         _setTokenMintLimit(symbol, mintLimit);
416: 
417:         emit TokenDeployed(symbol, tokenAddress);
418:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L434-L434

426:     function burnToken(bytes calldata params, bytes32) external onlySelf {
427:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));
428: 
429:         address tokenAddress = tokenAddresses(symbol);
430: 
431:         if (tokenAddress == address(0)) revert TokenDoesNotExist(symbol);
432: 
433:         if (_getTokenType(symbol) == TokenType.External) {
434:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode))); // <= FOUND
435: 
436:             if (_hasCode(depositHandlerAddress)) return;
437: 
438:             DepositHandler depositHandler = new DepositHandler{ salt: salt }();
439: 
440:             (bool success, bytes memory returnData) = depositHandler.execute(
441:                 tokenAddress,
442:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler)))
443:             );
444: 
445:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);
446: 
447:             
448:             depositHandler.destroy(address(this));
449:         } else {
450:             IBurnableMintableCappedERC20(tokenAddress).burn(salt);
451:         }
452:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L556-L556

555:     function _getTokenMintLimitKey(string memory symbol) internal pure returns (bytes32) {
556:         return keccak256(abi.encodePacked(PREFIX_TOKEN_MINT_LIMIT, symbol)); // <= FOUND
557:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L561-L561

559:     function _getTokenMintAmountKey(string memory symbol, uint256 day) internal pure returns (bytes32) {
560:         
561:         return keccak256(abi.encode(PREFIX_TOKEN_MINT_AMOUNT, symbol, day)); // <= FOUND
562:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L565-L565

564:     function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) {
565:         return keccak256(abi.encodePacked(PREFIX_TOKEN_TYPE, symbol)); // <= FOUND
566:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L569-L569

568:     function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {
569:         return keccak256(abi.encodePacked(PREFIX_TOKEN_ADDRESS, symbol)); // <= FOUND
570:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L573-L573

572:     function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {
573:         return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId)); // <= FOUND
574:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L583-L583

576:     function _getIsContractCallApprovedKey(
577:         bytes32 commandId,
578:         string memory sourceChain,
579:         string memory sourceAddress,
580:         address contractAddress,
581:         bytes32 payloadHash
582:     ) internal pure returns (bytes32) {
583:         return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); // <= FOUND
584:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L596-L596

586:     function _getIsContractCallApprovedWithMintKey(
587:         bytes32 commandId,
588:         string memory sourceChain,
589:         string memory sourceAddress,
590:         address contractAddress,
591:         bytes32 payloadHash,
592:         string memory symbol,
593:         uint256 amount
594:     ) internal pure returns (bytes32) {
595:         return
596:             keccak256( // <= FOUND
597:                 abi.encode(
598:                     PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT,
599:                     commandId,
600:                     sourceChain,
601:                     sourceAddress,
602:                     contractAddress,
603:                     payloadHash,
604:                     symbol,
605:                     amount
606:                 )
607:             );
608:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L615-L615

614:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {
615:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash))))); // <= FOUND
616:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L66-L66

41:     function _execute(
42:         string calldata sourceChain,
43:         string calldata sourceAddress,
44:         bytes calldata payload
45:     ) internal override {
46:         _beforeProposalExecuted(sourceChain, sourceAddress, payload);
47: 
48:         
49:         if (!whitelistedSenders[sourceChain][StringToAddress.toAddress(sourceAddress)]) {
50:             revert NotWhitelistedSourceAddress();
51:         }
52: 
53:         
54:         (address interchainProposalCaller, InterchainCalls.Call[] memory calls) = abi.decode(payload, (address, InterchainCalls.Call[]));
55: 
56:         
57:         if (!whitelistedCallers[sourceChain][interchainProposalCaller]) {
58:             revert NotWhitelistedCaller();
59:         }
60: 
61:         
62:         _executeProposal(calls);
63: 
64:         _onProposalExecuted(sourceChain, sourceAddress, interchainProposalCaller, payload);
65: 
66:         emit ProposalExecuted(keccak256(abi.encode(sourceChain, sourceAddress, interchainProposalCaller, payload))); // <= FOUND
67:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L25-L25

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {
25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt))); // <= FOUND
26:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L47-L47

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) {
47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt))); // <= FOUND
48: 
49:         
50:         (bool success, ) = deployedAddress_.call(init);
51:         if (!success) revert FailedInit();
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L63-L72

58:     function deployedAddress(
59:         bytes calldata bytecode,
60:         address sender,
61:         bytes32 salt
62:     ) external view returns (address deployedAddress_) {
63:         bytes32 newSalt = keccak256(abi.encode(sender, salt)); // <= FOUND
64:         deployedAddress_ = address(
65:             uint160(
66:                 uint256(
67:                     keccak256( // <= FOUND
68:                         abi.encodePacked(
69:                             hex'ff',
70:                             address(this),
71:                             newSalt,
72:                             keccak256(bytecode)  // <= FOUND
73:                         )
74:                     )
75:                 )
76:             )
77:         );
78:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L30-L33

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {
30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); // <= FOUND
31:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
32: 
33:         emit Deployed(keccak256(bytecode), salt, deployedAddress_); // <= FOUND
34:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L54-L60

49:     function deployAndInit(
50:         bytes memory bytecode,
51:         bytes32 salt,
52:         bytes calldata init
53:     ) external returns (address deployedAddress_) {
54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); // <= FOUND
55:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
56: 
57:         (bool success, ) = deployedAddress_.call(init);
58:         if (!success) revert FailedInit();
59: 
60:         emit Deployed(keccak256(bytecode), salt, deployedAddress_); // <= FOUND
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L68-L68

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) {
68:         bytes32 deploySalt = keccak256(abi.encode(sender, salt)); // <= FOUND
69:         return Create3.deployedAddress(address(this), deploySalt);
70:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L72-L74

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
72:         address deployer = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', sender, salt, DEPLOYER_BYTECODE_HASH))))); // <= FOUND
73: 
74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01'))))); // <= FOUND
75:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L203-L203

202:     function getCanonicalTokenId(address tokenAddress) public view returns (bytes32 tokenId) {
203:         tokenId = keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_ID, chainNameHash, tokenAddress)); // <= FOUND
204:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L214-L214

213:     function getCustomTokenId(address sender, bytes32 salt) public pure returns (bytes32 tokenId) {
214:         tokenId = keccak256(abi.encode(PREFIX_CUSTOM_TOKEN_ID, sender, salt)); // <= FOUND
215:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L828-L828

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt) {
828:         return keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_SALT, tokenId)); // <= FOUND
829:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L71-L71

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {
70:         string memory sourceAddressLC = _lowerCase(sourceAddress);
71:         bytes32 sourceAddressHash = keccak256(bytes(sourceAddressLC)); // <= FOUND
72:         if (sourceAddressHash == interchainTokenServiceAddressHash) {
73:             return true;
74:         }
75:         return sourceAddressHash == remoteAddressHashes[sourceChain];
76:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L86-L86

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {
84:         if (bytes(chain).length == 0) revert ZeroStringLength();
85:         if (bytes(addr).length == 0) revert ZeroStringLength();
86:         remoteAddressHashes[chain] = keccak256(bytes(_lowerCase(addr))); // <= FOUND
87:         remoteAddresses[chain] = addr;
88:         emit TrustedAddressAdded(chain, addr);
89:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L32-L32

26:     function _getExpressReceiveTokenSlot(
27:         bytes32 tokenId,
28:         address destinationAddress,
29:         uint256 amount,
30:         bytes32 commandId
31:     ) internal pure returns (uint256 slot) {
32:         slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId))); // <= FOUND
33:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L56-L56

46:     function _getExpressReceiveTokenWithDataSlot(
47:         bytes32 tokenId,
48:         string memory sourceChain,
49:         bytes memory sourceAddress,
50:         address destinationAddress,
51:         uint256 amount,
52:         bytes memory data,
53:         bytes32 commandId
54:     ) internal pure returns (uint256 slot) {
55:         slot = uint256(
56:             keccak256( // <= FOUND
57:                 abi.encode(
58:                     PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA,
59:                     tokenId,
60:                     sourceChain,
61:                     sourceAddress,
62:                     destinationAddress,
63:                     amount,
64:                     data,
65:                     commandId
66:                 )
67:             )
68:         );
69:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L47-L47

46:     function _getFlowOutSlot(uint256 epoch) internal pure returns (uint256 slot) {
47:         slot = uint256(keccak256(abi.encode(PREFIX_FLOW_OUT_AMOUNT, epoch))); // <= FOUND
48:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L56-L56

55:     function _getFlowInSlot(uint256 epoch) internal pure returns (uint256 slot) {
56:         slot = uint256(keccak256(abi.encode(PREFIX_FLOW_IN_AMOUNT, epoch))); // <= FOUND
57:     }

[GAS-23] Redundant else statement

Number of instances found

1

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L223-L223

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) { // <= FOUND
224:         
225:         
226:         if (TokenManagerType(tokenManagerType) == TokenManagerType.LOCK_UNLOCK) {
227:             return implementationLockUnlock;
228:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.MINT_BURN) {
229:             return implementationMintBurn;
230:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.LIQUIDITY_POOL) {
231:             return implementationLiquidityPool;
232:         }
233:     }

[GAS-24] Unbounded Gas Consumption Risk Due to External Call Recipients

Number of instances found

4

Resolution

In the context of Solidity, external function calls without a specified gas limit present a significant risk. The callee contract has the potential to consume all the gas allocated to the transaction, causing an undesired revert and disrupt the function's execution. To mitigate this, it's recommended to explicitly set a gas limit when performing external calls using addr.call{gas: }. This limits the gas forwarded to the callee, preventing potential pitfalls and offering better control over transaction execution.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L322-L373

322:     function execute(bytes calldata input) external override { // <= FOUND
323:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));
324: 
325:         bytes32 messageHash = ECDSA.toEthSignedMessageHash(keccak256(data));
326: 
327:         
328:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);
329: 
330:         uint256 chainId;
331:         bytes32[] memory commandIds;
332:         string[] memory commands;
333:         bytes[] memory params;
334: 
335:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));
336: 
337:         if (chainId != block.chainid) revert InvalidChainId();
338: 
339:         uint256 commandsLength = commandIds.length;
340: 
341:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();
342: 
343:         for (uint256 i; i < commandsLength; ++i) {
344:             bytes32 commandId = commandIds[i];
345: 
346:             if (isCommandExecuted(commandId)) continue; 
347: 
348:             bytes4 commandSelector;
349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));
350: 
351:             if (commandHash == SELECTOR_DEPLOY_TOKEN) {
352:                 commandSelector = AxelarGateway.deployToken.selector;
353:             } else if (commandHash == SELECTOR_MINT_TOKEN) {
354:                 commandSelector = AxelarGateway.mintToken.selector;
355:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL) {
356:                 commandSelector = AxelarGateway.approveContractCall.selector;
357:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {
358:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;
359:             } else if (commandHash == SELECTOR_BURN_TOKEN) {
360:                 commandSelector = AxelarGateway.burnToken.selector;
361:             } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
362:                 if (!allowOperatorshipTransfer) continue;
363: 
364:                 allowOperatorshipTransfer = false;
365:                 commandSelector = AxelarGateway.transferOperatorship.selector;
366:             } else {
367:                 continue; 
368:             }
369: 
370:             
371:             _setCommandExecuted(commandId, true);
372: 
373:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId)); // <= FOUND
374: 
375:             if (success) emit Executed(commandId);
376:             else _setCommandExecuted(commandId, false);
377:         }
378:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L50-L50

42:     function deployAndInit(
43:         bytes memory bytecode,
44:         bytes32 salt,
45:         bytes calldata init
46:     ) external returns (address deployedAddress_) {
47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));
48: 
49:         
50:         (bool success, ) = deployedAddress_.call(init); // <= FOUND
51:         if (!success) revert FailedInit();
52:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L57-L57

49:     function deployAndInit(
50:         bytes memory bytecode,
51:         bytes32 salt,
52:         bytes calldata init
53:     ) external returns (address deployedAddress_) {
54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));
55:         deployedAddress_ = Create3.deploy(deploySalt, bytecode);
56: 
57:         (bool success, ) = deployedAddress_.call(init); // <= FOUND
58:         if (!success) revert FailedInit();
59: 
60:         emit Deployed(keccak256(bytecode), salt, deployedAddress_);
61:     }

[GAS-25] Consider activating via-ir for deploying

Number of instances found

73

Resolution

The Solidity compiler's Intermediate Representation (IR) based code generator, which can be activated using --via-ir on the command line or {"viaIR": true} in the options, serves a dual purpose. Firstly, it boosts the transparency and audibility of code generation, which enhances developers' comprehension and control over the contract's final bytecode. Secondly, it enables more sophisticated optimization passes that span multiple functions, thereby potentially leading to more efficient bytecode.

It's important to note that using the IR-based code generator may lengthen compile times due to the extra optimization steps. Therefore, it's advised to test your contract with and without this option enabled to measure the performance and gas cost implications. If the IR-based code generator significantly enhances your contract's performance or reduces gas costs, consider using the --via-ir flag during deployment. This way, you can leverage more advanced compiler optimizations without hindering your development workflow.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Proxy } from '../../gmp-sdk/upgradable/Proxy.sol';
6: 
7: /**
8:  * @title RemoteAddressValidatorProxy
9:  * @dev Proxy contract for the RemoteAddressValidator contract. Inherits from the Proxy contract.
10:  */
11: contract RemoteAddressValidatorProxy is Proxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
13: 
14:     /**
15:      * @dev Constructs the RemoteAddressValidatorProxy contract.
16:      * @param implementationAddress Address of the RemoteAddressValidator implementation
17:      * @param owner Address of the owner of the proxy
18:      * @param params The params to be passed to the _setup function of the implementation.
19:      */
20:     constructor(
21:         address implementationAddress,
22:         address owner,
23:         bytes memory params
24:     ) Proxy(implementationAddress, owner, params) {}
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/libraries/AddressBytesUtils.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title AddressBytesUtils
7:  * @dev This library provides utility functions to convert between `address` and `bytes`.
8:  */
9: library AddressBytesUtils {
10:     error InvalidBytesLength(bytes bytesAddress);
11: 
12:     /**
13:      * @dev Converts a bytes address to an address type.
14:      * @param bytesAddress The bytes representation of an address
15:      * @return addr The converted address
16:      */
17:     function toAddress(bytes memory bytesAddress) internal pure returns (address addr) {
18:         if (bytesAddress.length != 20) revert InvalidBytesLength(bytesAddress);
19: 
20:         assembly {
21:             addr := mload(add(bytesAddress, 20))
22:         }
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IOperatable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IOperatable {
6:     error NotOperator();
7: 
8:     event OperatorChanged(address operator);
9: 
10:     /**
11:      * @notice Get the address of the operator
12:      * @return operator_ of the operator
13:      */
14:     function operator() external view returns (address operator_);
15: 
16:     /**
17:      * @notice Change the operator of the contract
18:      * @dev Can only be called by the current operator
19:      * @param operator_ The address of the new operator
20:      */
21:     function setOperator(address operator_) external;
22: }
23: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: import { IRemoteAddressValidator } from '../interfaces/IRemoteAddressValidator.sol';
5: import { AddressToString } from '../../gmp-sdk/util/AddressString.sol';
6: import { Upgradable } from '../../gmp-sdk/upgradable/Upgradable.sol';
7: 
8: /**
9:  * @title RemoteAddressValidator
10:  * @dev Manages and validates remote addresses, keeps track of addresses supported by the Axelar gateway contract
11:  */
12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
13:     using AddressToString for address;
14: 
15:     mapping(string => bytes32) public remoteAddressHashes;
16:     mapping(string => string) public remoteAddresses;
17:     address public immutable interchainTokenServiceAddress;
18:     bytes32 public immutable interchainTokenServiceAddressHash;
19:     mapping(string => bool) public supportedByGateway;
20: 
21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
22: 
23:     /**
24:      * @dev Constructs the RemoteAddressValidator contract, both array parameters must be equal in length
25:      * @param _interchainTokenServiceAddress Address of the interchain token service

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IImplementation.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IImplementation {
6:     error NotProxy();
7: }
8: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManagerType.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title ITokenManagerType
7:  * @notice A simple interface that defines all the token manager types
8:  */
9: interface ITokenManagerType {
10:     enum TokenManagerType {
11:         LOCK_UNLOCK,
12:         MINT_BURN,
13:         LIQUIDITY_POOL
14:     }
15: }
16: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IInterchainProposalExecutor {
6:     // An event emitted when the proposal caller is whitelisted
7:     event WhitelistedProposalCallerSet(string indexed sourceChain, address indexed sourceCaller, bool whitelisted);
8: 
9:     // An event emitted when the proposal sender is whitelisted
10:     event WhitelistedProposalSenderSet(string indexed sourceChain, address indexed sourceSender, bool whitelisted);
11: 
12:     event ProposalExecuted(bytes32 indexed payloadHash);
13: 
14:     // An error emitted when the proposal execution failed
15:     error ProposalExecuteFailed();
16: 
17:     // An error emitted when the proposal caller is not whitelisted
18:     error NotWhitelistedCaller();
19: 
20:     // An error emitted when the proposal sender is not whitelisted
21:     error NotWhitelistedSourceAddress();
22: 
23:     /**
24:      * @notice set the whitelisted status of a proposal sender which is the `InterchainProposalSender` contract address on the source chain
25:      * @param sourceChain The source chain

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from '../interfaces/IProxy.sol';
6: import { IFinalProxy } from '../interfaces/IFinalProxy.sol';
7: import { Create3 } from '../deploy/Create3.sol';
8: import { BaseProxy } from './BaseProxy.sol';
9: import { Proxy } from './Proxy.sol';
10: 
11: /**
12:  * @title FinalProxy Contract
13:  * @notice The FinalProxy contract is a proxy that can be upgraded to a final implementation
14:  * that uses less gas than regular proxy calls. It inherits from the Proxy contract and implements
15:  * the IFinalProxy interface.
16:  */
17: contract FinalProxy is Proxy, IFinalProxy {
18:     bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation');
19: 
20:     /**
21:      * @dev Constructs a FinalProxy contract with a given implementation address, owner, and setup parameters.
22:      * @param implementationAddress The address of the implementation contract
23:      * @param owner The owner of the proxy contract
24:      * @param setupParams Parameters to setup the implementation contract
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IFinalProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from './IProxy.sol';
6: 
7: // General interface for upgradable contracts
8: interface IFinalProxy is IProxy {
9:     function isFinal() external view returns (bool);
10: 
11:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) external returns (address);
12: }
13: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/ICaller.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface ICaller {
6:     error InsufficientBalance();
7:     error ExecutionFailed();
8: }
9: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ContractAddress } from '../util/ContractAddress.sol';
6: 
7: error AlreadyDeployed();
8: error EmptyBytecode();
9: error DeployFailed();
10: 
11: /**
12:  * @title CreateDeployer Contract
13:  * @notice This contract deploys new contracts using the `CREATE` opcode and is used as part of
14:  * the `Create3` deployment method.
15:  */
16: contract CreateDeployer {
17:     /**
18:      * @dev Deploys a new contract with the specified bytecode using the CREATE opcode.
19:      * @param bytecode The bytecode of the contract to be deployed
20:      */
21:     function deploy(bytes memory bytecode) external {
22:         address deployed;
23: 
24:         assembly {
25:             deployed := create(0, add(bytecode, 32), mload(bytecode))

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenMintBurn.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { StandardizedToken } from './StandardizedToken.sol';
6: 
7: contract StandardizedTokenMintBurn is StandardizedToken {
8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
9:         return false;
10:     }
11: }
12: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IUpgradable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IOwnable } from './IOwnable.sol';
6: 
7: // General interface for upgradable contracts
8: interface IUpgradable is IOwnable {
9:     error InvalidCodeHash();
10:     error InvalidImplementation();
11:     error SetupFailed();
12:     error NotProxy();
13: 
14:     event Upgraded(address indexed newImplementation);
15: 
16:     function implementation() external view returns (address);
17: 
18:     function upgrade(
19:         address newImplementation,
20:         bytes32 newImplementationCodeHash,
21:         bytes calldata params
22:     ) external;
23: 
24:     function setup(bytes calldata data) external;
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManager.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ITokenManagerType } from './ITokenManagerType.sol';
6: import { IOperatable } from './IOperatable.sol';
7: import { IFlowLimit } from './IFlowLimit.sol';
8: import { IImplementation } from './IImplementation.sol';
9: 
10: /**
11:  * @title ITokenManager
12:  * @notice This contract is responsible for handling tokens before initiating a cross chain token transfer, or after receiving one.
13:  */
14: interface ITokenManager is ITokenManagerType, IOperatable, IFlowLimit, IImplementation {
15:     error TokenLinkerZeroAddress();
16:     error NotService();
17:     error TakeTokenFailed();
18:     error GiveTokenFailed();
19:     error NotToken();
20: 
21:     /**
22:      * @notice A function that should return the address of the token.
23:      * Must be overridden in the inheriting contract.
24:      * @return address address of the token.
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Upgradable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IUpgradable } from '../interfaces/IUpgradable.sol';
6: import { Ownable } from '../util/Ownable.sol';
7: 
8: /**
9:  * @title Upgradable Contract
10:  * @notice This contract provides an interface for upgradable smart contracts and includes the functionality to perform upgrades.
11:  */
12: abstract contract Upgradable is Ownable, IUpgradable {
13:     // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
15:     address internal immutable implementationAddress;
16: 
17:     /**
18:      * @notice Constructor sets the implementation address to the address of the contract itself
19:      * @dev This is used in the onlyProxy modifier to prevent certain functions from being called directly
20:      * on the implementation contract itself
21:      */
22:     constructor() {
23:         implementationAddress = address(this);
24:     }
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: contract ConstAddressDeployer {
6:     error EmptyBytecode();
7:     error FailedDeploy();
8:     error FailedInit();
9: 
10:     event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);
11: 
12:     /**
13:      * @dev Deploys a contract using `CREATE2`. The address where the contract
14:      * will be deployed can be known in advance via {deployedAddress}.
15:      *
16:      * The bytecode for a contract can be obtained from Solidity with
17:      * `type(contractName).creationCode`.
18:      *
19:      * Requirements:
20:      *
21:      * - `bytecode` must not be empty.
22:      * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
23:      */
24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {
25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Multicall.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IMulticall } from '../interfaces/IMulticall.sol';
6: 
7: /**
8:  * @title Multicall
9:  * @notice This contract is a multi-functional smart contract which allows for multiple
10:  * contract calls in a single transaction.
11:  */
12: contract Multicall is IMulticall {
13:     error MulticallFailed(bytes err);
14: 
15:     /**
16:      * @notice Performs multiple delegate calls and returns the results of all calls as an array
17:      * @dev This function requires that the contract has sufficient balance for the delegate calls.
18:      * If any of the calls fail, the function will revert with the failure message.
19:      * @param data An array of encoded function calls
20:      * @return results An bytes array with the return data of each function call
21:      */
22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
23:         results = new bytes[](data.length);
24:         for (uint256 i = 0; i < data.length; ++i) {
25:             (bool success, bytes memory result) = address(this).delegatecall(data[i]);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainToken.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IERC20 } from '../../gmp-sdk/interfaces/IERC20.sol';
6: 
7: /**
8:  * @dev Interface of the ERC20 standard as defined in the EIP.
9:  */
10: interface IInterchainToken is IERC20 {
11:     /**
12:      * @notice Implementation of the interchainTransfer method
13:      * @dev We chose to either pass `metadata` as raw data on a remote contract call, or, if no data is passed, just do a transfer.
14:      * A different implementation could have `metadata` that tells this function which function to use or that it is used for anything else as well.
15:      * @param destinationChain The destination chain identifier.
16:      * @param recipient The bytes representation of the address of the recipient.
17:      * @param amount The amount of token to be transfered.
18:      * @param metadata Either empty, to just facilitate an interchain transfer, or the data can be passed for an interchain contract call with transfer as per semantics defined by the token service.
19:      */
20:     function interchainTransfer(
21:         string calldata destinationChain,
22:         bytes calldata recipient,
23:         uint256 amount,
24:         bytes calldata metadata
25:     ) external payable;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IMultisig.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IMultisigBase } from './IMultisigBase.sol';
6: import { ICaller } from './ICaller.sol';
7: 
8: /**
9:  * @title IMultisig Interface
10:  * @notice This interface extends IMultisigBase by adding an execute function for multisignature transactions.
11:  */
12: interface IMultisig is ICaller, IMultisigBase {
13:     /**
14:      * @notice Executes a function on an external target.
15:      * @param target The address of the target to call
16:      * @param callData The call data to be sent
17:      * @param nativeValue The native token value to be sent (e.g., ETH)
18:      */
19:     function execute(
20:         address target,
21:         bytes calldata callData,
22:         uint256 nativeValue
23:     ) external payable;
24: }
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/StandardizedTokenDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol';
6: 
7: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol';
8: 
9: import { StandardizedTokenProxy } from '../proxies/StandardizedTokenProxy.sol';
10: 
11: /**
12:  * @title StandardizedTokenDeployer
13:  * @notice This contract is used to deploy new instances of the StandardizedTokenProxy contract.
14:  */
15: contract StandardizedTokenDeployer is IStandardizedTokenDeployer {
16:     Create3Deployer public immutable deployer;
17:     address public immutable implementationMintBurnAddress;
18:     address public immutable implementationLockUnlockAddress;
19: 
20:     /**
21:      * @notice Constructor for the StandardizedTokenDeployer contract
22:      * @param deployer_ Address of the Create3Deployer contract
23:      * @param implementationLockUnlockAddress_ Address of the StandardizedTokenLockUnlock contract
24:      * @param implementationMintBurnAddress_ Address of the StandardizedTokenMintBurn contract
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/Multisig.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IMultisig } from '../interfaces/IMultisig.sol';
6: import { MultisigBase } from '../auth/MultisigBase.sol';
7: import { Caller } from '../util/Caller.sol';
8: 
9: /**
10:  * @title Multisig Contract
11:  * @notice An extension of MultisigBase that can call functions on any contract.
12:  */
13: contract Multisig is Caller, MultisigBase, IMultisig {
14:     /**
15:      * @notice Contract constructor
16:      * @dev Sets the initial list of signers and corresponding threshold.
17:      * @param accounts Address array of the signers
18:      * @param threshold Signature threshold required to validate a transaction
19:      */
20:     constructor(address[] memory accounts, uint256 threshold) MultisigBase(accounts, threshold) {}
21: 
22:     /**
23:      * @notice Executes an external contract call.
24:      * @dev Calls a target address with specified calldata and optionally sends value.
25:      * This function is protected by the onlySigners modifier.

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IInterchainTokenService.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarGateway } from '../../gmp-sdk/interfaces/IAxelarGateway.sol';
6: import { IAxelarExecutable } from '../../gmp-sdk/interfaces/IAxelarExecutable.sol';
7: 
8: import { IExpressCallHandler } from './IExpressCallHandler.sol';
9: import { ITokenManagerDeployer } from './ITokenManagerDeployer.sol';
10: import { ITokenManagerType } from './ITokenManagerType.sol';
11: import { IPausable } from './IPausable.sol';
12: import { IMulticall } from './IMulticall.sol';
13: 
14: interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAxelarExecutable, IPausable, IMulticall {
15:     // more generic error
16:     error ZeroAddress();
17:     error LengthMismatch();
18:     error InvalidTokenManagerImplementation();
19:     error NotRemoteService();
20:     error TokenManagerDoesNotExist(bytes32 tokenId);
21:     error NotTokenManager();
22:     error ExecuteWithInterchainTokenFailed(address contractAddress);
23:     error NotCanonicalTokenManager();
24:     error GatewayToken();
25:     error TokenManagerDeploymentFailed();

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedTokenLockUnlock.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { StandardizedToken } from './StandardizedToken.sol';
6: 
7: contract StandardizedTokenLockUnlock is StandardizedToken {
8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
9:         return true;
10:     }
11: }
12: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarGateway } from '../gmp-sdk/interfaces/IAxelarGateway.sol';
6: import { IAxelarGasService } from '../gmp-sdk/interfaces/IAxelarGasService.sol';
7: import { IInterchainProposalSender } from './interfaces/IInterchainProposalSender.sol';
8: import { InterchainCalls } from './lib/InterchainCalls.sol';
9: 
10: /**
11:  * @title InterchainProposalSender
12:  * @dev This contract is responsible for facilitating the execution of approved proposals across multiple chains.
13:  * It achieves this by working in conjunction with the AxelarGateway and AxelarGasService contracts.
14:  *
15:  * The contract allows for the sending of a single proposal to multiple destination chains. This is achieved
16:  * through the `sendProposals` function, which takes in arrays representing the destination chains,
17:  * destination contracts, fees, target contracts, amounts of tokens to send, function signatures, and encoded
18:  * function arguments.
19:  *
20:  * Each destination chain has a unique corresponding set of contracts to call, amounts of native tokens to send,
21:  * function signatures to call, and encoded function arguments. This information is provided in a 2D array where
22:  * the first dimension is the destination chain index, and the second dimension corresponds to the specific details
23:  * for each chain.
24:  *
25:  * In addition, the contract also allows for the execution of a single proposal at a single destination chain

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/lib/InterchainCalls.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: library InterchainCalls {
6:     /**
7:      * @dev An interchain call to be executed at the destination chain
8:      * @param destinationChain destination chain
9:      * @param destinationContract destination contract
10:      * @param gas The amount of native token to transfer to the target contract as gas payment for the interchain call
11:      * @param calls An array of calls to be executed at the destination chain
12:      */
13:     struct InterchainCall {
14:         string destinationChain;
15:         string destinationContract;
16:         uint256 gas;
17:         Call[] calls;
18:     }
19: 
20:     /**
21:      * @dev A call to be executed at the destination chain
22:      * @param target The address of the contract to call
23:      * @param value The amount of native token to transfer to the target contract
24:      * @param callData The data to pass to the target contract
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Pausable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IPausable } from '../interfaces/IPausable.sol';
6: 
7: /**
8:  * @title Pausable
9:  * @notice This contract provides a mechanism to halt the execution of specific functions
10:  * if a pause condition is activated.
11:  */
12: contract Pausable is IPausable {
13:     // uint256(keccak256('paused')) - 1
14:     uint256 internal constant PAUSE_SLOT = 0xee35723ac350a69d2a92d3703f17439cbaadf2f093a21ba5bf5f1a53eb2a14d8;
15: 
16:     /**
17:      * @notice A modifier that throws a Paused custom error if the contract is paused
18:      * @dev This modifier should be used with functions that can be paused
19:      */
20:     modifier notPaused() {
21:         if (isPaused()) revert Paused();
22:         _;
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/FlowLimit.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IFlowLimit } from '../interfaces/IFlowLimit.sol';
6: 
7: /**
8:  * @title FlowLimit
9:  * @notice Implements flow limit logic for interchain token transfers.
10:  * @dev This contract implements low-level assembly for optimization purposes.
11:  */
12: contract FlowLimit is IFlowLimit {
13:     // uint256(keccak256('flow-limit')) - 1
14:     uint256 internal constant FLOW_LIMIT_SLOT = 0x201b7a0b7c19aaddc4ce9579b7df8d2db123805861bc7763627f13e04d8af42f;
15:     uint256 internal constant PREFIX_FLOW_OUT_AMOUNT = uint256(keccak256('prefix-flow-out-amount'));
16:     uint256 internal constant PREFIX_FLOW_IN_AMOUNT = uint256(keccak256('prefix-flow-in-amount'));
17: 
18:     uint256 internal constant EPOCH_TIME = 6 hours;
19: 
20:     /**
21:      * @notice Returns the current flow limit
22:      * @return flowLimit The current flow limit value
23:      */
24:     function getFlowLimit() public view returns (uint256 flowLimit) {
25:         assembly {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/TokenManager.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ITokenManager } from '../interfaces/ITokenManager.sol';
6: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';
7: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol';
8: 
9: import { Operatable } from '../utils/Operatable.sol';
10: import { FlowLimit } from '../utils/FlowLimit.sol';
11: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol';
12: import { Implementation } from '../utils/Implementation.sol';
13: 
14: /**
15:  * @title The main functionality of TokenManagers.
16:  * @notice This contract is responsible for handling tokens before initiating a cross chain token transfer, or after receiving one.
17:  */
18: abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implementation {
19:     using AddressBytesUtils for bytes;
20: 
21:     IInterchainTokenService public immutable interchainTokenService;
22: 
23:     /**
24:      * @notice Constructs the TokenManager contract.
25:      * @param interchainTokenService_ The address of the interchain token service

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IMulticall.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title IMulticall
7:  * @notice This contract is a multi-functional smart contract which allows for multiple
8:  * contract calls in a single transaction.
9:  */
10: interface IMulticall {
11:     /**
12:      * @notice Performs multiple delegate calls and returns the results of all calls as an array
13:      * @dev This function requires that the contract has sufficient balance for the delegate calls.
14:      * If any of the calls fail, the function will revert with the failure message.
15:      * @param data An array of encoded function calls
16:      * @return results An bytes array with the return data of each function call
17:      */
18:     function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
19: }
20: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Create3 } from './Create3.sol';
6: 
7: /**
8:  * @title Create3Deployer Contract
9:  * @notice This contract is responsible for deploying and initializing new contracts using the CREATE3 technique
10:  * which ensures that only the sender address and salt influence the deployed address, not the contract bytecode.
11:  */
12: contract Create3Deployer {
13:     error FailedInit();
14: 
15:     event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);
16: 
17:     /**
18:      * @dev Deploys a contract using `CREATE3`. The address where the contract
19:      * will be deployed can be known in advance via {deployedAddress}.
20:      *
21:      * The bytecode for a contract can be obtained from Solidity with
22:      * `type(contractName).creationCode`.
23:      *
24:      * Requirements:
25:      *

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: pragma solidity ^0.8.0;
3: 
4: import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';
5: import { StringToAddress } from '../gmp-sdk/util/AddressString.sol';
6: import { AxelarExecutable } from '../gmp-sdk/executable/AxelarExecutable.sol';
7: import { IInterchainProposalExecutor } from './interfaces/IInterchainProposalExecutor.sol';
8: import { InterchainCalls } from './lib/InterchainCalls.sol';
9: 
10: /**
11:  * @title InterchainProposalExecutor
12:  * @dev This contract is intended to be the destination contract for `InterchainProposalSender` contract.
13:  * The proposal will be finally executed from this contract on the destination chain.
14:  *
15:  * The contract maintains whitelists for proposal senders and proposal callers. Proposal senders
16:  * are InterchainProposalSender contracts at the source chain and proposal callers are contracts
17:  * that call the InterchainProposalSender at the source chain.
18:  * For most governance system, the proposal caller should be the Timelock contract.
19:  *
20:  * This contract is abstract and some of its functions need to be implemented in a derived contract.
21:  */
22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {
23:     // Whitelisted proposal callers. The proposal caller is the contract that calls the `InterchainProposalSender` at the source chain.
24:     mapping(string => mapping(address => bool)) public whitelistedCallers;
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FixedProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from '../interfaces/IProxy.sol';
6: 
7: /**
8:  * @title FixedProxy Contract
9:  * @notice The FixedProxy is a type of Proxy contract with a fixed implementation that cannot be updated.
10:  * It implements the IProxy interface. Any function calls to this contract will be forwarded to the implementation contract.
11:  */
12: contract FixedProxy is IProxy {
13:     /**
14:      * @dev The immutable address of the implementation contract.
15:      * This address is set in the constructor and cannot be updated after.
16:      */
17:     address public immutable implementation;
18: 
19:     /**
20:      * @dev Constructs a FixedProxy contract with the given implementation address.
21:      * @param implementationAddress The address of the implementation contract
22:      */
23:     constructor(address implementationAddress) {
24:         implementation = implementationAddress;
25:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol';
6: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol';
7: 
8: import { SafeTokenTransferFrom, SafeTokenTransfer } from '../../../gmp-sdk/util/SafeTransfer.sol';
9: 
10: /**
11:  * @title TokenManagerLockUnlock
12:  * @notice This contract is an implementation of TokenManager that locks and unlocks a specific token on behalf of the interchain token service.
13:  * @dev This contract extends TokenManagerAddressStorage and provides implementation for its abstract methods.
14:  * It uses the Axelar SDK to safely transfer tokens.
15:  */
16: contract TokenManagerLockUnlock is TokenManagerAddressStorage {
17:     /**
18:      * @dev Constructs an instance of TokenManagerLockUnlock. Calls the constructor
19:      * of TokenManagerAddressStorage which calls the constructor of TokenManager.
20:      * @param interchainTokenService_ The address of the interchain token service contract
21:      */
22:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}
23: 
24:     function implementationType() external pure returns (uint256) {
25:         return 0;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Distributable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IDistributable } from '../interfaces/IDistributable.sol';
6: 
7: /**
8:  * @title Distributable Contract
9:  * @dev A contract module which provides a basic access control mechanism, where
10:  * there is an account (a distributor) that can be granted exclusive access to
11:  * specific functions. This module is used through inheritance.
12:  */
13: contract Distributable is IDistributable {
14:     // uint256(keccak256('distributor')) - 1
15:     uint256 internal constant DISTRIBUTOR_SLOT = 0x71c5a35e45a25c49e8f747acd4bcb869814b3d104c492d2554f4c46e12371f56;
16: 
17:     /**
18:      * @dev Throws a NotDistributor custom eror if called by any account other than the distributor.
19:      */
20:     modifier onlyDistributor() {
21:         if (distributor() != msg.sender) revert NotDistributor();
22:         _;
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Implementation.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IImplementation } from '../interfaces/IImplementation.sol';
6: 
7: /**
8:  * @title Implementation
9:  * @notice This contract serves as a base for other contracts and enforces a proxy-first access restriction.
10:  * @dev Derived contracts must implement the setup function.
11:  */
12: abstract contract Implementation is IImplementation {
13:     address private immutable implementationAddress;
14: 
15:     /**
16:      * @dev Contract constructor that sets the implementation address to the address of this contract.
17:      */
18:     constructor() {
19:         implementationAddress = address(this);
20:     }
21: 
22:     /**
23:      * @dev Modifier to require the caller to be the proxy contract.
24:      * Reverts if the caller is the current contract (i.e., the implementation contract itself).
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/TokenManagerDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol';
6: 
7: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol';
8: 
9: import { TokenManagerProxy } from '../proxies/TokenManagerProxy.sol';
10: 
11: /**
12:  * @title TokenManagerDeployer
13:  * @notice This contract is used to deploy new instances of the TokenManagerProxy contract.
14:  */
15: contract TokenManagerDeployer is ITokenManagerDeployer {
16:     Create3Deployer public immutable deployer;
17: 
18:     /**
19:      * @notice Constructor for the TokenManagerDeployer contract
20:      * @param deployer_ Address of the Create3Deployer contract
21:      */
22:     constructor(address deployer_) {
23:         if (deployer_ == address(0)) revert AddressZero();
24:         deployer = Create3Deployer(deployer_);
25:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ITimeLock } from '../interfaces/ITimeLock.sol';
6: 
7: /**
8:  * @title TimeLock
9:  * @dev A contract that enables function execution after a certain time has passed.
10:  * Implements the {ITimeLock} interface.
11:  */
12: contract TimeLock is ITimeLock {
13:     bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock');
14: 
15:     uint256 internal immutable _minimumTimeLockDelay;
16: 
17:     /**
18:      * @notice The constructor for the TimeLock.
19:      * @param minimumTimeDelay The minimum time delay (in secs) that must pass for the TimeLock to be executed
20:      */
21:     constructor(uint256 minimumTimeDelay) {
22:         _minimumTimeLockDelay = minimumTimeDelay;
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedToken.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInterchainToken } from './IInterchainToken.sol';
6: import { IDistributable } from './IDistributable.sol';
7: import { IERC20BurnableMintable } from './IERC20BurnableMintable.sol';
8: 
9: /**
10:  * @title StandardizedToken
11:  * @notice This contract implements a standardized token which extends InterchainToken functionality.
12:  * This contract also inherits Distributable and Implementation logic.
13:  */
14: interface IStandardizedToken is IInterchainToken, IDistributable, IERC20BurnableMintable {
15:     /**
16:      * @notice Returns the contract id, which a proxy can check to ensure no false implementation was used.
17:      */
18:     function contractId() external view returns (bytes32);
19: 
20:     /**
21:      * @notice Called by the proxy to setup itself.
22:      * @dev This should be hidden by the proxy.
23:      * @param params the data to be used for the initialization.
24:      */
25:     function setup(bytes calldata params) external;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IFlowLimit.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IFlowLimit {
6:     error FlowLimitExceeded();
7: 
8:     event FlowLimitSet(uint256 flowLimit);
9: 
10:     /**
11:      * @notice Returns the current flow limit
12:      * @return flowLimit The current flow limit value
13:      */
14:     function getFlowLimit() external view returns (uint256 flowLimit);
15: 
16:     /**
17:      * @notice Returns the current flow out amount
18:      * @return flowOutAmount The current flow out amount
19:      */
20:     function getFlowOutAmount() external view returns (uint256 flowOutAmount);
21: 
22:     /**
23:      * @notice Returns the current flow in amount
24:      * @return flowInAmount The current flow in amount
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IAxelarServiceGovernance.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInterchainGovernance } from './IInterchainGovernance.sol';
6: import { IMultisigBase } from './IMultisigBase.sol';
7: 
8: /**
9:  * @title IAxelarServiceGovernance Interface
10:  * @dev This interface extends IInterchainGovernance and IMultisigBase for multisig proposal actions
11:  */
12: interface IAxelarServiceGovernance is IMultisigBase, IInterchainGovernance {
13:     error NotApproved();
14: 
15:     event MultisigApproved(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue);
16:     event MultisigCancelled(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue);
17:     event MultisigExecuted(bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue);
18: 
19:     /**
20:      * @notice Executes a multisig proposal
21:      * @param targetContract The target address the proposal will call
22:      * @param callData The data that encodes the function and arguments to call on the target contract
23:      */
24:     function executeMultisigProposal(
25:         address targetContract,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol';
6: import { TimeLock } from '../../gmp-sdk/util/TimeLock.sol';
7: import { IInterchainGovernance } from '../interfaces/IInterchainGovernance.sol';
8: import { Caller } from '../util/Caller.sol';
9: 
10: /**
11:  * @title Interchain Governance contract
12:  * @notice This contract handles cross-chain governance actions. It includes functionality
13:  * to create, cancel, and execute governance proposals.
14:  */
15: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance {
16:     enum GovernanceCommand {
17:         ScheduleTimeLockProposal,
18:         CancelTimeLockProposal
19:     }
20: 
21:     string public governanceChain;
22:     string public governanceAddress;
23:     bytes32 public immutable governanceChainHash;
24:     bytes32 public immutable governanceAddressHash;
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IInterchainGovernance.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarExecutable } from '../../gmp-sdk/interfaces/IAxelarExecutable.sol';
6: import { ICaller } from './ICaller.sol';
7: 
8: /**
9:  * @title IInterchainGovernance Interface
10:  * @notice This interface extends IAxelarExecutable for interchain governance mechanisms.
11:  */
12: interface IInterchainGovernance is IAxelarExecutable, ICaller {
13:     error NotGovernance();
14:     error InvalidCommand();
15:     error InvalidTarget();
16:     error TokenNotSupported();
17: 
18:     event ProposalScheduled(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed eta);
19:     event ProposalCancelled(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed eta);
20:     event ProposalExecuted(bytes32 indexed proposalHash, address indexed target, bytes callData, uint256 value, uint256 indexed timestamp);
21: 
22:     /**
23:      * @notice Returns the name of the governance chain.
24:      * @return string The name of the governance chain
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IInitProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from './IProxy.sol';
6: 
7: // General interface for upgradable contracts
8: interface IInitProxy is IProxy {
9:     function init(
10:         address implementationAddress,
11:         address newOwner,
12:         bytes memory params
13:     ) external;
14: }
15: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IMultisigBase } from '../interfaces/IMultisigBase.sol';
6: 
7: /**
8:  * @title MultisigBase Contract
9:  * @notice This contract implements a custom multisignature wallet where transactions must be confirmed by a
10:  * threshold of signers. The signers and threshold may be updated every `epoch`.
11:  */
12: contract MultisigBase is IMultisigBase {
13:     struct Voting {
14:         uint256 voteCount;
15:         mapping(address => bool) hasVoted;
16:     }
17: 
18:     struct Signers {
19:         address[] accounts;
20:         uint256 threshold;
21:         mapping(address => bool) isSigner;
22:     }
23: 
24:     Signers public signers;
25:     uint256 public signerEpoch;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInitProxy } from '../interfaces/IInitProxy.sol';
6: import { IUpgradable } from '../interfaces/IUpgradable.sol';
7: import { BaseProxy } from './BaseProxy.sol';
8: 
9: /**
10:  * @title InitProxy Contract
11:  * @notice A proxy contract that can be initialized to use a specified implementation and owner. Inherits from BaseProxy
12:  * and implements the IInitProxy interface.
13:  * @dev This proxy is constructed empty and then later initialized with the implementation contract address, new owner address,
14:  * and any optional setup parameters.
15:  */
16: contract InitProxy is BaseProxy, IInitProxy {
17:     /**
18:      * @dev Initializes the contract and sets the caller as the owner of the contract.
19:      */
20:     constructor() {
21:         assembly {
22:             sstore(_OWNER_SLOT, caller())
23:         }
24:     }
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { InterchainCalls } from '../lib/InterchainCalls.sol';
6: 
7: interface IInterchainProposalSender {
8:     // An error emitted when the given gas is invalid
9:     error InvalidFee();
10: 
11:     /**
12:      * @dev Broadcast the proposal to be executed at multiple destination chains
13:      * @param calls An array of calls to be executed at the destination chain
14:      */
15:     function sendProposals(InterchainCalls.InterchainCall[] memory calls) external payable;
16: 
17:     /**
18:      * @dev Broadcast the proposal to be executed at single destination chain
19:      * @param destinationChain destination chain
20:      * @param destinationContract destination contract
21:      * @param calls An array of calls to be executed at the destination chain
22:      */
23:     function sendProposal(
24:         string calldata destinationChain,
25:         string calldata destinationContract,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedTokenProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title StandardizedTokenProxy
7:  * @dev Proxy contract for StandardizedToken contracts. Inherits from FixedProxy and implements IStandardizedTokenProxy.
8:  */
9: interface IStandardizedTokenProxy {
10:     /**
11:      * @notice Returns the contract id, which a proxy can check to ensure no false implementation was used.
12:      */
13:     function contractId() external view returns (bytes32);
14: }
15: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IRemoteAddressValidator.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title IRemoteAddressValidator
7:  * @dev Manages and validates remote addresses, keeps track of addresses supported by the Axelar gateway contract
8:  */
9: interface IRemoteAddressValidator {
10:     error ZeroAddress();
11:     error LengthMismatch();
12:     error ZeroStringLength();
13: 
14:     event TrustedAddressAdded(string souceChain, string sourceAddress);
15:     event TrustedAddressRemoved(string souceChain);
16:     event GatewaySupportedChainAdded(string chain);
17:     event GatewaySupportedChainRemoved(string chain);
18: 
19:     /**
20:      * @dev Validates that the sender is a valid interchain token service address
21:      * @param sourceChain Source chain of the transaction
22:      * @param sourceAddress Source address of the transaction
23:      * @return bool true if the sender is validated, false otherwise
24:      */
25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarGateway } from '../../gmp-sdk/interfaces/IAxelarGateway.sol';
6: import { IAxelarGasService } from '../../gmp-sdk/interfaces/IAxelarGasService.sol';
7: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol';
8: import { SafeTokenTransferFrom } from '../../gmp-sdk/util/SafeTransfer.sol';
9: import { IERC20 } from '../../gmp-sdk/interfaces/IERC20.sol';
10: 
11: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';
12: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol';
13: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol';
14: import { IRemoteAddressValidator } from '../interfaces/IRemoteAddressValidator.sol';
15: import { IInterchainTokenExpressExecutable } from '../interfaces/IInterchainTokenExpressExecutable.sol';
16: import { ITokenManager } from '../interfaces/ITokenManager.sol';
17: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol';
18: import { IERC20Named } from '../interfaces/IERC20Named.sol';
19: 
20: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol';
21: import { StringToBytes32, Bytes32ToString } from '../../gmp-sdk/util/Bytes32String.sol';
22: 
23: import { Upgradable } from '../../gmp-sdk/upgradable/Upgradable.sol';
24: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol';
25: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.9;
4: 
5: import { SafeTokenCall, SafeTokenTransfer, SafeTokenTransferFrom } from '../gmp-sdk/util/SafeTransfer.sol';
6: import { IERC20 } from '../gmp-sdk/interfaces/IERC20.sol';
7: import { IAxelarGateway } from './interfaces/IAxelarGateway.sol';
8: import { IGovernable } from './interfaces/IGovernable.sol';
9: import { IAxelarAuth } from './interfaces/IAxelarAuth.sol';
10: import { IBurnableMintableCappedERC20 } from './interfaces/IBurnableMintableCappedERC20.sol';
11: import { ITokenDeployer } from './interfaces/ITokenDeployer.sol';
12: 
13: import { ECDSA } from './ECDSA.sol';
14: import { DepositHandler } from './DepositHandler.sol';
15: import { AdminMultisigBase } from './AdminMultisigBase.sol';
16: 
17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase {
18:     using SafeTokenCall for IERC20;
19:     using SafeTokenTransfer for IERC20;
20:     using SafeTokenTransferFrom for IERC20;
21: 
22:     error InvalidImplementation();
23: 
24:     enum TokenType {
25:         InternalBurnable,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManagerDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol';
6: 
7: /**
8:  * @title ITokenManagerDeployer
9:  * @notice This contract is used to deploy new instances of the TokenManagerProxy contract.
10:  */
11: interface ITokenManagerDeployer {
12:     error AddressZero();
13:     error TokenManagerDeploymentFailed();
14: 
15:     /**
16:      * @notice Getter for the Create3Deployer.
17:      */
18:     function deployer() external view returns (Create3Deployer);
19: 
20:     /**
21:      * @notice Deploys a new instance of the TokenManagerProxy contract
22:      * @param tokenId The unique identifier for the token
23:      * @param implementationType Token manager implementation type
24:      * @param params Additional parameters used in the setup of the token manager
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerMintBurn.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol';
6: import { IERC20BurnableMintable } from '../../interfaces/IERC20BurnableMintable.sol';
7: 
8: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol';
9: import { SafeTokenCall } from '../../../gmp-sdk/util/SafeTransfer.sol';
10: 
11: /**
12:  * @title TokenManagerMintBurn
13:  * @notice This contract is an implementation of TokenManager that mints and burns a specific token on behalf of the interchain token service.
14:  * @dev This contract extends TokenManagerAddressStorage and provides implementation for its abstract methods.
15:  * It uses the Axelar SDK to safely transfer tokens.
16:  */
17: contract TokenManagerMintBurn is TokenManagerAddressStorage {
18:     /**
19:      * @dev Constructs an instance of TokenManagerMintBurn. Calls the constructor
20:      * of TokenManagerAddressStorage which calls the constructor of TokenManager.
21:      * @param interchainTokenService_ The address of the interchain token service contract
22:      */
23:     constructor(address interchainTokenService_) TokenManagerAddressStorage(interchainTokenService_) {}
24: 
25:     function implementationType() external pure returns (uint256) {

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/Operatable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IOperatable } from '../interfaces/IOperatable.sol';
6: 
7: /**
8:  * @title Operatable Contract
9:  * @dev A contract module which provides a basic access control mechanism, where
10:  * there is an account (an operator) that can be granted exclusive access to
11:  * specific functions. This module is used through inheritance.
12:  */
13: contract Operatable is IOperatable {
14:     // uint256(keccak256('operator')) - 1
15:     uint256 internal constant OPERATOR_SLOT = 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d7;
16: 
17:     /**
18:      * @dev Throws a NotOperator custom error if called by any account other than the operator.
19:      */
20:     modifier onlyOperator() {
21:         if (operator() != msg.sender) revert NotOperator();
22:         _;
23:     }
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/ITimeLock.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title ITimeLock
7:  * @dev Interface for a TimeLock that enables function execution after a certain time has passed.
8:  */
9: interface ITimeLock {
10:     error InvalidTimeLockHash();
11:     error TimeLockAlreadyScheduled();
12:     error TimeLockNotReady();
13: 
14:     /**
15:      * @notice Returns a minimum time delay at which the TimeLock may be scheduled.
16:      * @return uint Minimum scheduling delay time (in secs) from the current block timestamp
17:      */
18:     function minimumTimeLockDelay() external view returns (uint256);
19: 
20:     /**
21:      * @notice Returns the timestamp after which the TimeLock may be executed.
22:      * @param hash The hash of the timelock
23:      * @return uint The timestamp after which the timelock with the given hash can be executed
24:      */
25:     function getTimeLock(bytes32 hash) external view returns (uint256);

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/TokenManagerProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';
6: import { ITokenManagerProxy } from '../interfaces/ITokenManagerProxy.sol';
7: 
8: /**
9:  * @title TokenManagerProxy
10:  * @dev This contract is a proxy for token manager contracts. It implements ITokenManagerProxy and
11:  * inherits from FixedProxy from the gmp sdk repo
12:  */
13: contract TokenManagerProxy is ITokenManagerProxy {
14:     IInterchainTokenService public immutable interchainTokenServiceAddress;
15:     uint256 public immutable implementationType;
16:     bytes32 public immutable tokenId;
17: 
18:     /**
19:      * @dev Constructs the TokenManagerProxy contract.
20:      * @param interchainTokenServiceAddress_ The address of the interchain token service
21:      * @param implementationType_ The token manager type
22:      * @param tokenId_ The identifier for the token
23:      * @param params The initialization parameters for the token manager contract
24:      */
25:     constructor(

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token/InterchainToken.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IInterchainToken } from '../interfaces/IInterchainToken.sol';
6: import { ITokenManager } from '../interfaces/ITokenManager.sol';
7: import { ERC20 } from '../token-implementations/ERC20.sol';
8: 
9: /**
10:  * @title An example implementation of the IInterchainToken.
11:  * @notice The implementation ERC20 can be done in any way, however this example assumes that an _approve internal function exists
12:  * that can be used to create approvals, and that `allowance` is a mapping.
13:  * @dev You can skip the `tokenManagerRequiresApproval()` function altogether if you know what it should return for your token.
14:  */
15: abstract contract InterchainToken is IInterchainToken, ERC20 {
16:     /**
17:      * @notice Getter for the tokenManager used for this token.
18:      * @dev Needs to be overwitten.
19:      * @return tokenManager the TokenManager called to facilitate cross chain transfers.
20:      */
21:     function getTokenManager() public view virtual returns (ITokenManager tokenManager);
22: 
23:     /**
24:      * @notice Getter function specifiying if the tokenManager requires approval to facilitate cross-chain transfers.
25:      * Usually, only mint/burn tokenManagers do not need approval.

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IStandardizedTokenDeployer.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { Create3Deployer } from '../../gmp-sdk/deploy/Create3Deployer.sol';
6: 
7: /**
8:  * @title IStandardizedTokenDeployer
9:  * @notice This contract is used to deploy new instances of the StandardizedTokenProxy contract.
10:  */
11: interface IStandardizedTokenDeployer {
12:     error AddressZero();
13:     error TokenDeploymentFailed();
14: 
15:     /**
16:      * @notice Getter for the Create3Deployer.
17:      */
18:     function deployer() external view returns (Create3Deployer);
19: 
20:     /**
21:      * @notice Deploys a new instance of the StandardizedTokenProxy contract
22:      * @param salt The salt used by Create3Deployer
23:      * @param tokenManager Address of the token manager
24:      * @param distributor Address of the distributor
25:      * @param name Name of the token

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/interfaces/IMultisigBase.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title IMultisigBase Interface
7:  * @notice An interface defining the base operations for a multisignature contract.
8:  */
9: interface IMultisigBase {
10:     error NotSigner();
11:     error AlreadyVoted();
12:     error InvalidSigners();
13:     error InvalidSignerThreshold();
14:     error DuplicateSigner(address account);
15: 
16:     /**********\
17:     |* Events *|
18:     \**********/
19: 
20:     event MultisigOperationExecuted(bytes32 indexed operationHash);
21: 
22:     event SignersRotated(address[] newAccounts, uint256 newThreshold);
23: 
24:     /***********\
25:     |* Getters *|

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/interfaces/IProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: // General interface for upgradable contracts
6: interface IProxy {
7:     error InvalidOwner();
8:     error InvalidImplementation();
9:     error SetupFailed();
10:     error NotOwner();
11:     error AlreadyInitialized();
12: 
13:     function implementation() external view returns (address implementation_);
14: 
15:     function setup(bytes calldata setupParams) external;
16: }
17: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/util/Caller.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { ICaller } from '../interfaces/ICaller.sol';
6: 
7: contract Caller is ICaller {
8:     /**
9:      * @dev Calls a target address with specified calldata and optionally sends value.
10:      */
11:     function _call(
12:         address target,
13:         bytes calldata callData,
14:         uint256 nativeValue
15:     ) internal {
16:         if (nativeValue > address(this).balance) revert InsufficientBalance();
17: 
18:         (bool success, ) = target.call{ value: nativeValue }(callData);
19:         if (!success) {
20:             revert ExecutionFailed();
21:         }
22:     }
23: }
24: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/Proxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from '../interfaces/IProxy.sol';
6: import { IUpgradable } from '../interfaces/IUpgradable.sol';
7: import { BaseProxy } from './BaseProxy.sol';
8: 
9: /**
10:  * @title Proxy Contract
11:  * @notice A proxy contract that delegates calls to a designated implementation contract. Inherits from BaseProxy.
12:  * @dev The constructor takes in the address of the implementation contract, the owner address, and any optional setup
13:  * parameters for the implementation contract.
14:  */
15: contract Proxy is BaseProxy {
16:     /**
17:      * @notice Constructs the proxy contract with a the implementation address, owner address, and optional setup parameters.
18:      * @param implementationAddress The address of the implementation contract
19:      * @param owner The owner address
20:      * @param setupParams Optional parameters to setup the implementation contract
21:      * @dev The constructor verifies that the owner address is not the zero address and that the contract ID of the implementation is valid.
22:      * It then stores the implementation address and owner address in their designated storage slots and calls the setup function on the
23:      * implementation (if setup params exist).
24:      */
25:     constructor(

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IPausable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title Pausable
7:  * @notice This contract provides a mechanism to halt the execution of specific functions
8:  * if a pause condition is activated.
9:  */
10: interface IPausable {
11:     event PausedSet(bool paused);
12: 
13:     error Paused();
14: 
15:     /**
16:      * @notice Check if the contract is paused
17:      * @return paused A boolean representing the pause status. True if paused, false otherwise.
18:      */
19:     function isPaused() external view returns (bool);
20: }
21: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IDistributable.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IDistributable {
6:     error NotDistributor();
7: 
8:     event DistributorChanged(address distributor);
9: 
10:     /**
11:      * @notice Get the address of the distributor
12:      * @return distributor of the distributor
13:      */
14:     function distributor() external view returns (address distributor);
15: 
16:     /**
17:      * @notice Change the distributor of the contract
18:      * @dev Can only be called by the current distributor
19:      * @param distributor The address of the new distributor
20:      */
21:     function setDistributor(address distributor) external;
22: }
23: 

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol';
6: 
7: import { InterchainToken } from '../interchain-token/InterchainToken.sol';
8: import { ERC20Permit } from '../token-implementations/ERC20Permit.sol';
9: import { AddressBytesUtils } from '../libraries/AddressBytesUtils.sol';
10: import { ITokenManager } from '../interfaces/ITokenManager.sol';
11: import { Implementation } from '../utils/Implementation.sol';
12: import { Distributable } from '../utils/Distributable.sol';
13: 
14: /**
15:  * @title StandardizedToken
16:  * @notice This contract implements a standardized token which extends InterchainToken functionality.
17:  * This contract also inherits Distributable and Implementation logic.
18:  */
19: abstract contract StandardizedToken is InterchainToken, ERC20Permit, Implementation, Distributable {
20:     using AddressBytesUtils for bytes;
21: 
22:     address public tokenManager;
23:     string public name;
24:     string public symbol;
25:     uint8 public decimals;

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/BaseProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IProxy } from '../interfaces/IProxy.sol';
6: 
7: /**
8:  * @title BaseProxy Contract
9:  * @dev This abstract contract implements a basic proxy that stores an implementation address. Fallback function
10:  * calls are delegated to the implementation. This contract is meant to be inherited by other proxy contracts.
11:  */
12: abstract contract BaseProxy is IProxy {
13:     // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
15:     // keccak256('owner')
16:     bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
17: 
18:     /**
19:      * @dev Returns the current implementation address.
20:      * @return implementation_ The address of the current implementation contract
21:      */
22:     function implementation() public view virtual returns (address implementation_) {
23:         assembly {
24:             implementation_ := sload(_IMPLEMENTATION_SLOT)
25:         }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { TokenManager } from '../TokenManager.sol';
6: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol';
7: import { IAxelarGateway } from '../../../gmp-sdk/interfaces/IAxelarGateway.sol';
8: 
9: /**
10:  * @title TokenManagerAddressStorage
11:  * @notice This contract extends the TokenManager contract and provides additional functionality to store and retrieve
12:  * the token address using a predetermined storage slot
13:  */
14: abstract contract TokenManagerAddressStorage is TokenManager {
15:     /**
16:      * @dev Creates an instance of the TokenManagerAddressStorage contract.
17:      * @param interchainTokenService_ The address of the interchain token service contract
18:      */
19:     constructor(address interchainTokenService_) TokenManager(interchainTokenService_) {}
20: 
21:     // uint256(keccak256('token-address')) - 1
22:     uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba;
23: 
24:     /**
25:      * @dev Reads the stored token address from the predetermined storage slot

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { TokenManagerAddressStorage } from './TokenManagerAddressStorage.sol';
6: import { IERC20 } from '../../../gmp-sdk/interfaces/IERC20.sol';
7: 
8: import { SafeTokenTransferFrom } from '../../../gmp-sdk/util/SafeTransfer.sol';
9: 
10: /**
11:  * @title TokenManagerLiquidityPool
12:  * @notice This contract is a an implementation of TokenManager that stores all tokens in a separate liquity pool
13:  * rather than within itself.
14:  * @dev This contract extends TokenManagerAddressStorage and provides implementation for its abstract methods.
15:  * It uses the Axelar SDK to safely transfer tokens.
16:  */
17: contract TokenManagerLiquidityPool is TokenManagerAddressStorage {
18:     // uint256(keccak256('liquidity-pool-slot')) - 1
19:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807;
20: 
21:     /**
22:      * @dev Constructs an instance of TokenManagerLiquidityPool. Calls the constructor
23:      * of TokenManagerAddressStorage which calls the constructor of TokenManager.
24:      * @param interchainTokenService_ The address of the interchain token service contract
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/StandardizedTokenProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { FixedProxy } from '../../gmp-sdk/upgradable/FixedProxy.sol';
6: import { IStandardizedToken } from '../interfaces/IStandardizedToken.sol';
7: import { IStandardizedTokenProxy } from '../interfaces/IStandardizedTokenProxy.sol';
8: 
9: /**
10:  * @title StandardizedTokenProxy
11:  * @dev Proxy contract for StandardizedToken contracts. Inherits from FixedProxy and implements IStandardizedTokenProxy.
12:  */
13: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy {
14:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token');
15: 
16:     /**
17:      * @dev Constructs the StandardizedTokenProxy contract.
18:      * @param implementationAddress Address of the StandardizedToken implementation
19:      * @param params Initialization parameters for the StandardizedToken contract
20:      */
21:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) {
22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();
23: 
24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
25:         if (!success) revert SetupFailed();

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/IExpressCallHandler.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: interface IExpressCallHandler {
6:     error AlreadyExpressCalled();
7:     error SameDestinationAsCaller();
8: 
9:     event ExpressReceive(
10:         bytes32 indexed tokenId,
11:         address indexed destinationAddress,
12:         uint256 amount,
13:         bytes32 indexed sendHash,
14:         address expressCaller
15:     );
16:     event ExpressExecutionFulfilled(
17:         bytes32 indexed tokenId,
18:         address indexed destinationAddress,
19:         uint256 amount,
20:         bytes32 indexed sendHash,
21:         address expressCaller
22:     );
23: 
24:     event ExpressReceiveWithData(
25:         bytes32 indexed tokenId,

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/utils/ExpressCallHandler.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IExpressCallHandler } from '../interfaces/IExpressCallHandler.sol';
6: 
7: /**
8:  * @title ExpressCallHandler
9:  * @dev Integrates the interchain token service with the GMP express service by providing methods to handle express calls for
10:  * token transfers and token transfers with contract calls between chains. Implements the IExpressCallHandler interface.
11:  */
12: contract ExpressCallHandler is IExpressCallHandler {
13:     // uint256(keccak256('prefix-express-give-token'));
14:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN = 0x67c7b41c1cb0375e36084c4ec399d005168e83425fa471b9224f6115af865619;
15:     // uint256(keccak256('prefix-express-give-token-with-data'));
16:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA = 0x3e607cc12a253b1d9f677a03d298ad869a90a8ba4bd0fb5739e7d79db7cdeaad;
17: 
18:     /**
19:      * @notice Calculates the unique slot for a given express token transfer.
20:      * @param tokenId The ID of the token being sent
21:      * @param destinationAddress The address of the recipient
22:      * @param amount The amount of tokens to be sent
23:      * @param commandId The unique hash for this token transfer
24:      * @return slot The calculated slot for this token transfer
25:      */

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { IAxelarServiceGovernance } from '../interfaces/IAxelarServiceGovernance.sol';
6: import { InterchainGovernance } from './InterchainGovernance.sol';
7: import { MultisigBase } from '../auth/MultisigBase.sol';
8: 
9: /**
10:  * @title AxelarServiceGovernance Contract
11:  * @dev This contract is part of the Axelar Governance system, it inherits the Interchain Governance contract
12:  * with added functionality to approve and execute multisig proposals.
13:  */
14: contract AxelarServiceGovernance is InterchainGovernance, MultisigBase, IAxelarServiceGovernance {
15:     enum ServiceGovernanceCommand {
16:         ScheduleTimeLockProposal,
17:         CancelTimeLockProposal,
18:         ApproveMultisigProposal,
19:         CancelMultisigApproval
20:     }
21: 
22:     mapping(bytes32 => bool) public multisigApprovals;
23: 
24:     /**
25:      * @notice Initializes the contract.

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/InterchainTokenServiceProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: import { FinalProxy } from '../../gmp-sdk/upgradable/FinalProxy.sol';
6: 
7: /**
8:  * @title InterchainTokenServiceProxy
9:  * @dev Proxy contract for interchain token service contracts. Inherits from the FinalProxy contract.
10:  */
11: contract InterchainTokenServiceProxy is FinalProxy {
12:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
13: 
14:     /**
15:      * @dev Constructs the InterchainTokenServiceProxy contract.
16:      * @param implementationAddress Address of the interchain token service implementation
17:      * @param owner Address of the owner of the proxy
18:      */
19:     constructor(
20:         address implementationAddress,
21:         address owner,
22:         address operator
23:     ) FinalProxy(implementationAddress, owner, abi.encodePacked(operator)) {}
24: 
25:     /**

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interfaces/ITokenManagerProxy.sol#L1-L1

1: // SPDX-License-Identifier: MIT
2: 
3: pragma solidity ^0.8.0;
4: 
5: /**
6:  * @title TokenManagerProxy
7:  * @dev This contract is a proxy for token manager contracts. It implements ITokenManagerProxy and
8:  * inherits from FixedProxy from the gmp sdk repo
9:  */
10: interface ITokenManagerProxy {
11:     error ImplementationLookupFailed();
12:     error SetupFailed();
13: 
14:     /**
15:      * @notice Returns implementation type of this token manager
16:      */
17:     function implementationType() external view returns (uint256);
18: 
19:     /**
20:      * @notice Returns the address of the current implementation.
21:      * @return impl The address of the current implementation
22:      */
23:     function implementation() external view returns (address);
24: 
25:     /**

[GAS-26] The result of a function call should be cached rather than re-calling the function

Number of instances found

9

Resolution

External calls in Solidity are costly in terms of gas usage. This can significantly impact contract efficiency and cost. Functions that make repetitive calls to fetch the same data from other contracts can cause unnecessary gas expenditure. To optimize this, it's advisable to store the returned value of these function calls in a state variable, essentially caching the data. This data can be updated at regular intervals or under specific conditions instead of fetching it from the external contract on every invocation. Be sure to analyze the frequency of data change in the external contract to balance data freshness with gas efficiency when implementing caching.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L173

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
150:         uint256 length = signers.accounts.length;
151: 
152:         
153:         for (uint256 i; i < length; ++i) {
154:             signers.isSigner[signers.accounts[i]] = false;
155:         }
156: 
157:         length = newAccounts.length;
158: 
159:         if (newThreshold > length) revert InvalidSigners(); // <= FOUND
160: 
161:         if (newThreshold == 0) revert InvalidSignerThreshold();
162: 
163:         ++signerEpoch;
164: 
165:         signers.accounts = newAccounts;
166:         signers.threshold = newThreshold;
167: 
168:         for (uint256 i; i < length; ++i) {
169:             address account = newAccounts[i];
170: 
171:             
172:             if (signers.isSigner[account]) revert DuplicateSigner(account);
173:             if (account == address(0)) revert InvalidSigners(); // <= FOUND
174: 
175:             signers.isSigner[account] = true;
176:         }
177: 
178:         emit SignersRotated(newAccounts, newThreshold);
179:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/InitProxy.sol#L35-L50

35:     function init(
36:         address implementationAddress,
37:         address newOwner,
38:         bytes memory params
39:     ) external {
40:         address owner;
41: 
42:         assembly {
43:             owner := sload(_OWNER_SLOT)
44:         }
45: 
46:         if (msg.sender != owner) revert NotOwner();
47:         if (implementation() != address(0)) revert AlreadyInitialized(); // <= FOUND
48: 
49:         bytes32 id = contractId(); // <= FOUND
50:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation(); // <= FOUND
51: 
52:         assembly {
53:             sstore(_IMPLEMENTATION_SLOT, implementationAddress)
54:             sstore(_OWNER_SLOT, newOwner)
55:         }
56: 
57:         if (params.length != 0) {
58:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, params));
59:             if (!success) revert SetupFailed();
60:         }
61:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L37-L40

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_) { // <= FOUND
38:         implementation_ = _finalImplementation();
39:         if (implementation_ == address(0)) {
40:             implementation_ = super.implementation(); // <= FOUND
41:         }
42:     }

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L83-L85

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {
84:         if (bytes(chain).length == 0) revert ZeroStringLength(); // <= FOUND
85:         if (bytes(addr).length == 0) revert ZeroStringLength(); // <= FOUND
86:         remoteAddressHashes[chain] = keccak256(bytes(_lowerCase(addr)));
87:         remoteAddresses[chain] = addr;
88:         emit TrustedAddressAdded(chain, addr);
89:     }

[GAS-27] Private functions used once can be inlined

Number of instances found

1

Resolution

Private functions which are only called once can be inlined to save GAS.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/interchain-governance-executor/InterchainProposalSender.sol#L104-L104

104:     function revertIfInvalidFee(InterchainCalls.InterchainCall[] calldata interchainCalls) private  // <= FOUND

[GAS-28] Use bitmap to save gas

Number of instances found

10

Resolution

Bitmaps in Solidity are essentially a way of representing a set of boolean values within an integer type variable such as uint256. Each bit in the integer represents a true or false value (1 or 0), thus allowing efficient storage of multiple boolean values.

Bitmaps can save gas in the Ethereum network because they condense a lot of information into a small amount of storage. In Ethereum, storage is one of the most significant costs in terms of gas usage. By reducing the amount of storage space needed, you can potentially save on gas fees.

Here's a quick comparison:

If you were to represent 256 different boolean values in the traditional way, you would have to declare 256 different bool variables. Given that each bool occupies a storage slot and each storage slot costs 20,000 gas to initialize, you would end up paying a considerable amount of gas.

On the other hand, if you were to use a bitmap, you could store these 256 boolean values within a single uint256 variable. In other words, you'd only pay for a single storage slot, resulting in significant gas savings.

However, it's important to note that while bitmaps can provide gas efficiencies, they do add complexity to the code, making it harder to read and maintain. Also, using bitmaps is efficient only when dealing with a large number of boolean variables that are frequently changed or accessed together.

In contrast, the straightforward counterpart to bitmaps would be using arrays or mappings to store boolean values, with each bool value occupying its own storage slot. This approach is simpler and more readable but could potentially be more expensive in terms of gas usage.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L97-L97

97:             multisigApprovals[proposalHash] = true; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L53-L53

53:         voting.hasVoted[msg.sender] = true; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L175-L175

175:             signers.isSigner[account] = true; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L110-L110

110:             supportedByGateway[chainName] = true; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L57-L57

57:         multisigApprovals[proposalHash] = false; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L102-L102

102:             multisigApprovals[proposalHash] = false; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L71-L71

71:             voting.hasVoted[signers.accounts[i]] = false; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L154-L154

154:             signers.isSigner[signers.accounts[i]] = false; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L364-L364

364:                 allowOperatorshipTransfer = false; // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L123-L123

123:             supportedByGateway[chainName] = false; // <= FOUND

[GAS-29] Use assembly hashing

Number of instances found

38

Resolution

From a gas standpoint, the assembly version of the keccak256 hashing function can be more efficient than the high-level Solidity version. This is because Solidity has additional overhead when handling function calls and memory management, which can increase the gas cost.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L41-L41

41:         governanceChainHash = keccak256(bytes(governanceChain_)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L42-L42

42:         governanceAddressHash = keccak256(bytes(governanceAddress_)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/governance/InterchainGovernance.sol#L73-L73

73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L47-L47

47:         bytes32 topic = keccak256(msg.data); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L13-L13

13:     bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/util/TimeLock.sol#L93-L93

93:         bytes32 key = keccak256(abi.encodePacked(PREFIX_TIME_LOCK, hash)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L44-L44

44:     bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L45-L45

45:     bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L46-L46

46:     bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L47-L47

47:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L48-L48

48:     bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L49-L49

49:     bytes32 internal constant PREFIX_TOKEN_MINT_LIMIT = keccak256('token-mint-limit'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L50-L50

50:     bytes32 internal constant PREFIX_TOKEN_MINT_AMOUNT = keccak256('token-mint-amount'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L52-L52

52:     bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L53-L53

53:     bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L54-L54

54:     bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L55-L55

55:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L56-L56

56:     bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L57-L57

57:     bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L349-L349

349:             bytes32 commandHash = keccak256(abi.encodePacked(commands[i])); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/AxelarGateway.sol#L395-L395

395:             bytes32 salt = keccak256(abi.encodePacked(symbol)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/ConstAddressDeployer.sol#L63-L63

63:         bytes32 newSalt = keccak256(abi.encode(sender, salt)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L30-L30

30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3Deployer.sol#L68-L68

68:         bytes32 deploySalt = keccak256(abi.encode(sender, salt)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/deploy/Create3.sol#L41-L41

41:     bytes32 internal constant DEPLOYER_BYTECODE_HASH = keccak256(type(CreateDeployer).creationCode); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/gmp-sdk/upgradable/FinalProxy.sol#L18-L18

18:     bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L62-L62

62:     bytes32 internal constant PREFIX_CUSTOM_TOKEN_ID = keccak256('its-custom-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L63-L63

63:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_ID = keccak256('its-standardized-token-id'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L64-L64

64:     bytes32 internal constant PREFIX_STANDARDIZED_TOKEN_SALT = keccak256('its-standardized-token-salt'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L71-L71

71:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L111-L111

111:         chainNameHash = keccak256(bytes(chainName_)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L203-L203

203:         tokenId = keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_ID, chainNameHash, tokenAddress)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L214-L214

214:         tokenId = keccak256(abi.encode(PREFIX_CUSTOM_TOKEN_ID, sender, salt)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/proxies/RemoteAddressValidatorProxy.sol#L12-L12

12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/token-implementations/StandardizedToken.sol#L27-L27

27:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token'); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L30-L30

30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString()))); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L71-L71

71:         bytes32 sourceAddressHash = keccak256(bytes(sourceAddressLC)); // <= FOUND

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L86-L86

86:         remoteAddressHashes[chain] = keccak256(bytes(_lowerCase(addr))); // <= FOUND

[GAS-30] Consider merging sequential for loops

Number of instances found

2

Resolution

Merging multiple for loops within a function in Solidity can enhance efficiency and reduce gas costs, especially when they share a common iterating variable or perform related operations. By minimizing redundant iterations over the same data set, execution becomes more cost-effective. However, while merging can optimize gas usage and simplify logic, it may also increase code complexity. Therefore, careful balance between optimization and maintainability is essential, along with thorough testing to ensure the refactored code behaves as expected.

Findings

Findings are labeled with ' <= FOUND'

Click to show findings

https://github.com/code-423n4/2023-07-axelar/tree/main/contracts/cgp/auth/MultisigBase.sol#L149-L168

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
150:         uint256 length = signers.accounts.length;
151: 
152:         
153:         for (uint256 i; i < length; ++i) { // <= FOUND
154:             signers.isSigner[signers.accounts[i]] = false;
155:         }
156: 
157:         length = newAccounts.length;
158: 
159:         if (newThreshold > length) revert InvalidSigners();
160: 
161:         if (newThreshold == 0) revert InvalidSignerThreshold();
162: 
163:         ++signerEpoch;
164: 
165:         signers.accounts = newAccounts;
166:         signers.threshold = newThreshold;
167: 
168:         for (uint256 i; i < length; ++i) { // <= FOUND
169:             address account = newAccounts[i];
170: 
171:             
172:             if (signers.isSigner[account]) revert DuplicateSigner(account);
173:             if (account == address(0)) revert InvalidSigners();
174: 
175:             signers.isSigner[account] = true;
176:         }
177: 
178:         emit SignersRotated(newAccounts, newThreshold);
179:     }
@thebrittfactor
Copy link
Author

For transparency, the sponsor has provided their input on the H/M findings within this bot report via discord. Their response is below:

H-01 - Mentions to be careful with Multicall, although there's no actual issue reported, so seems more like a QA.
M-01 - Invalid, this is an intended design decision. Although these functions can only be called by a particular address, in practice this address will be one of our governance contracts and therefore will not represent a single point of failure. Here is the AxelarServiceGovernance contract for reference.
M-02 - Invalid, we have a dedicated token manager for fee-on-transfer tokens that takes this into account. Here is TokenManagerLockUnlockFee for reference.
M-03 - Invalid, either the user is calling such functions in which case they are responsible, or a relayer is. Relayers require gas payment and use a gas limit when calling such methods to avoid any gas grief issues. For the deployer contracts, it is also the responsibility of the user to ensure they are not deploying malicious contracts which will lead to gas grief attacks when initialized.
M-06 - NFT is not relevant to the audit scope.
M-07 - interesting if the call doesn't fully revert on a failure, but we don't have those instances.

@thebrittfactor
Copy link
Author

For transparency, the judge has also provided their input via discord. Their response is below:

H-01 - Agree with sponsor. It should be QA (Low). Concrete example demonstrating a potential issue is missing.
M-01 - I consider this submission as QA (NC) for the same reason the sponsor elaborated.
M-02 - Agree with the sponsor that there is a special token manager for such fee-on-transfer tokens. However, the identified instances in the report are still affected by the issue. Consequently, I consider medium severity to be appropriate.
M-03 - Agree with the sponsor that this finding is invalid. The instances mentioned in the report are not necessarily untrusted external contracts. The AxelarGateway contract calls itself in line 373. The other instances involve deploying contracts, as such, the deployer is responsible to only deploy legitimate code to avoid being vulnerable to gas griefing.
M-06 - Agree with sponsor that this finding is invalid. Seems like a false positive.
M-07 - As there's no concrete impact mentioned and this only becomes an issue if the caller supplied more native tokens than specified in the function parameter (e.g., nativeValue, call.value) I consider this to be QA (Low).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment