Axelar Network - matrix_0wl's results

Decentralized interoperability network.

General Information

Platform: Code4rena

Start Date: 12/07/2023

Pot Size: $80,000 USDC

Total HM: 11

Participants: 47

Period: 9 days

Judge: berndartmueller

Total Solo HM: 1

Id: 260

League: ETH

Axelar Network

Findings Distribution

Researcher Performance

Rank: 30/47

Findings: 2

Award: $62.61

QA:
grade-b
Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Labels

bug
grade-b
QA (Quality Assurance)
Q-05

Awards

43.3267 USDC - $43.33

External Links

Non Critical Issues

Issue
NC-1ADD A TIMELOCK TO CRITICAL FUNCTIONS
NC-2Avoid passing as reference the chainid
NC-3GENERATE PERFECT CODE HEADERS EVERY TIME
NC-4COMMENTED CODE
NC-5INCONSISTENT SOLIDITY VERSIONS
NC-6CONSTANT VALUES SUCH AS A CALL TO KECCAK256(), SHOULD USE IMMUTABLE RATHER THAN CONSTANT
NC-7FOR EXTENDED “USING-FOR” USAGE, USE THE LATEST PRAGMA VERSION
NC-8MISSING EVENT FOR CRITICAL PARAMETER CHANGE
NC-9NO SAME VALUE INPUT CONTROL
NC-10SOLIDITY COMPILER OPTIMIZATIONS CAN BE PROBLEMATIC
NC-11Return values of _approve() not checked
NC-12LINES ARE TOO LONG
NC-13Constants should be defined rather than using magic numbers
NC-14IMPLEMENT SOME TYPE OF VERSION COUNTER THAT WILL BE INCREMENTED AUTOMATICALLY FOR CONTRACT UPGRADES

[NC-1] ADD A TIMELOCK TO CRITICAL FUNCTIONS

Description:

It is a good practice to give time for users to react and adjust to critical changes. A timelock provides more guarantees and reduces the level of trust required, thus decreasing risk for users. It also indicates that the project is legitimate (less risk of a malicious owner making a sandwich attack on a user).

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

266:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {

627:     function _setTokenMintLimit(string memory symbol, uint256 limit) internal {

633:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {

640:     function _setTokenType(string memory symbol, TokenType tokenType) internal {

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

648:     function _setCommandExecuted(bytes32 commandId, bool executed) internal {

652:     function _setContractCallApproved(

662:     function _setContractCallApprovedWithMint(

677:     function _setImplementation(address newImplementation) internal {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

92:     function setWhitelistedProposalCaller(

107:     function setWhitelistedProposalSender(
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

29:     function setWhitelistedProposalSender(

41:     function setWhitelistedProposalCaller(
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {
File: /contracts/its/interfaces/IDistributable.sol

21:     function setDistributor(address distributor) external;
File: /contracts/its/interfaces/IInterchainTokenService.sol

286:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external;

313:     function setPaused(bool paused) external;
File: /contracts/its/interfaces/IOperatable.sol

21:     function setOperator(address operator_) external;
File: /contracts/its/interfaces/ITokenManager.sol

87:     function setFlowLimit(uint256 flowLimit) external;
File: /contracts/its/token-manager/TokenManager.sol

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator {
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

38:     function _setTokenAddress(address tokenAddress_) internal {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

47:     function _setLiquidityPool(address liquidityPool_) internal {

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
File: /contracts/its/utils/Distributable.sol

39:     function _setDistributor(address distributor_) internal {

51:     function setDistributor(address distr) external onlyDistributor {
File: /contracts/its/utils/ExpressCallHandler.sol

79:     function _setExpressReceiveToken(

110:     function _setExpressReceiveTokenWithData(
File: /contracts/its/utils/FlowLimit.sol

34:     function _setFlowLimit(uint256 flowLimit) internal {
File: /contracts/its/utils/Operatable.sol

39:     function _setOperator(address operator_) internal {

51:     function setOperator(address operator_) external onlyOperator {
File: /contracts/its/utils/Pausable.sol

41:     function _setPaused(bool paused) internal {

[NC-2] Avoid passing as reference the chainid

Description:

Instead of passing chainid as reference you could get current chainid using block.chainid

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

338:         if (chainId != block.chainid) revert InvalidChainId();

[NC-3] GENERATE PERFECT CODE HEADERS EVERY TIME

Description:

I recommend using header for Solidity code layout and readability: https://github.com/transmissions11/headers

/*//////////////////////////////////////////////////////////////
                           TESTING 123
//////////////////////////////////////////////////////////////*/

[NC-4] COMMENTED CODE

Proof Of Concept
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

72:                             keccak256(bytecode) // init code hash

[NC-5] INCONSISTENT SOLIDITY VERSIONS

Description:

The project is compiled with different versions of Solidity, which is not recommended because it can lead to undefined behaviors.

It is better to use one Solidity compiler version across all contracts instead of different versions with different bugs and security checks.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

3: pragma solidity ^0.8.9;
File: /contracts/cgp/auth/MultisigBase.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/InterchainGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/Multisig.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IAxelarServiceGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/ICaller.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IMultisig.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IMultisigBase.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/util/Caller.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/Create3.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IFinalProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IInitProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/ITimeLock.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IUpgradable.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/InitProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/Proxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/util/TimeLock.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

2: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/lib/InterchainCalls.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interchain-token/InterchainToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IDistributable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IExpressCallHandler.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IFlowLimit.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IImplementation.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IInterchainToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IInterchainTokenService.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IMulticall.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IOperatable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IPausable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedTokenProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManager.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerType.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/libraries/AddressBytesUtils.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/StandardizedTokenProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/TokenManagerProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedTokenLockUnlock.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedTokenMintBurn.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/TokenManager.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerMintBurn.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Distributable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/ExpressCallHandler.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/FlowLimit.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Implementation.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Multicall.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Operatable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Pausable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/StandardizedTokenDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/TokenManagerDeployer.sol

3: pragma solidity ^0.8.0;

[NC-6] CONSTANT VALUES SUCH AS A CALL TO KECCAK256(), SHOULD USE IMMUTABLE RATHER THAN CONSTANT

Description:

There is a difference between constant variables and immutable variables, and they should each be used in their appropriate contexts.

While it doesn’t save any gas because the compiler knows that developers often make this mistake, it’s still best to use the right tool for the task at hand.

WConstants should be used for literal values written into the code, and immutable variables should be used for expressions, or values calculated in, or passed into the constructor.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

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

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

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

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

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

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

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

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

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

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

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

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

57:     bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship');
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

18:     bytes32 internal constant FINAL_IMPLEMENTATION_SALT = keccak256('final-implementation');
File: /contracts/gmp-sdk/util/TimeLock.sol

13:     bytes32 internal constant PREFIX_TIME_LOCK = keccak256('time-lock');
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

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');

71:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

12:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
File: /contracts/its/proxies/StandardizedTokenProxy.sol

14:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token');
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
File: /contracts/its/token-implementations/StandardizedToken.sol

27:     bytes32 private constant CONTRACT_ID = keccak256('standardized-token');
File: /contracts/its/utils/FlowLimit.sol

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'));

[NC-7] FOR EXTENDED “USING-FOR” USAGE, USE THE LATEST PRAGMA VERSION

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

3: pragma solidity ^0.8.9;
File: /contracts/cgp/auth/MultisigBase.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/InterchainGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/governance/Multisig.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IAxelarServiceGovernance.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/ICaller.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IMultisig.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/interfaces/IMultisigBase.sol

3: pragma solidity ^0.8.0;
File: /contracts/cgp/util/Caller.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/Create3.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IFinalProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IInitProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/ITimeLock.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/interfaces/IUpgradable.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/InitProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/Proxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

3: pragma solidity ^0.8.0;
File: /contracts/gmp-sdk/util/TimeLock.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

2: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol

3: pragma solidity ^0.8.0;
File: /contracts/interchain-governance-executor/lib/InterchainCalls.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interchain-token/InterchainToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IDistributable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IExpressCallHandler.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IFlowLimit.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IImplementation.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IInterchainToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IInterchainTokenService.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IMulticall.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IOperatable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IPausable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/IStandardizedTokenProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManager.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/interfaces/ITokenManagerType.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/libraries/AddressBytesUtils.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/StandardizedTokenProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/proxies/TokenManagerProxy.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedToken.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedTokenLockUnlock.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-implementations/StandardizedTokenMintBurn.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/TokenManager.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/token-manager/implementations/TokenManagerMintBurn.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Distributable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/ExpressCallHandler.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/FlowLimit.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Implementation.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Multicall.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Operatable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/Pausable.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/StandardizedTokenDeployer.sol

3: pragma solidity ^0.8.0;
File: /contracts/its/utils/TokenManagerDeployer.sol

3: pragma solidity ^0.8.0;

Use solidity pragma version min. 0.8.13

[NC-8] MISSING EVENT FOR CRITICAL PARAMETER CHANGE

Description:

Events help non-contract tools to track changes, and events prevent users from being surprised by changes.

When changing state variables events are not emitted. Emitting events allows monitoring activities with off-chain monitoring tools.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

266:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

92:     function setWhitelistedProposalCaller(

107:     function setWhitelistedProposalSender(
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

29:     function setWhitelistedProposalSender(

41:     function setWhitelistedProposalCaller(
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {

547:     function setPaused(bool paused) external onlyOwner {
File: /contracts/its/interfaces/IDistributable.sol

21:     function setDistributor(address distributor) external;
File: /contracts/its/interfaces/IInterchainTokenService.sol

286:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external;

313:     function setPaused(bool paused) external;
File: /contracts/its/interfaces/IOperatable.sol

21:     function setOperator(address operator_) external;
File: /contracts/its/interfaces/ITokenManager.sol

87:     function setFlowLimit(uint256 flowLimit) external;
File: /contracts/its/token-manager/TokenManager.sol

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
File: /contracts/its/utils/Distributable.sol

51:     function setDistributor(address distr) external onlyDistributor {
File: /contracts/its/utils/Operatable.sol

51:     function setOperator(address operator_) external onlyOperator {

[NC-9] NO SAME VALUE INPUT CONTROL

Proof Of Concept
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

29:         interchainTokenServiceAddress = _interchainTokenServiceAddress;

[NC-10] SOLIDITY COMPILER OPTIMIZATIONS CAN BE PROBLEMATIC

Description:

Protocol has enabled optional compiler optimizations in Solidity. There have been several optimization bugs with security implications. Moreover, optimizations are actively being developed. Solidity compiler optimizations are disabled by default, and it is unclear how many contracts in the wild actually use them.

Therefore, it is unclear how well they are being tested and exercised. High-severity security issues due to optimization bugs have occurred in the past. A high-severity bug in the emscripten-generated solc-js compiler used by Truffle and Remix persisted until late 2018. The fix for this bug was not reported in the Solidity CHANGELOG.

Another high-severity optimization bug resulting in incorrect bit shift results was patched in Solidity 0.5.6. More recently, another bug due to the incorrect caching of keccak256 was reported. A compiler audit of Solidity from November 2018 concluded that the optional optimizations may not be safe. It is likely that there are latent bugs related to optimization and that new bugs will be introduced due to future optimizations.

Exploit Scenario:

A latent or future bug in Solidity compiler optimizations—or in the Emscripten transpilation to solc-js—causes a security vulnerability in the contracts.

Proof Of Concept
File: hardhat.config.ts

solidity: {
        version: '0.8.9',
        settings: {
            evmVersion: process.env.EVM_VERSION || 'london',
            optimizer: {
                enabled: true,
                runs: 1000,

[NC-11] Return values of _approve() not checked

Description:

Not all IERC20 implementations revert() when there's a failure in _approve(). The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything

Proof Of Concept
File: /contracts/its/interchain-token/InterchainToken.sol

61:                 _approve(sender, address(tokenManager), allowance_ + amount);

89:             _approve(sender, msg.sender, _allowance - amount);

100:                 _approve(sender, address(tokenManager), allowance_ + amount);

[NC-12] LINES ARE TOO LONG

Description:

Usually lines in source code are limited to 80 characters. Today’s screens are much larger so it’s reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

5: import { SafeTokenCall, SafeTokenTransfer, SafeTokenTransferFrom } from '../gmp-sdk/util/SafeTransfer.sol';

10: import { IBurnableMintableCappedERC20 } from './interfaces/IBurnableMintableCappedERC20.sol';

35:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);

38:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909);

41:     bytes32 internal constant KEY_MINT_LIMITER = bytes32(0x627f0c11732837b3240a2de89c0b6343512886dd50978b99c76a68c6416a4d92);

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

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

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

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

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

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

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

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

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

66:         if (tokenDeployerImplementation_.code.length == 0) revert InvalidTokenDeployer();

88:         if (msg.sender != getAddress(KEY_MINT_LIMITER) && msg.sender != getAddress(KEY_GOVERNANCE)) revert NotMintLimiter();

104:         emit TokenSent(msg.sender, destinationChain, destinationAddress, symbol, amount);

112:         emit ContractCall(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload);

123:         emit ContractCallWithToken(msg.sender, destinationChain, destinationContractAddress, keccak256(payload), payload, symbol, amount);

133:         return getBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash));

147:                 _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount)

157:         bytes32 key = _getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash);

170:         bytes32 key = _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, msg.sender, payloadHash, symbol, amount);

199:     function tokenMintLimit(string memory symbol) public view override returns (uint256) {

203:     function tokenMintAmount(string memory symbol) public view override returns (uint256) {

204:         return getUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours));

224:     function admins(uint256) external pure override returns (address[] memory) {

232:     function tokenAddresses(string memory symbol) public view override returns (address) {

242:     function isCommandExecuted(bytes32 commandId) public view override returns (bool) {

254:     function transferGovernance(address newGovernance) external override onlyGovernance {

260:     function transferMintLimiter(address newMintLimiter) external override onlyMintLimiter {

266:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {

274:             if (tokenAddresses(symbol) == address(0)) revert TokenDoesNotExist(symbol);

285:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();

287:         if (AxelarGateway(newImplementation).contractId() != contractId()) revert InvalidImplementation();

294:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(IAxelarGateway.setup.selector, setupParams));

311:         (address governance_, address mintLimiter_, bytes memory newOperatorsData) = abi.decode(params, (address, address, bytes));

324:         (bytes memory data, bytes memory proof) = abi.decode(input, (bytes, bytes));

329:         bool allowOperatorshipTransfer = IAxelarAuth(AUTH_MODULE).validateProof(messageHash, proof);

336:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));

342:         if (commandsLength != commands.length || commandsLength != params.length) revert InvalidCommands();

347:             if (isCommandExecuted(commandId)) continue; /* Ignore if duplicate commandId received */

358:             } else if (commandHash == SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT) {

359:                 commandSelector = AxelarGateway.approveContractCallWithMint.selector;

374:             (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i], commandId));

386:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(

392:         if (tokenAddresses(symbol) != address(0)) revert TokenAlreadyExists(symbol);

398:             (bool success, bytes memory data) = TOKEN_DEPLOYER_IMPLEMENTATION.delegatecall(

399:                 abi.encodeWithSelector(ITokenDeployer.deployToken.selector, name, symbol, decimals, cap, salt)

409:             if (tokenAddress.code.length == uint256(0)) revert TokenContractDoesNotExist(tokenAddress);

422:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));

428:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));

435:             address depositHandlerAddress = _getCreate2Address(salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode)));

443:                 abi.encodeWithSelector(IERC20.transfer.selector, address(this), IERC20(tokenAddress).balanceOf(address(depositHandler)))

446:             if (!success || (returnData.length != uint256(0) && !abi.decode(returnData, (bool)))) revert BurnFailed(symbol);

455:     function approveContractCall(bytes calldata params, bytes32 commandId) external onlySelf {

463:         ) = abi.decode(params, (string, string, address, bytes32, bytes32, uint256));

465:         _setContractCallApproved(commandId, sourceChain, sourceAddress, contractAddress, payloadHash);

466:         emit ContractCallApproved(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, sourceTxHash, sourceEventIndex);

469:     function approveContractCallWithMint(bytes calldata params, bytes32 commandId) external onlySelf {

479:         ) = abi.decode(params, (string, string, address, bytes32, string, uint256, bytes32, uint256));

481:         _setContractCallApprovedWithMint(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount);

495:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf {

509:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

543:             IERC20(tokenAddress).safeTransferFrom(sender, address(this), amount);

545:             IERC20(tokenAddress).safeCall(abi.encodeWithSelector(IBurnableMintableCappedERC20.burnFrom.selector, sender, amount));

547:             IERC20(tokenAddress).safeTransferFrom(sender, IBurnableMintableCappedERC20(tokenAddress).depositAddress(bytes32(0)), amount);

556:     function _getTokenMintLimitKey(string memory symbol) internal pure returns (bytes32) {

560:     function _getTokenMintAmountKey(string memory symbol, uint256 day) internal pure returns (bytes32) {

565:     function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) {

569:     function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {

573:     function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {

584:         return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash));

615:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {

616:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash)))));

619:     function _getTokenType(string memory symbol) internal view returns (TokenType) {

633:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {

637:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount);

640:     function _setTokenType(string memory symbol, TokenType tokenType) internal {

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

659:         _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true);

672:             _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount),

688:         emit MintLimiterTransferred(getAddress(KEY_MINT_LIMITER), newMintLimiter);
File: /contracts/cgp/auth/MultisigBase.sol

95:     function signerAccounts() external view override returns (address[] memory) {

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

119:     function getSignerVotesCount(bytes32 topic) external view override returns (uint256) {

123:             if (votingPerTopic[signerEpoch][topic].hasVoted[signers.accounts[i]]) {

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

149:     function _rotateSigners(address[] memory newAccounts, uint256 newThreshold) internal {
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

5: import { IAxelarServiceGovernance } from '../interfaces/IAxelarServiceGovernance.sol';

14: contract AxelarServiceGovernance is InterchainGovernance, MultisigBase, IAxelarServiceGovernance {

40:     ) InterchainGovernance(gateway, governanceChain, governanceAddress, minimumTimeDelay) MultisigBase(cosigners, threshold) {}

53:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));

84:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));

89:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);

91:         } else if (command == ServiceGovernanceCommand.CancelTimeLockProposal) {

94:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);

96:         } else if (command == ServiceGovernanceCommand.ApproveMultisigProposal) {

101:         } else if (command == ServiceGovernanceCommand.CancelMultisigApproval) {

104:             emit MultisigCancelled(proposalHash, target, callData, nativeValue);
File: /contracts/cgp/governance/InterchainGovernance.sol

5: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol';

7: import { IInterchainGovernance } from '../interfaces/IInterchainGovernance.sol';

15: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance {

57:         return _getTimeLockEta(_getProposalHash(target, callData, nativeValue));

73:         bytes32 proposalHash = keccak256(abi.encodePacked(target, callData, nativeValue));

78:         emit ProposalExecuted(proposalHash, target, callData, nativeValue, block.timestamp);

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

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

130:             emit ProposalScheduled(proposalHash, target, callData, nativeValue, eta);

135:             emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta);
File: /contracts/cgp/governance/Multisig.sol

20:     constructor(address[] memory accounts, uint256 threshold) MultisigBase(accounts, threshold) {}
File: /contracts/cgp/interfaces/IAxelarServiceGovernance.sol

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);
File: /contracts/cgp/interfaces/IMultisigBase.sol

56:     function hasSignerVoted(address account, bytes32 topic) external view returns (bool);

62:     function getSignerVotesCount(bytes32 topic) external view returns (uint256);

73:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external;
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

10:     event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {

25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

80:     function _deploy(bytes memory bytecode, bytes32 salt) internal returns (address deployedAddress_) {

85:             deployedAddress_ := create2(0, add(bytecode, 32), mload(bytecode), salt)
File: /contracts/gmp-sdk/deploy/Create3.sol

41:     bytes32 internal constant DEPLOYER_BYTECODE_HASH = keccak256(type(CreateDeployer).creationCode);

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

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)))));

74:         deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', deployer, hex'01')))));
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

15:     event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) {
File: /contracts/gmp-sdk/interfaces/IFinalProxy.sol

11:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) external returns (address);
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

16:     bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;

22:     function implementation() public view virtual returns (address implementation_) {

51:             let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

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

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_) {

57:     function _finalImplementation() internal view virtual returns (address implementation_) {

61:         implementation_ = Create3.deployedAddress(address(this), FINAL_IMPLEMENTATION_SALT);

72:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) public returns (address finalImplementation_) {

79:         finalImplementation_ = Create3.deploy(FINAL_IMPLEMENTATION_SALT, bytecode);

81:             (bool success, ) = finalImplementation_.delegatecall(abi.encodeWithSelector(BaseProxy.setup.selector, setupParams));
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

43:             let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
File: /contracts/gmp-sdk/upgradable/InitProxy.sol

50:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();

58:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, params));
File: /contracts/gmp-sdk/upgradable/Proxy.sol

33:         if (id != bytes32(0) && IUpgradable(implementationAddress).contractId() != id) revert InvalidImplementation();

41:             (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IUpgradable.setup.selector, setupParams));
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

57:         if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation();

58:         if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();

61:             (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params));
File: /contracts/gmp-sdk/util/TimeLock.sol

38:     function getTimeLock(bytes32 hash) external view override returns (uint256) {

50:     function _scheduleTimeLock(bytes32 hash, uint256 eta) internal returns (uint256) {

92:     function _getTimeLockEta(bytes32 hash) internal view returns (uint256 eta) {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

7: import { IInterchainProposalExecutor } from './interfaces/IInterchainProposalExecutor.sol';

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {

49:         if (!whitelistedSenders[sourceChain][StringToAddress.toAddress(sourceAddress)]) {

54:         (address interchainProposalCaller, InterchainCalls.Call[] memory calls) = abi.decode(payload, (address, InterchainCalls.Call[]));

64:         _onProposalExecuted(sourceChain, sourceAddress, interchainProposalCaller, payload);

66:         emit ProposalExecuted(keccak256(abi.encode(sourceChain, sourceAddress, interchainProposalCaller, payload)));

76:             (bool success, bytes memory result) = call.target.call{ value: call.value }(call.callData);

98:         emit WhitelistedProposalCallerSet(sourceChain, sourceCaller, whitelisted);

113:         emit WhitelistedProposalSenderSet(sourceChain, sourceSender, whitelisted);

178:     function _onTargetExecuted(InterchainCalls.Call memory call, bytes memory result) internal virtual {
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

6: import { IAxelarGasService } from '../gmp-sdk/interfaces/IAxelarGasService.sol';

7: import { IInterchainProposalSender } from './interfaces/IInterchainProposalSender.sol';

59:     function sendProposals(InterchainCalls.InterchainCall[] calldata interchainCalls) external payable override {

85:         _sendProposal(InterchainCalls.InterchainCall(destinationChain, destinationContract, msg.value, calls));

88:     function _sendProposal(InterchainCalls.InterchainCall memory interchainCall) internal {

92:             gasService.payNativeGasForContractCall{ value: interchainCall.gas }(

101:         gateway.callContract(interchainCall.destinationChain, interchainCall.destinationContract, payload);

104:     function revertIfInvalidFee(InterchainCalls.InterchainCall[] calldata interchainCalls) private {
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

7:     event WhitelistedProposalCallerSet(string indexed sourceChain, address indexed sourceCaller, bool whitelisted);

10:     event WhitelistedProposalSenderSet(string indexed sourceChain, address indexed sourceSender, bool whitelisted);
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol

15:     function sendProposals(InterchainCalls.InterchainCall[] memory calls) external payable;
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

6: import { IAxelarGasService } from '../../gmp-sdk/interfaces/IAxelarGasService.sol';

7: import { AxelarExecutable } from '../../gmp-sdk/executable/AxelarExecutable.sol';

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';

21: import { StringToBytes32, Bytes32ToString } from '../../gmp-sdk/util/Bytes32String.sol';

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');

69:     uint256 private constant SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN = 4;

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

98:         remoteAddressValidator = IRemoteAddressValidator(remoteAddressValidator_);

104:         if (tokenManagerImplementations.length != uint256(type(TokenManagerType).max) + 1) revert LengthMismatch();

106:         implementationLockUnlock = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LOCK_UNLOCK);

107:         implementationMintBurn = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.MINT_BURN);

108:         implementationLiquidityPool = _sanitizeTokenManagerImplementation(tokenManagerImplementations, TokenManagerType.LIQUIDITY_POOL);

123:     modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {

124:         if (!remoteAddressValidator.validateSender(sourceChain, sourceAddress)) revert NotRemoteService();

133:         if (msg.sender != getTokenManagerAddress(tokenId)) revert NotTokenManager();

161:     function getTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {

170:     function getValidTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {

172:         if (ITokenManagerProxy(tokenManagerAddress).tokenId() != tokenId) revert TokenManagerDoesNotExist(tokenId);

180:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress) {

191:     function getStandardizedTokenAddress(bytes32 tokenId) public view returns (address tokenAddress) {

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

203:         tokenId = keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_ID, chainNameHash, tokenAddress));

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

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) {

226:         if (TokenManagerType(tokenManagerType) == TokenManagerType.LOCK_UNLOCK) {

228:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.MINT_BURN) {

230:         } else if (TokenManagerType(tokenManagerType) == TokenManagerType.LIQUIDITY_POOL) {

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

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

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit) {

276:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount) {

286:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount) {

296:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

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

311:         if (gateway.tokenAddresses(tokenSymbol) == tokenAddress) revert GatewayToken();

313:         _deployTokenManager(tokenId, TokenManagerType.LOCK_UNLOCK, abi.encode(address(this).toBytes(), 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);

374:         _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params);

397:         _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, mintAmount, msg.sender);

399:         TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;

401:         _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress));

428:         _deployRemoteStandardizedToken(tokenId, name, symbol, decimals, distributor, operator, destinationChain, gasValue);

445:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);

448:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

451:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);

453:         _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);

476:         if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);

479:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

482:         SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);

484:         _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);

486:         _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);

512:             payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount);

514:             emit TokenSent(tokenId, destinationChain, destinationAddress, amount);

520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata);

522:         emit TokenSentWithData(tokenId, destinationChain, destinationAddress, amount, sourceAddress, metadata);

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {

538:             ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i]));

559:     function _sanitizeTokenManagerImplementation(address[] memory implementaions, TokenManagerType tokenManagerType)

566:         if (ITokenManager(implementation).implementationType() != uint256(tokenManagerType)) revert InvalidTokenManagerImplementation();

579:     ) internal override onlyRemoteService(sourceChain, sourceAddress) notPaused {

587:         } else if (selector == SELECTOR_DEPLOY_AND_REGISTER_STANDARDIZED_TOKEN) {

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));

607:         ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));

608:         address expressCaller = _popExpressReceiveToken(tokenId, destinationAddress, amount, commandId);

611:             emit TokenReceived(tokenId, sourceChain, destinationAddress, amount);

622:     function _processSendTokenWithDataPayload(string calldata sourceChain, bytes calldata payload) internal {

635:             (, tokenId, destinationAddressBytes, amount, sourceAddress, data) = abi.decode(

641:         ITokenManager tokenManager = ITokenManager(getTokenManagerAddress(tokenId));

658:         IInterchainTokenExpressExecutable(destinationAddress).executeWithInterchainToken(sourceChain, sourceAddress, data, tokenId, amount);

659:         emit TokenReceivedWithData(tokenId, sourceChain, destinationAddress, amount, sourceAddress, data);

666:     function _processDeployTokenManagerPayload(bytes calldata payload) internal {

667:         (, bytes32 tokenId, TokenManagerType tokenManagerType, bytes memory params) = abi.decode(

678:     function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal {

687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));

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;

696:             abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)

713:         string memory destinationAddress = remoteAddressValidator.getRemoteAddress(destinationChain);

755:         bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params);

757:         emit RemoteTokenManagerDeploymentInitialized(tokenId, destinationChain, gasValue, tokenManagerType, params);

814:             abi.encodeWithSelector(ITokenManagerDeployer.deployTokenManager.selector, tokenId, tokenManagerType, params)

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt) {

869:         emit StandardizedTokenDeployed(tokenId, name, symbol, decimals, mintAmount, mintTo);

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data) {

888:         IInterchainTokenExpressExecutable(destinationAddress).expressExecuteWithInterchainToken(
File: /contracts/its/interchain-token/InterchainToken.sol

21:     function getTokenManager() public view virtual returns (ITokenManager tokenManager);

66:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);

104:         tokenManager.transmitInterchainTransfer{ value: msg.value }(sender, destinationChain, recipient, amount, metadata);
File: /contracts/its/interfaces/IInterchainTokenService.sol

6: import { IAxelarExecutable } from '../../gmp-sdk/interfaces/IAxelarExecutable.sol';

14: interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAxelarExecutable, IPausable, IMulticall {

32:     event TokenSent(bytes32 tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount);

41:     event TokenReceived(bytes32 indexed tokenId, string sourceChain, address indexed destinationAddress, uint256 indexed amount);

67:     event TokenManagerDeployed(bytes32 indexed tokenId, TokenManagerType indexed tokenManagerType, bytes params);

76:     event CustomTokenIdClaimed(bytes32 indexed tokenId, address indexed deployer, bytes32 indexed salt);

82:     function tokenManagerDeployer() external view returns (address tokenManagerDeployerAddress);

88:     function standardizedTokenDeployer() external view returns (address standardizedTokenDeployerAddress);

101:     function getTokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress);

108:     function getValidTokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress);

115:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

122:     function getStandardizedTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

129:     function getCanonicalTokenId(address tokenAddress) external view returns (bytes32 tokenId);

137:     function getCustomTokenId(address operator, bytes32 salt) external view returns (bytes32 tokenId);

145:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) external pure returns (bytes memory params);

153:     function getParamsMintBurn(bytes memory operator, address tokenAddress) external pure returns (bytes memory params);

173:     function registerCanonicalToken(address tokenAddress) external payable returns (bytes32 tokenId);

261:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress);

286:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external;

293:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit);

300:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount);

307:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount);
File: /contracts/its/interfaces/IMulticall.sol

18:     function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool);

32:     function addTrustedAddress(string memory sourceChain, string memory sourceAddress) external;

45:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress);

51:     function supportedByGateway(string calldata chainName) external view returns (bool);

63:     function removeGatewaySupportedChains(string[] calldata chainNames) external;
File: /contracts/its/interfaces/IStandardizedToken.sol

14: interface IStandardizedToken is IInterchainToken, IDistributable, IERC20BurnableMintable {
File: /contracts/its/interfaces/ITokenManager.sol

14: interface ITokenManager is ITokenManagerType, IOperatable, IFlowLimit, IImplementation {

81:     function giveToken(address destinationAddress, uint256 amount) external returns (uint256);
File: /contracts/its/libraries/AddressBytesUtils.sol

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

30:     function toBytes(address addr) internal pure returns (bytes memory bytesAddress) {
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

12:     bytes32 private constant CONTRACT_ID = keccak256('interchain-token-service');
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

12:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');
File: /contracts/its/proxies/StandardizedTokenProxy.sol

7: import { IStandardizedTokenProxy } from '../interfaces/IStandardizedTokenProxy.sol';

21:     constructor(address implementationAddress, bytes memory params) FixedProxy(implementationAddress) {

22:         if (IStandardizedToken(implementationAddress).contractId() != CONTRACT_ID) revert InvalidImplementation();

24:         (bool success, ) = implementationAddress.delegatecall(abi.encodeWithSelector(IStandardizedToken.setup.selector, params));
File: /contracts/its/proxies/TokenManagerProxy.sol

5: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';

31:         interchainTokenServiceAddress = IInterchainTokenService(interchainTokenServiceAddress_);

34:         address impl = _getImplementation(IInterchainTokenService(interchainTokenServiceAddress_), implementationType_);

36:         (bool success, ) = impl.delegatecall(abi.encodeWithSelector(TokenManagerProxy.setup.selector, params));

45:         impl = _getImplementation(interchainTokenServiceAddress, implementationType);

54:     function _getImplementation(IInterchainTokenService interchainTokenServiceAddress_, uint256 implementationType_)

59:         impl = interchainTokenServiceAddress_.getImplementation(implementationType_);

78:             let result := delegatecall(gas(), implementaion_, 0, calldatasize(), 0, 0)
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

4: import { IRemoteAddressValidator } from '../interfaces/IRemoteAddressValidator.sol';

21:     bytes32 private constant CONTRACT_ID = keccak256('remote-address-validator');

30:         interchainTokenServiceAddressHash = keccak256(bytes(_lowerCase(interchainTokenServiceAddress.toString())));

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));

54:     function _lowerCase(string memory s) internal pure returns (string memory) {

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

133:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) {
File: /contracts/its/token-implementations/StandardizedToken.sol

5: import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol';

19: abstract contract StandardizedToken is InterchainToken, ERC20Permit, Implementation, Distributable {

54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));

63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
File: /contracts/its/token-implementations/StandardizedTokenLockUnlock.sol

8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
File: /contracts/its/token-implementations/StandardizedTokenMintBurn.sol

8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
File: /contracts/its/token-manager/TokenManager.sol

6: import { IInterchainTokenService } from '../interfaces/IInterchainTokenService.sol';

18: abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implementation {

28:         if (interchainTokenService_ == address(0)) revert TokenLinkerZeroAddress();

29:         interchainTokenService = IInterchainTokenService(interchainTokenService_);

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

182:     function _takeToken(address from, uint256 amount) internal virtual returns (uint256);

191:     function _giveToken(address from, uint256 amount) internal virtual returns (uint256);
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

7: import { IAxelarGateway } from '../../../gmp-sdk/interfaces/IAxelarGateway.sol';

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

22:     uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba;

28:     function tokenAddress() public view override returns (address tokenAddress_) {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

19:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807;

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

38:         (, address tokenAddress_, address liquidityPool_) = abi.decode(params, (bytes, address, address));

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

82:         SafeTokenTransferFrom.safeTransferFrom(token, from, liquidityPool_, amount);

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

98:         SafeTokenTransferFrom.safeTransferFrom(token, liquidityPool(), to, amount);
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

8: import { SafeTokenTransferFrom, SafeTokenTransfer } from '../../../gmp-sdk/util/SafeTransfer.sol';

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

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

48:         SafeTokenTransferFrom.safeTransferFrom(token, from, address(this), amount);

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
File: /contracts/its/token-manager/implementations/TokenManagerMintBurn.sol

6: import { IERC20BurnableMintable } from '../../interfaces/IERC20BurnableMintable.sol';

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

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

48:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.burn.selector, from, amount));

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

62:         SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20BurnableMintable.mint.selector, to, amount));
File: /contracts/its/utils/Distributable.sol

15:     uint256 internal constant DISTRIBUTOR_SLOT = 0x71c5a35e45a25c49e8f747acd4bcb869814b3d104c492d2554f4c46e12371f56;
File: /contracts/its/utils/ExpressCallHandler.sol

14:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN = 0x67c7b41c1cb0375e36084c4ec399d005168e83425fa471b9224f6115af865619;

16:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA = 0x3e607cc12a253b1d9f677a03d298ad869a90a8ba4bd0fb5739e7d79db7cdeaad;

32:         slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId)));

86:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);

95:         emit ExpressReceive(tokenId, destinationAddress, amount, commandId, expressCaller);

137:         emit ExpressReceiveWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, expressCaller);

154:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);

208:         uint256 slot = _getExpressReceiveTokenSlot(tokenId, destinationAddress, amount, commandId);

216:             emit ExpressExecutionFulfilled(tokenId, destinationAddress, amount, commandId, expressCaller);
File: /contracts/its/utils/FlowLimit.sol

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'));

46:     function _getFlowOutSlot(uint256 epoch) internal pure returns (uint256 slot) {

55:     function _getFlowInSlot(uint256 epoch) internal pure returns (uint256 slot) {

101:         if (flowToAdd + flowAmount > flowToCompare + flowLimit) revert FlowLimitExceeded();
File: /contracts/its/utils/Multicall.sol

22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {

25:             (bool success, bytes memory result) = address(this).delegatecall(data[i]);
File: /contracts/its/utils/Operatable.sol

15:     uint256 internal constant OPERATOR_SLOT = 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d7;
File: /contracts/its/utils/Pausable.sol

14:     uint256 internal constant PAUSE_SLOT = 0xee35723ac350a69d2a92d3703f17439cbaadf2f093a21ba5bf5f1a53eb2a14d8;
File: /contracts/its/utils/StandardizedTokenDeployer.sol

7: import { IStandardizedTokenDeployer } from '../interfaces/IStandardizedTokenDeployer.sol';

31:         if (deployer_ == address(0) || implementationLockUnlockAddress_ == address(0) || implementationMintBurnAddress_ == address(0))

60:         address implementationAddress = distributor == tokenManager ? implementationMintBurnAddress : implementationLockUnlockAddress;

62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo);

63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params));
File: /contracts/its/utils/TokenManagerDeployer.sol

7: import { ITokenManagerDeployer } from '../interfaces/ITokenManagerDeployer.sol';

38:         bytes memory args = abi.encode(address(this), implementationType, tokenId, params);

39:         bytes memory bytecode = abi.encodePacked(type(TokenManagerProxy).creationCode, args);

41:         if (tokenManagerAddress.code.length == 0) revert TokenManagerDeploymentFailed();

[NC-13] Constants should be defined rather than using magic numbers

Proof Of Concept
File: /contracts/its/libraries/AddressBytesUtils.sol

31:         bytesAddress = new bytes(20);

[NC-14] IMPLEMENT SOME TYPE OF VERSION COUNTER THAT WILL BE INCREMENTED AUTOMATICALLY FOR CONTRACT UPGRADES

Description:

I suggest implementing some kind of version counter that will be incremented automatically when you upgrade the contract.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

280:     function upgrade(
File: /contracts/gmp-sdk/interfaces/IUpgradable.sol

18:     function upgrade(
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

52:     function upgrade(

Low Issues

Issue
L-1CRITICAL CHANGES SHOULD USE TWO-STEP PROCEDURE
L-2DECODING AN IPFS HASH USING A FIXED HASH FUNCTION AND LENGTH OF THE HASH
L-3Initializers could be front-run
L-4UNIFY RETURN CRITERIA
L-5REQUIRE MESSAGES ARE TOO SHORT AND UNCLEAR
L-6THE SAFETRANSFER FUNCTION DOES NOT CHECK FOR POTENTIALLY SELF-DESTROYED TOKENS
L-7A SINGLE POINT OF FAILURE
L-8Timestamp Dependence
L-9UNUSED RECEIVE() FUNCTION WILL LOCK ETHER IN CONTRACT
L-10USE _SAFEMINT INSTEAD OF _MINT
L-11USE SAFETRANSFEROWNERSHIP INSTEAD OF TRANSFEROWNERSHIP FUNCTION

[L-1] CRITICAL CHANGES SHOULD USE TWO-STEP PROCEDURE

Description:

The critical procedures should be two step process.

Changing critical addresses in contracts should be a two-step process where the first transaction (from the old/current address) registers the new address (i.e. grants ownership) and the second transaction (from the new address) replaces the old address with the new one (i.e. claims ownership). This gives an opportunity to recover from incorrect addresses mistakenly used in the first step. If not, contract functionality might become inaccessible. (see here and here)

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

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

652:     function _setContractCallApproved(

662:     function _setContractCallApprovedWithMint(

677:     function _setImplementation(address newImplementation) internal {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

92:     function setWhitelistedProposalCaller(

107:     function setWhitelistedProposalSender(
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

38:     function _setTokenAddress(address tokenAddress_) internal {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

47:     function _setLiquidityPool(address liquidityPool_) internal {

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
File: /contracts/its/utils/Distributable.sol

39:     function _setDistributor(address distributor_) internal {

51:     function setDistributor(address distr) external onlyDistributor {
File: /contracts/its/utils/ExpressCallHandler.sol

79:     function _setExpressReceiveToken(

110:     function _setExpressReceiveTokenWithData(
File: /contracts/its/utils/Operatable.sol

39:     function _setOperator(address operator_) internal {

51:     function setOperator(address operator_) external onlyOperator {

Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.

[L-2] DECODING AN IPFS HASH USING A FIXED HASH FUNCTION AND LENGTH OF THE HASH

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

35:     bytes32 internal constant KEY_IMPLEMENTATION = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);

38:     bytes32 internal constant KEY_GOVERNANCE = bytes32(0xabea6fd3db56a6e6d0242111b43ebb13d1c42709651c032c7894962023a1f909);

41:     bytes32 internal constant KEY_MINT_LIMITER = bytes32(0x627f0c11732837b3240a2de89c0b6343512886dd50978b99c76a68c6416a4d92);

509:         return codehash != bytes32(0) && codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

616:         return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, codeHash)))));
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

16:     bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

14:     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

22:     uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba;
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

19:     uint256 internal constant LIQUIDITY_POOL_SLOT = 0x8e02741a3381812d092c5689c9fc701c5185c1742fdf7954c4c4472be4cc4807;
File: /contracts/its/utils/Distributable.sol

15:     uint256 internal constant DISTRIBUTOR_SLOT = 0x71c5a35e45a25c49e8f747acd4bcb869814b3d104c492d2554f4c46e12371f56;
File: /contracts/its/utils/ExpressCallHandler.sol

14:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN = 0x67c7b41c1cb0375e36084c4ec399d005168e83425fa471b9224f6115af865619;

16:     uint256 internal constant PREFIX_EXPRESS_RECEIVE_TOKEN_WITH_DATA = 0x3e607cc12a253b1d9f677a03d298ad869a90a8ba4bd0fb5739e7d79db7cdeaad;
File: /contracts/its/utils/FlowLimit.sol

14:     uint256 internal constant FLOW_LIMIT_SLOT = 0x201b7a0b7c19aaddc4ce9579b7df8d2db123805861bc7763627f13e04d8af42f;
File: /contracts/its/utils/Operatable.sol

15:     uint256 internal constant OPERATOR_SLOT = 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d7;
File: /contracts/its/utils/Pausable.sol

14:     uint256 internal constant PAUSE_SLOT = 0xee35723ac350a69d2a92d3703f17439cbaadf2f093a21ba5bf5f1a53eb2a14d8;

Consider using a more generic implementation that can handle different hash functions and lengths and allow the user to choose.

[L-3] Initializers could be front-run

Description:

Initializers could be front-run, allowing an attacker to either set their own values, take ownership of the contract, and in the best case forcing a re-deployment.

Proof Of Concept
File: /contracts/gmp-sdk/interfaces/IInitProxy.sol

9:     function init(
File: /contracts/gmp-sdk/upgradable/InitProxy.sol

35:     function init(

[L-4] UNIFY RETURN CRITERIA

Description:

In contracts, sometimes the name of the return variable is not defined and sometimes is, unifying the way of writing the code makes the code more uniform and readable.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

132:     ) external view override returns (bool) {

144:     ) external view override returns (bool) {

156:     ) external override returns (bool valid) {

169:     ) external override returns (bool valid) {

183:     function authModule() public view override returns (address) {

187:     function governance() public view override returns (address) {

191:     function mintLimiter() public view override returns (address) {

195:     function tokenDeployer() public view returns (address) {

199:     function tokenMintLimit(string memory symbol) public view override returns (uint256) {

203:     function tokenMintAmount(string memory symbol) public view override returns (uint256) {

209:     function allTokensFrozen() external pure override returns (bool) {

214:     function adminEpoch() external pure override returns (uint256) {

219:     function adminThreshold(uint256) external pure override returns (uint256) {

224:     function admins(uint256) external pure override returns (address[] memory) {

228:     function implementation() public view override returns (address) {

232:     function tokenAddresses(string memory symbol) public view override returns (address) {

238:     function tokenFrozen(string memory) external pure override returns (bool) {

242:     function isCommandExecuted(bytes32 commandId) public view override returns (bool) {

246:     function contractId() public pure returns (bytes32) {

505:     function _hasCode(address addr) internal view returns (bool) {

556:     function _getTokenMintLimitKey(string memory symbol) internal pure returns (bytes32) {

560:     function _getTokenMintAmountKey(string memory symbol, uint256 day) internal pure returns (bytes32) {

565:     function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) {

569:     function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {

573:     function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {

583:     ) internal pure returns (bytes32) {

595:     ) internal pure returns (bytes32) {

615:     function _getCreate2Address(bytes32 salt, bytes32 codeHash) internal view returns (address) {

619:     function _getTokenType(string memory symbol) internal view returns (TokenType) {
File: /contracts/cgp/auth/MultisigBase.sol

87:     function signerThreshold() external view override returns (uint256) {

95:     function signerAccounts() external view override returns (address[] memory) {

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

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

119:     function getSignerVotesCount(bytes32 topic) external view override returns (uint256) {
File: /contracts/cgp/governance/InterchainGovernance.sol

56:     ) external view returns (uint256) {

147:     ) internal pure returns (bytes32) {
File: /contracts/cgp/interfaces/IMultisigBase.sol

32:     function signerEpoch() external view returns (uint256);

38:     function signerThreshold() external view returns (uint256);

44:     function signerAccounts() external view returns (address[] memory);

50:     function isSigner(address account) external view returns (bool);

56:     function hasSignerVoted(address account, bytes32 topic) external view returns (bool);

62:     function getSignerVotesCount(bytes32 topic) external view returns (uint256);
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

24:     function deploy(bytes memory bytecode, bytes32 salt) external returns (address deployedAddress_) {

46:     ) external returns (address deployedAddress_) {

62:     ) external view returns (address deployedAddress_) {

80:     function _deploy(bytes memory bytecode, bytes32 salt) internal returns (address deployedAddress_) {
File: /contracts/gmp-sdk/deploy/Create3.sol

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

71:     function deployedAddress(address sender, bytes32 salt) internal pure returns (address deployed) {
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

29:     function deploy(bytes calldata bytecode, bytes32 salt) external returns (address deployedAddress_) {

53:     ) external returns (address deployedAddress_) {

67:     function deployedAddress(address sender, bytes32 salt) external view returns (address) {
File: /contracts/gmp-sdk/interfaces/IFinalProxy.sol

9:     function isFinal() external view returns (bool);

11:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) external returns (address);
File: /contracts/gmp-sdk/interfaces/IProxy.sol

13:     function implementation() external view returns (address implementation_);
File: /contracts/gmp-sdk/interfaces/ITimeLock.sol

18:     function minimumTimeLockDelay() external view returns (uint256);

25:     function getTimeLock(bytes32 hash) external view returns (uint256);
File: /contracts/gmp-sdk/interfaces/IUpgradable.sol

16:     function implementation() external view returns (address);

26:     function contractId() external pure returns (bytes32);
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

22:     function implementation() public view virtual returns (address implementation_) {

39:     function contractId() internal pure virtual returns (bytes32) {
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

37:     function implementation() public view override(BaseProxy, IProxy) returns (address implementation_) {

48:     function isFinal() public view returns (bool) {

57:     function _finalImplementation() internal view virtual returns (address implementation_) {

72:     function finalUpgrade(bytes memory bytecode, bytes calldata setupParams) public returns (address finalImplementation_) {
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

39:     function implementation() public view returns (address implementation_) {
File: /contracts/gmp-sdk/util/TimeLock.sol

29:     function minimumTimeLockDelay() external view override returns (uint256) {

38:     function getTimeLock(bytes32 hash) external view override returns (uint256) {

50:     function _scheduleTimeLock(bytes32 hash, uint256 eta) internal returns (uint256) {

92:     function _getTimeLockEta(bytes32 hash) internal view returns (uint256 eta) {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

144:     function contractId() external pure returns (bytes32) {

152:     function getChainName() public view returns (string memory name) {

161:     function getTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {

170:     function getValidTokenManagerAddress(bytes32 tokenId) public view returns (address tokenManagerAddress) {

180:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress) {

191:     function getStandardizedTokenAddress(bytes32 tokenId) public view returns (address tokenAddress) {

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

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

223:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress) {

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

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

266:     ) public pure returns (bytes memory params) {

275:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit) {

285:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount) {

295:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount) {

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

347:     ) public payable notPaused returns (bytes32 tokenId) {

371:     ) external payable notPaused returns (bytes32 tokenId) {

562:         returns (address implementation)

728:         returns (

827:     function _getStandardizedTokenSalt(bytes32 tokenId) internal pure returns (bytes32 salt) {

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data) {
File: /contracts/its/interchain-token/InterchainToken.sol

21:     function getTokenManager() public view virtual returns (ITokenManager tokenManager);

32:     function tokenManagerRequiresApproval() public view virtual returns (bool);
File: /contracts/its/interfaces/IDistributable.sol

14:     function distributor() external view returns (address distributor);
File: /contracts/its/interfaces/IExpressCallHandler.sol

58:     ) external view returns (address expressCaller);

79:     ) external view returns (address expressCaller);
File: /contracts/its/interfaces/IFlowLimit.sol

14:     function getFlowLimit() external view returns (uint256 flowLimit);

20:     function getFlowOutAmount() external view returns (uint256 flowOutAmount);

26:     function getFlowInAmount() external view returns (uint256 flowInAmount);
File: /contracts/its/interfaces/IInterchainTokenService.sol

82:     function tokenManagerDeployer() external view returns (address tokenManagerDeployerAddress);

88:     function standardizedTokenDeployer() external view returns (address standardizedTokenDeployerAddress);

94:     function getChainName() external view returns (string memory name);

101:     function getTokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress);

108:     function getValidTokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress);

115:     function getTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

122:     function getStandardizedTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

129:     function getCanonicalTokenId(address tokenAddress) external view returns (bytes32 tokenId);

137:     function getCustomTokenId(address operator, bytes32 salt) external view returns (bytes32 tokenId);

145:     function getParamsLockUnlock(bytes memory operator, address tokenAddress) external pure returns (bytes memory params);

153:     function getParamsMintBurn(bytes memory operator, address tokenAddress) external pure returns (bytes memory params);

166:     ) external pure returns (bytes memory params);

173:     function registerCanonicalToken(address tokenAddress) external payable returns (bytes32 tokenId);

198:     ) external payable returns (bytes32 tokenId);

214:     ) external payable returns (bytes32 tokenId);

261:     function getImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress);

293:     function getFlowLimit(bytes32 tokenId) external view returns (uint256 flowLimit);

300:     function getFlowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount);

307:     function getFlowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount);
File: /contracts/its/interfaces/IMulticall.sol

18:     function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
File: /contracts/its/interfaces/IOperatable.sol

14:     function operator() external view returns (address operator_);
File: /contracts/its/interfaces/IPausable.sol

19:     function isPaused() external view returns (bool);
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool);

45:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress);

51:     function supportedByGateway(string calldata chainName) external view returns (bool);
File: /contracts/its/interfaces/IStandardizedToken.sol

18:     function contractId() external view returns (bytes32);
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

18:     function deployer() external view returns (Create3Deployer);
File: /contracts/its/interfaces/IStandardizedTokenProxy.sol

13:     function contractId() external view returns (bytes32);
File: /contracts/its/interfaces/ITokenManager.sol

26:     function tokenAddress() external view returns (address);

31:     function implementationType() external pure returns (uint256);

81:     function giveToken(address destinationAddress, uint256 amount) external returns (uint256);
File: /contracts/its/interfaces/ITokenManagerDeployer.sol

18:     function deployer() external view returns (Create3Deployer);
File: /contracts/its/interfaces/ITokenManagerProxy.sol

17:     function implementationType() external view returns (uint256);

23:     function implementation() external view returns (address);

28:     function tokenId() external view returns (bytes32);
File: /contracts/its/libraries/AddressBytesUtils.sol

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

30:     function toBytes(address addr) internal pure returns (bytes memory bytesAddress) {
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

29:     function contractId() internal pure override returns (bytes32) {
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

30:     function contractId() internal pure override returns (bytes32) {
File: /contracts/its/proxies/StandardizedTokenProxy.sol

31:     function contractId() external pure returns (bytes32) {
File: /contracts/its/proxies/TokenManagerProxy.sol

44:     function implementation() public view returns (address impl) {

57:         returns (address impl)
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

36:     function contractId() external pure returns (bytes32) {

54:     function _lowerCase(string memory s) internal pure returns (string memory) {

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {

133:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) {
File: /contracts/its/token-implementations/StandardizedToken.sol

32:     function contractId() external pure returns (bytes32) {

40:     function getTokenManager() public view override returns (ITokenManager) {
File: /contracts/its/token-implementations/StandardizedTokenLockUnlock.sol

8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
File: /contracts/its/token-implementations/StandardizedTokenMintBurn.sol

8:     function tokenManagerRequiresApproval() public pure override returns (bool) {
File: /contracts/its/token-manager/TokenManager.sol

53:     function tokenAddress() public view virtual returns (address);

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

182:     function _takeToken(address from, uint256 amount) internal virtual returns (uint256);

191:     function _giveToken(address from, uint256 amount) internal virtual returns (uint256);

204:     function _getTokenId() internal view returns (bytes32 tokenId) {
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

28:     function tokenAddress() public view override returns (address tokenAddress_) {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

28:     function implementationType() external pure returns (uint256) {

57:     function liquidityPool() public view returns (address liquidityPool_) {

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

94:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

24:     function implementationType() external pure returns (uint256) {

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

60:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
File: /contracts/its/token-manager/implementations/TokenManagerMintBurn.sol

25:     function implementationType() external pure returns (uint256) {

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

59:     function _giveToken(address to, uint256 amount) internal override returns (uint256) {
File: /contracts/its/utils/Distributable.sol

29:     function distributor() public view returns (address distr) {
File: /contracts/its/utils/ExpressCallHandler.sol

31:     ) internal pure returns (uint256 slot) {

54:     ) internal pure returns (uint256 slot) {

153:     ) public view returns (address expressCaller) {

179:     ) public view returns (address expressCaller) {

207:     ) internal returns (address expressCaller) {

239:     ) internal returns (address expressCaller) {
File: /contracts/its/utils/FlowLimit.sol

24:     function getFlowLimit() public view returns (uint256 flowLimit) {

46:     function _getFlowOutSlot(uint256 epoch) internal pure returns (uint256 slot) {

55:     function _getFlowInSlot(uint256 epoch) internal pure returns (uint256 slot) {

63:     function getFlowOutAmount() external view returns (uint256 flowOutAmount) {

75:     function getFlowInAmount() external view returns (uint256 flowInAmount) {
File: /contracts/its/utils/Multicall.sol

22:     function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
File: /contracts/its/utils/Operatable.sol

29:     function operator() public view returns (address operator_) {
File: /contracts/its/utils/Pausable.sol

29:     function isPaused() public view returns (bool paused) {

add {return x} if you want to return the updated value or else remove returns(uint) from the function(){} if no value you wanted to return

[L-5] REQUIRE MESSAGES ARE TOO SHORT AND UNCLEAR

Description:

The correct and clear error description explains to the user why the function reverts, but the error descriptions below in the project are not self-explanatory. These error descriptions are very important in the debug features of DApps like Tenderly. Error definitions should be added to the require block, not exceeding 32 bytes.

Proof Of Concept

Error definitions should be added to the require block, not exceeding 32 bytes or we should use custom errors

File: /contracts/gmp-sdk/deploy/Create3.sol

27:                 revert(0, 0)
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

56:                 revert(0, returndatasize())
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

48:                 revert(0, returndatasize())
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

164:                 revert(add(32, result), mload(result))
File: /contracts/its/proxies/TokenManagerProxy.sol

83:                 revert(0, returndatasize())
File: /contracts/its/utils/Multicall.sol

28:                 revert(string(result));

[L-6] THE SAFETRANSFER FUNCTION DOES NOT CHECK FOR POTENTIALLY SELF-DESTROYED TOKENS

Description:

If a pair gets created and after a while one of the tokens gets self-destroyed (maybe because of a bug) then safeTransfer would still succeed. It’s probably a good idea to check if the contract still exists by checking the bytecode length.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

524:             IERC20(tokenAddress).safeTransfer(account, amount);
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

64:         SafeTokenTransfer.safeTransfer(token, to, amount);

[L-7] A SINGLE POINT OF FAILURE

Description:

The owner role has a single point of failure and onlyOwner can use critical a few functions.

Owner is not behind a multisig and changes are not behind a timelock.

Even if protocol admins/developers are not malicious there is still a chance for Owner keys to be stolen. In such a case, the attacker can cause serious damage to the project due to important functions. In such a case, users who have invested in project will suffer high financial losses.

Proof Of Concept
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

56:     ) external override onlyOwner {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

96:     ) external override onlyOwner {

111:     ) external override onlyOwner {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

547:     function setPaused(bool paused) external onlyOwner {
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {

95:     function removeTrustedAddress(string calldata chain) external onlyOwner {

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

Add a time lock to critical functions. Admin-only functions that change critical parameters should emit events and have timelocks.

Events allow capturing the changed parameters so that off-chain tools/interfaces can register such changes with timelocks that allow users to evaluate them and consider if they would like to engage/exit based on how they perceive the changes as affecting the trustworthiness of the protocol or profitability of the implemented financial services.

Allow only multi-signature wallets to call the function to reduce the likelihood of an attack.

https://twitter.com/danielvf/status/1572963475101556738?s=20&t=V1kvzfJlsx-D2hfnG0OmuQ

Also detail them in documentation and NatSpec comments.

[L-8] Timestamp Dependence

Description:

Contracts often need access to time values to perform certain types of functionality. Values such as block.timestamp, and block.number can give you a sense of the current time or a time delta, however, they are not safe to use for most purposes.

In the case of block.timestamp, developers often attempt to use it to trigger time-dependent events. As Ethereum is decentralized, nodes can synchronize time only to some degree. Moreover, malicious miners can alter the timestamp of their blocks, especially if they can gain advantages by doing so. However, miners cant set a timestamp smaller than the previous one (otherwise the block will be rejected), nor can they set the timestamp too far ahead in the future. Taking all of the above into consideration, developers cant rely on the preciseness of the provided timestamp.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

204:         return getUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours));

637:         _setUint(_getTokenMintAmountKey(symbol, block.timestamp / 6 hours), amount);
File: /contracts/cgp/governance/InterchainGovernance.sol

78:         emit ProposalExecuted(proposalHash, target, callData, nativeValue, block.timestamp);
File: /contracts/gmp-sdk/util/TimeLock.sol

54:         uint256 minimumEta = block.timestamp + _minimumTimeLockDelay;

84:         if (block.timestamp < eta) revert TimeLockNotReady();
File: /contracts/its/utils/FlowLimit.sol

64:         uint256 epoch = block.timestamp / EPOCH_TIME;

76:         uint256 epoch = block.timestamp / EPOCH_TIME;

114:         uint256 epoch = block.timestamp / EPOCH_TIME;

127:         uint256 epoch = block.timestamp / EPOCH_TIME;

[L-9] UNUSED RECEIVE() FUNCTION WILL LOCK ETHER IN CONTRACT

Description:

If the intention is for the Ether to be used, the function should call another function, otherwise it should revert

Proof Of Concept
File: /contracts/cgp/governance/InterchainGovernance.sol

168:     receive() external payable {}
File: /contracts/cgp/governance/Multisig.sol

41:     receive() external payable {}
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

67:     receive() external payable virtual {}
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

59:     receive() external payable virtual {}
File: /contracts/its/proxies/TokenManagerProxy.sol

94:     receive() external payable virtual {}

The function should call another function, otherwise it should revert

[L-10] USE _SAFEMINT INSTEAD OF _MINT

Description:

According to openzepplin’s ERC721, the use of _mint is discouraged, use safeMint whenever possible.

https://docs.openzeppelin.com/contracts/3.x/api/token/erc721#ERC721-mint-address-uint256-

Proof Of Concept
File: /contracts/its/token-implementations/StandardizedToken.sol

65:                 _mint(mintTo, mintAmount);

77:         _mint(account, amount);

Use _safeMint whenever possible instead of _mint

[L-11] USE SAFETRANSFEROWNERSHIP INSTEAD OF TRANSFEROWNERSHIP FUNCTION

Description:

transferOwnership function is used to change Ownership from Owned.sol.

Use a 2 structure transferOwnership which is safer.

safeTransferOwnership, use it is more secure due to 2-stage ownership transfer.

Proof Of Concept
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

30:         _transferOwnership(_owner);

Use Ownable2Step.sol

#0 - c4-judge

2023-09-08T11:35:49Z

berndartmueller marked the issue as grade-b

Awards

19.2767 USDC - $19.28

Labels

bug
G (Gas Optimization)
grade-b
G-13

External Links

Gas Optimizations

Issue
GAS-1Use selfbalance() instead of address(this).balance
GAS-2<x> += <y>/<x> -= <y> costs more gas than <x> = <x> + <y>/<x> = <x> - <y> for state variables
GAS-3ABI.ENCODE() IS LESS EFFICIENT THAN ABI.ENCODEPACKED()
GAS-4BEFORE SOME FUNCTIONS, WE SHOULD CHECK SOME VARIABLES FOR POSSIBLE GAS SAVE
GAS-5Using bools for storage incurs overhead
GAS-6<ARRAY>.LENGTH SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR-LOOP
GAS-7Use custom errors rather than revert()/require() strings to save gas
GAS-8USE FUNCTION INSTEAD OF MODIFIERS
GAS-9IT COSTS MORE GAS TO INITIALIZE NON-CONSTANT/NON-IMMUTABLE VARIABLES TO ZERO THAN TO LET THE DEFAULT OF ZERO BE APPLIED
GAS-10MODIFIERS ARE REDUNDANT IF USED ONLY ONCE OR NOT USED AT ALL
GAS-11Multiple address/id mappings can be combined into a single mapping of an address/id to a struct, where appropriate
GAS-12Functions guaranteed to revert when called by normal users can be marked payable
GAS-13Optimize names to save gas
GAS-14++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) = for-loop and while-loops
GAS-15Reorder structure layout
GAS-16TERNARY OPERATION IS CHEAPER THAN IF-ELSE STATEMENT
GAS-17Usage of uint/int smaller than 32 bytes (256 bits) incurs overhead
GAS-18USE BYTES32 INSTEAD OF STRING
GAS-19USING > 0 COSTS MORE GAS THAN != 0 WHEN USED ON A UINT IN A REQUIRE() STATEMENT

[GAS-1] Use selfbalance() instead of address(this).balance

Description:

Use selfbalance() instead of address(this).balance when getting your contract’s balance of ETH to save gas.Use assembly when getting a contract's balance of ETH.

You can use selfbalance() instead of address(this).balance when getting your contract's balance of ETH to save gas. Additionally, you can use balance(address) instead of address.balance() when getting an external contract's balance of ETH.

Proof Of Concept
File: /contracts/cgp/util/Caller.sol

16:         if (nativeValue > address(this).balance) revert InsufficientBalance();

[GAS-2] <x> += <y>/<x> -= <y> costs more gas than <x> = <x> + <y>/<x> = <x> - <y> for state variables

Description:

Using the addition operator instead of plus-equals saves gas

Proof Of Concept
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

107:             totalGas += interchainCalls[i].gas;

[GAS-3] ABI.ENCODE() IS LESS EFFICIENT THAN ABI.ENCODEPACKED()

Description:

Use abi.encodePacked() where possible to save gas

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

562:         return keccak256(abi.encode(PREFIX_TOKEN_MINT_AMOUNT, symbol, day));

584:         return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash));
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

25:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

47:         deployedAddress_ = _deploy(bytecode, keccak256(abi.encode(msg.sender, salt)));

63:         bytes32 newSalt = keccak256(abi.encode(sender, salt));
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

30:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));

54:         bytes32 deploySalt = keccak256(abi.encode(msg.sender, salt));

68:         bytes32 deploySalt = keccak256(abi.encode(sender, salt));
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

66:         emit ProposalExecuted(keccak256(abi.encode(sourceChain, sourceAddress, interchainProposalCaller, payload)));
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

89:         bytes memory payload = abi.encode(msg.sender, interchainCall.calls);
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

203:         tokenId = keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_ID, chainNameHash, tokenAddress));

214:         tokenId = keccak256(abi.encode(PREFIX_CUSTOM_TOKEN_ID, sender, salt));

242:         params = abi.encode(operator, tokenAddress);

252:         params = abi.encode(operator, tokenAddress);

267:         params = abi.encode(operator, tokenAddress, liquidityPoolAddress);

313:         _deployTokenManager(tokenId, TokenManagerType.LOCK_UNLOCK, abi.encode(address(this).toBytes(), tokenAddress));

401:         _deployTokenManager(tokenId, tokenManagerType, abi.encode(msg.sender.toBytes(), tokenAddress));

512:             payload = abi.encode(SELECTOR_SEND_TOKEN, tokenId, destinationAddress, amount);

520:         payload = abi.encode(SELECTOR_SEND_TOKEN_WITH_DATA, tokenId, destinationAddress, amount, sourceAddress.toBytes(), metadata);

696:             abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)

755:         bytes memory payload = abi.encode(SELECTOR_DEPLOY_TOKEN_MANAGER, tokenId, tokenManagerType, params);

828:         return keccak256(abi.encode(PREFIX_STANDARDIZED_TOKEN_SALT, tokenId));
File: /contracts/its/utils/ExpressCallHandler.sol

32:         slot = uint256(keccak256(abi.encode(PREFIX_EXPRESS_RECEIVE_TOKEN, tokenId, destinationAddress, amount, commandId)));
File: /contracts/its/utils/FlowLimit.sol

47:         slot = uint256(keccak256(abi.encode(PREFIX_FLOW_OUT_AMOUNT, epoch)));

56:         slot = uint256(keccak256(abi.encode(PREFIX_FLOW_IN_AMOUNT, epoch)));
File: /contracts/its/utils/StandardizedTokenDeployer.sol

62:             bytes memory params = abi.encode(tokenManager, distributor, name, symbol, decimals, mintAmount, mintTo);

63:             bytecode = abi.encodePacked(type(StandardizedTokenProxy).creationCode, abi.encode(implementationAddress, params));
File: /contracts/its/utils/TokenManagerDeployer.sol

38:         bytes memory args = abi.encode(address(this), implementationType, tokenId, params);

[GAS-4] BEFORE SOME FUNCTIONS, WE SHOULD CHECK SOME VARIABLES FOR POSSIBLE GAS SAVE

Description:

Before transfer, we should check for amount being 0 so the function doesnt run when its not gonna do anything:

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

495:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf {

681:     function _transferGovernance(address newGovernance) internal {

687:     function _transferMintLimiter(address newMintLimiter) internal {

[GAS-5] Using bools for storage incurs overhead

Description:

Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past. See source.

Proof Of Concept
File: /contracts/cgp/auth/MultisigBase.sol

15:         mapping(address => bool) hasVoted;

21:         mapping(address => bool) isSigner;
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

22:     mapping(bytes32 => bool) public multisigApprovals;
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

24:     mapping(string => mapping(address => bool)) public whitelistedCallers;

27:     mapping(string => mapping(address => bool)) public whitelistedSenders;
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

19:     mapping(string => bool) public supportedByGateway;

[GAS-6] <ARRAY>.LENGTH SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR-LOOP

Description:

If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).

Source

Source

Proof Of Concept
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

74:         for (uint256 i = 0; i < calls.length; i++) {
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

63:         for (uint256 i = 0; i < interchainCalls.length; ) {

106:         for (uint256 i = 0; i < interchainCalls.length; ) {
File: /contracts/its/utils/Multicall.sol

24:         for (uint256 i = 0; i < data.length; ++i) {

[GAS-7] Use custom errors rather than revert()/require() strings to save gas

Description:

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they’re hit by avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas.Source Instead of using error strings, to reduce deployment and runtime cost, you should use Custom Errors. This would save both deployment and runtime cost. Source

Proof Of Concept
File: /contracts/gmp-sdk/deploy/Create3.sol

27:                 revert(0, 0)
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

56:                 revert(0, returndatasize())
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

48:                 revert(0, returndatasize())
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

164:                 revert(add(32, result), mload(result))
File: /contracts/its/proxies/TokenManagerProxy.sol

83:                 revert(0, returndatasize())
File: /contracts/its/utils/Multicall.sol

28:                 revert(string(result));

[GAS-8] USE FUNCTION INSTEAD OF MODIFIERS

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

72:     modifier onlySelf() {

78:     modifier onlyGovernance() {

87:     modifier onlyMintLimiter() {
File: /contracts/cgp/auth/MultisigBase.sol

44:     modifier onlySigners() {
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

29:     modifier onlyProxy() {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

123:     modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {

132:     modifier onlyTokenManager(bytes32 tokenId) {
File: /contracts/its/token-manager/TokenManager.sol

35:     modifier onlyService() {

43:     modifier onlyToken() {
File: /contracts/its/utils/Distributable.sol

20:     modifier onlyDistributor() {
File: /contracts/its/utils/Implementation.sol

26:     modifier onlyProxy() {
File: /contracts/its/utils/Operatable.sol

20:     modifier onlyOperator() {
File: /contracts/its/utils/Pausable.sol

20:     modifier notPaused() {

[GAS-9] IT COSTS MORE GAS TO INITIALIZE NON-CONSTANT/NON-IMMUTABLE VARIABLES TO ZERO THAN TO LET THE DEFAULT OF ZERO BE APPLIED

Description:

If a variable is not set/initialized, the default value is assumed (0, false, 0x0 … depending on the data type). You are simply wasting gas if you directly initialize it with its default value.

Proof Of Concept
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

74:         for (uint256 i = 0; i < calls.length; i++) {
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

63:         for (uint256 i = 0; i < interchainCalls.length; ) {

105:         uint256 totalGas = 0;

106:         for (uint256 i = 0; i < interchainCalls.length; ) {
File: /contracts/its/token-manager/TokenManager.sol

118:         uint32 version = 0;
File: /contracts/its/utils/Multicall.sol

24:         for (uint256 i = 0; i < data.length; ++i) {

[GAS-10] MODIFIERS ARE REDUNDANT IF USED ONLY ONCE OR NOT USED AT ALL

Proof Of Concept
File: /contracts/cgp/auth/MultisigBase.sol

44:     modifier onlySigners() {
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

29:     modifier onlyProxy() {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

123:     modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {

132:     modifier onlyTokenManager(bytes32 tokenId) {
File: /contracts/its/token-manager/TokenManager.sol

35:     modifier onlyService() {

43:     modifier onlyToken() {
File: /contracts/its/utils/Distributable.sol

20:     modifier onlyDistributor() {
File: /contracts/its/utils/Implementation.sol

26:     modifier onlyProxy() {
File: /contracts/its/utils/Operatable.sol

20:     modifier onlyOperator() {
File: /contracts/its/utils/Pausable.sol

20:     modifier notPaused() {

[GAS-11] Multiple address/id mappings can be combined into a single mapping of an address/id to a struct, where appropriate

Description:

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key’s keccak256 hash (Gkeccak256 - 30 gas) and that calculation’s associated stack operations. If both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key’s keccak256 hash (Gkeccak256 - 30 gas) and that calculation’s associated stack operations.

Proof Of Concept
File: /contracts/cgp/auth/MultisigBase.sol

15:         mapping(address => bool) hasVoted;

21:         mapping(address => bool) isSigner;

27:     mapping(uint256 => mapping(bytes32 => Voting)) public votingPerTopic;
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

24:     mapping(string => mapping(address => bool)) public whitelistedCallers;

27:     mapping(string => mapping(address => bool)) public whitelistedSenders;
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

15:     mapping(string => bytes32) public remoteAddressHashes;

16:     mapping(string => string) public remoteAddresses;

Make mapping a struct instead

[GAS-12] Functions guaranteed to revert when called by normal users can be marked payable

Description:

If a function modifier such as onlyOwner/onlyX is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

254:     function transferGovernance(address newGovernance) external override onlyGovernance {

260:     function transferMintLimiter(address newMintLimiter) external override onlyMintLimiter {

266:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {

284:     ) external override onlyGovernance {

385:     function deployToken(bytes calldata params, bytes32) external onlySelf {

421:     function mintToken(bytes calldata params, bytes32) external onlySelf {

427:     function burnToken(bytes calldata params, bytes32) external onlySelf {

455:     function approveContractCall(bytes calldata params, bytes32 commandId) external onlySelf {

469:     function approveContractCallWithMint(bytes calldata params, bytes32 commandId) external onlySelf {

495:     function transferOperatorship(bytes calldata newOperatorsData, bytes32) external onlySelf {
File: /contracts/cgp/auth/MultisigBase.sol

142:     function rotateSigners(address[] memory newAccounts, uint256 newThreshold) external virtual onlySigners {
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

52:     ) external payable onlySigners {
File: /contracts/cgp/governance/Multisig.sol

34:     ) external payable onlySigners {
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

56:     ) external override onlyOwner {

78:     function setup(bytes calldata data) external override onlyProxy {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

96:     ) external override onlyOwner {

111:     ) external override onlyOwner {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

509:     ) external payable onlyTokenManager(tokenId) notPaused {

534:     function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {

547:     function setPaused(bool paused) external onlyOwner {

579:     ) internal override onlyRemoteService(sourceChain, sourceAddress) notPaused {
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {

95:     function removeTrustedAddress(string calldata chain) external onlyOwner {

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {
File: /contracts/its/token-implementations/StandardizedToken.sol

49:     function setup(bytes calldata params) external override onlyProxy {

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

86:     function burn(address account, uint256 amount) external onlyDistributor {
File: /contracts/its/token-manager/TokenManager.sol

35:     modifier onlyService() {

43:     modifier onlyToken() {

61:     function setup(bytes calldata params) external override onlyProxy {

142:     ) external payable virtual onlyToken {

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

171:     function setFlowLimit(uint256 flowLimit) external onlyOperator {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

67:     function setLiquidityPool(address newLiquidityPool) external onlyOperator {
File: /contracts/its/utils/Distributable.sol

20:     modifier onlyDistributor() {

51:     function setDistributor(address distr) external onlyDistributor {
File: /contracts/its/utils/Implementation.sol

26:     modifier onlyProxy() {
File: /contracts/its/utils/Operatable.sol

20:     modifier onlyOperator() {

51:     function setOperator(address operator_) external onlyOperator {

[GAS-13] Optimize names to save gas

Description:

public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. In this report are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted.

Solidity optimize name github

Source

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

17: contract AxelarGateway is IAxelarGateway, IGovernable, AdminMultisigBase {
File: /contracts/cgp/auth/MultisigBase.sol

12: contract MultisigBase is IMultisigBase {
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

14: contract AxelarServiceGovernance is InterchainGovernance, MultisigBase, IAxelarServiceGovernance {
File: /contracts/cgp/governance/InterchainGovernance.sol

15: contract InterchainGovernance is AxelarExecutable, TimeLock, Caller, IInterchainGovernance {
File: /contracts/cgp/governance/Multisig.sol

13: contract Multisig is Caller, MultisigBase, IMultisig {
File: /contracts/cgp/interfaces/IAxelarServiceGovernance.sol

12: interface IAxelarServiceGovernance is IMultisigBase, IInterchainGovernance {
File: /contracts/cgp/interfaces/ICaller.sol

5: interface ICaller {
File: /contracts/cgp/interfaces/IMultisig.sol

12: interface IMultisig is ICaller, IMultisigBase {
File: /contracts/cgp/interfaces/IMultisigBase.sol

9: interface IMultisigBase {
File: /contracts/cgp/util/Caller.sol

7: contract Caller is ICaller {
File: /contracts/gmp-sdk/deploy/ConstAddressDeployer.sol

5: contract ConstAddressDeployer {
File: /contracts/gmp-sdk/deploy/Create3.sol

16: contract CreateDeployer {
File: /contracts/gmp-sdk/deploy/Create3Deployer.sol

12: contract Create3Deployer {
File: /contracts/gmp-sdk/interfaces/IFinalProxy.sol

8: interface IFinalProxy is IProxy {
File: /contracts/gmp-sdk/interfaces/IInitProxy.sol

8: interface IInitProxy is IProxy {
File: /contracts/gmp-sdk/interfaces/IProxy.sol

6: interface IProxy {
File: /contracts/gmp-sdk/interfaces/ITimeLock.sol

9: interface ITimeLock {
File: /contracts/gmp-sdk/interfaces/IUpgradable.sol

8: interface IUpgradable is IOwnable {
File: /contracts/gmp-sdk/upgradable/BaseProxy.sol

12: abstract contract BaseProxy is IProxy {
File: /contracts/gmp-sdk/upgradable/FinalProxy.sol

17: contract FinalProxy is Proxy, IFinalProxy {
File: /contracts/gmp-sdk/upgradable/FixedProxy.sol

12: contract FixedProxy is IProxy {
File: /contracts/gmp-sdk/upgradable/InitProxy.sol

16: contract InitProxy is BaseProxy, IInitProxy {
File: /contracts/gmp-sdk/upgradable/Proxy.sol

15: contract Proxy is BaseProxy {
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

12: abstract contract Upgradable is Ownable, IUpgradable {
File: /contracts/gmp-sdk/util/TimeLock.sol

12: contract TimeLock is ITimeLock {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

22: contract InterchainProposalExecutor is IInterchainProposalExecutor, AxelarExecutable, Ownable {
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

38: contract InterchainProposalSender is IInterchainProposalSender {
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

5: interface IInterchainProposalExecutor {
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol

7: interface IInterchainProposalSender {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

37: contract InterchainTokenService is
File: /contracts/its/interchain-token/InterchainToken.sol

15: abstract contract InterchainToken is IInterchainToken, ERC20 {
File: /contracts/its/interfaces/IDistributable.sol

5: interface IDistributable {
File: /contracts/its/interfaces/IExpressCallHandler.sol

5: interface IExpressCallHandler {
File: /contracts/its/interfaces/IFlowLimit.sol

5: interface IFlowLimit {
File: /contracts/its/interfaces/IImplementation.sol

5: interface IImplementation {
File: /contracts/its/interfaces/IInterchainToken.sol

10: interface IInterchainToken is IERC20 {
File: /contracts/its/interfaces/IInterchainTokenService.sol

14: interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAxelarExecutable, IPausable, IMulticall {
File: /contracts/its/interfaces/IMulticall.sol

10: interface IMulticall {
File: /contracts/its/interfaces/IOperatable.sol

5: interface IOperatable {
File: /contracts/its/interfaces/IPausable.sol

10: interface IPausable {
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

9: interface IRemoteAddressValidator {
File: /contracts/its/interfaces/IStandardizedToken.sol

14: interface IStandardizedToken is IInterchainToken, IDistributable, IERC20BurnableMintable {
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

11: interface IStandardizedTokenDeployer {
File: /contracts/its/interfaces/IStandardizedTokenProxy.sol

9: interface IStandardizedTokenProxy {
File: /contracts/its/interfaces/ITokenManager.sol

14: interface ITokenManager is ITokenManagerType, IOperatable, IFlowLimit, IImplementation {
File: /contracts/its/interfaces/ITokenManagerDeployer.sol

11: interface ITokenManagerDeployer {
File: /contracts/its/interfaces/ITokenManagerProxy.sol

10: interface ITokenManagerProxy {
File: /contracts/its/interfaces/ITokenManagerType.sol

9: interface ITokenManagerType {
File: /contracts/its/proxies/InterchainTokenServiceProxy.sol

11: contract InterchainTokenServiceProxy is FinalProxy {
File: /contracts/its/proxies/RemoteAddressValidatorProxy.sol

11: contract RemoteAddressValidatorProxy is Proxy {
File: /contracts/its/proxies/StandardizedTokenProxy.sol

13: contract StandardizedTokenProxy is FixedProxy, IStandardizedTokenProxy {
File: /contracts/its/proxies/TokenManagerProxy.sol

13: contract TokenManagerProxy is ITokenManagerProxy {
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

12: contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
File: /contracts/its/token-implementations/StandardizedToken.sol

19: abstract contract StandardizedToken is InterchainToken, ERC20Permit, Implementation, Distributable {
File: /contracts/its/token-implementations/StandardizedTokenLockUnlock.sol

7: contract StandardizedTokenLockUnlock is StandardizedToken {
File: /contracts/its/token-implementations/StandardizedTokenMintBurn.sol

7: contract StandardizedTokenMintBurn is StandardizedToken {
File: /contracts/its/token-manager/TokenManager.sol

18: abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implementation {
File: /contracts/its/token-manager/implementations/TokenManagerAddressStorage.sol

14: abstract contract TokenManagerAddressStorage is TokenManager {
File: /contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol

17: contract TokenManagerLiquidityPool is TokenManagerAddressStorage {
File: /contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol

16: contract TokenManagerLockUnlock is TokenManagerAddressStorage {
File: /contracts/its/token-manager/implementations/TokenManagerMintBurn.sol

17: contract TokenManagerMintBurn is TokenManagerAddressStorage {
File: /contracts/its/utils/Distributable.sol

13: contract Distributable is IDistributable {
File: /contracts/its/utils/ExpressCallHandler.sol

12: contract ExpressCallHandler is IExpressCallHandler {
File: /contracts/its/utils/FlowLimit.sol

12: contract FlowLimit is IFlowLimit {
File: /contracts/its/utils/Implementation.sol

12: abstract contract Implementation is IImplementation {
File: /contracts/its/utils/Multicall.sol

12: contract Multicall is IMulticall {
File: /contracts/its/utils/Operatable.sol

13: contract Operatable is IOperatable {
File: /contracts/its/utils/Pausable.sol

12: contract Pausable is IPausable {
File: /contracts/its/utils/StandardizedTokenDeployer.sol

15: contract StandardizedTokenDeployer is IStandardizedTokenDeployer {
File: /contracts/its/utils/TokenManagerDeployer.sol

15: contract TokenManagerDeployer is ITokenManagerDeployer {

[GAS-14] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) = for-loop and while-loops

Description:

In Solidity 0.8+, there’s a default overflow check on unsigned integers. It’s possible to uncheck this in for-loops and save some gas at each iteration, but at the cost of some code readability, as this uncheck cannot be made inline.

Proof Of Concept
File: /contracts/cgp/auth/MultisigBase.sol

124:                 voteCount++;
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

74:         for (uint256 i = 0; i < calls.length; i++) {
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

56:         for (uint256 i; i < length; i++) {

[GAS-15] Reorder structure layout

Description:

Structures could be optimized moving the position of certain values in order to save a lot slots.

For example Enums are represented by integers; the possibility listed first by 0, the next by 1, and so forth. An enum type just acts like uintN, where N is the smallest legal value large enough to accomodate all the possibilities.

Source

Source

Proof Of Concept
File: /contracts/cgp/auth/MultisigBase.sol

18:     struct Signers {
            address[] accounts;
            uint256 threshold;
            mapping(address => bool) isSigner;
        }

[GAS-16] TERNARY OPERATION IS CHEAPER THAN IF-ELSE STATEMENT

Description:

There are instances where a ternary operation can be used instead of if-else statement. In these cases, using ternary operation will save modest amounts of gas. Note that this optimization seems to be dependent on usage of a more recent Solidity version. The following gas savings are on version 0.8.17.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

523:    if (_getTokenType(symbol) == TokenType.External) {
            IERC20(tokenAddress).safeTransfer(account, amount);
        } else {
            IBurnableMintableCappedERC20(tokenAddress).mint(account, amount);
        }
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

78:         if (!success) {
                _onTargetExecutionFailed(call, result);
            } else {
                _onTargetExecuted(call, result);
            }
File: /contracts/its/token-manager/TokenManager.sol

68:     if (operatorBytes.length == 0) {
            operator_ = address(interchainTokenService);
        } else {
            operator_ = operatorBytes.toAddress();
        }

[GAS-17] Usage of uint/int smaller than 32 bytes (256 bits) incurs overhead

Description:

When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed. https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed.

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

386:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(

388:             (string, string, uint8, uint256, address, uint256)
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress);

392:         uint8 decimals,

421:         uint8 decimals,

517:         uint32 version;

684:             uint8 decimals,

687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));

731:             uint8 decimals

774:         uint8 decimals,

846:         uint8 decimals,

872:     function _decodeMetadata(bytes calldata metadata) internal pure returns (uint32 version, bytes calldata data) {
File: /contracts/its/interfaces/IInterchainTokenService.sol

29:     error InvalidMetadataVersion(uint32 version);

61:         uint8 tokenDecimals,

72:         uint8 decimals,

229:         uint8 decimals,

249:         uint8 decimals,
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

37:         uint8 decimals,
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

57:             uint8 b = uint8(bytes(s)[i]);

57:             uint8 b = uint8(bytes(s)[i]);

58:             if ((b >= 65) && (b <= 70)) bytes(s)[i] = bytes1(b + uint8(32));
File: /contracts/its/token-implementations/StandardizedToken.sol

25:     uint8 public decimals;

54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));

63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
File: /contracts/its/token-manager/TokenManager.sol

118:         uint32 version = 0;
File: /contracts/its/utils/StandardizedTokenDeployer.sol

55:         uint8 decimals,

[GAS-18] USE BYTES32 INSTEAD OF STRING

Description:

Use bytes32 instead of string to save gas whenever possible. String is a dynamic data structure and therefore is more gas consuming then bytes32.

Code4arena example

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

98:         string calldata destinationChain,

99:         string calldata destinationAddress,

100:         string calldata symbol,

108:         string calldata destinationChain,

109:         string calldata destinationContractAddress,

116:         string calldata destinationChain,

117:         string calldata destinationContractAddress,

119:         string calldata symbol,

128:         string calldata sourceChain,

129:         string calldata sourceAddress,

138:         string calldata sourceChain,

139:         string calldata sourceAddress,

142:         string calldata symbol,

153:         string calldata sourceChain,

154:         string calldata sourceAddress,

164:         string calldata sourceChain,

165:         string calldata sourceAddress,

167:         string calldata symbol,

199:     function tokenMintLimit(string memory symbol) public view override returns (uint256) {

203:     function tokenMintAmount(string memory symbol) public view override returns (uint256) {

232:     function tokenAddresses(string memory symbol) public view override returns (address) {

238:     function tokenFrozen(string memory) external pure override returns (bool) {

266:     function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyMintLimiter {

271:             string memory symbol = symbols[i];

333:         string[] memory commands;

336:         (chainId, commandIds, commands, params) = abi.decode(data, (uint256, bytes32[], string[], bytes[]));

386:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(

386:         (string memory name, string memory symbol, uint8 decimals, uint256 cap, address tokenAddress, uint256 mintLimit) = abi.decode(

388:             (string, string, uint8, uint256, address, uint256)

388:             (string, string, uint8, uint256, address, uint256)

422:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));

422:         (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));

428:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));

428:         (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));

457:             string memory sourceChain,

458:             string memory sourceAddress,

463:         ) = abi.decode(params, (string, string, address, bytes32, bytes32, uint256));

463:         ) = abi.decode(params, (string, string, address, bytes32, bytes32, uint256));

471:             string memory sourceChain,

472:             string memory sourceAddress,

475:             string memory symbol,

479:         ) = abi.decode(params, (string, string, address, bytes32, string, uint256, bytes32, uint256));

479:         ) = abi.decode(params, (string, string, address, bytes32, string, uint256, bytes32, uint256));

479:         ) = abi.decode(params, (string, string, address, bytes32, string, uint256, bytes32, uint256));

513:         string memory symbol,

532:         string memory symbol,

556:     function _getTokenMintLimitKey(string memory symbol) internal pure returns (bytes32) {

560:     function _getTokenMintAmountKey(string memory symbol, uint256 day) internal pure returns (bytes32) {

565:     function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) {

569:     function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {

579:         string memory sourceChain,

580:         string memory sourceAddress,

589:         string memory sourceChain,

590:         string memory sourceAddress,

593:         string memory symbol,

619:     function _getTokenType(string memory symbol) internal view returns (TokenType) {

627:     function _setTokenMintLimit(string memory symbol, uint256 limit) internal {

633:     function _setTokenMintAmount(string memory symbol, uint256 amount) internal {

640:     function _setTokenType(string memory symbol, TokenType tokenType) internal {

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

654:         string memory sourceChain,

655:         string memory sourceAddress,

664:         string memory sourceChain,

665:         string memory sourceAddress,

668:         string memory symbol,
File: /contracts/cgp/governance/AxelarServiceGovernance.sol

35:         string memory governanceChain,

36:         string memory governanceAddress,
File: /contracts/cgp/governance/InterchainGovernance.sol

21:     string public governanceChain;

22:     string public governanceAddress;

35:         string memory governanceChain_,

36:         string memory governanceAddress_,

88:         string calldata sourceChain,

89:         string calldata sourceAddress,

156:         string calldata, /* sourceChain */

157:         string calldata, /* sourceAddress */

159:         string calldata, /* tokenSymbol */
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

24:     mapping(string => mapping(address => bool)) public whitelistedCallers;

27:     mapping(string => mapping(address => bool)) public whitelistedSenders;

42:         string calldata sourceChain,

43:         string calldata sourceAddress,

93:         string calldata sourceChain,

108:         string calldata sourceChain,

127:         string calldata sourceChain,

128:         string calldata sourceAddress,

143:         string calldata, /* sourceChain */

144:         string calldata, /* sourceAddress */
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

81:         string memory destinationChain,

82:         string memory destinationContract,
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalExecutor.sol

7:     event WhitelistedProposalCallerSet(string indexed sourceChain, address indexed sourceCaller, bool whitelisted);

10:     event WhitelistedProposalSenderSet(string indexed sourceChain, address indexed sourceSender, bool whitelisted);

30:         string calldata sourceChain,

42:         string calldata sourceChain,
File: /contracts/interchain-governance-executor/interfaces/IInterchainProposalSender.sol

24:         string calldata destinationChain,

25:         string calldata destinationContract,
File: /contracts/interchain-governance-executor/lib/InterchainCalls.sol

14:         string destinationChain;

15:         string destinationContract;
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

46:     using StringToBytes32 for string;

90:         string memory chainName_

123:     modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {

123:     modifier onlyRemoteService(string calldata sourceChain, string calldata sourceAddress) {

152:     function getChainName() public view returns (string memory name) {

310:         (, string memory tokenSymbol, ) = _validateToken(tokenAddress);

327:         string calldata destinationChain,

333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress);

333:         (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) = _validateToken(tokenAddress);

367:         string calldata destinationChain,

390:         string calldata name,

391:         string calldata symbol,

419:         string calldata name,

420:         string calldata symbol,

424:         string calldata destinationChain,

469:         string memory sourceChain,

505:         string calldata destinationChain,

576:         string calldata sourceChain,

577:         string calldata sourceAddress,

599:     function _processSendTokenPayload(string calldata sourceChain, bytes calldata payload) internal {

622:     function _processSendTokenWithDataPayload(string calldata sourceChain, bytes calldata payload) internal {

682:             string memory name,

683:             string memory symbol,

687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));

687:         ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));

708:         string calldata destinationChain,

713:         string memory destinationAddress = remoteAddressValidator.getRemoteAddress(destinationChain);

729:             string memory name,

730:             string memory symbol,

750:         string calldata destinationChain,

772:         string memory name,

773:         string memory symbol,

777:         string calldata destinationChain,

844:         string memory name,

845:         string memory symbol,

883:         string memory sourceChain,
File: /contracts/its/interchain-token/InterchainToken.sol

44:         string calldata destinationChain,

81:         string calldata destinationChain,
File: /contracts/its/interfaces/IExpressCallHandler.sol

26:         string sourceChain,

36:         string sourceChain,

73:         string memory sourceChain,
File: /contracts/its/interfaces/IInterchainToken.sol

21:         string calldata destinationChain,

39:         string calldata destinationChain,
File: /contracts/its/interfaces/IInterchainTokenService.sol

32:     event TokenSent(bytes32 tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount);

35:         string destinationChain,

41:     event TokenReceived(bytes32 indexed tokenId, string sourceChain, address indexed destinationAddress, uint256 indexed amount);

44:         string sourceChain,

52:         string destinationChain,

59:         string tokenName,

60:         string tokenSymbol,

64:         string destinationChain,

70:         string name,

71:         string symbol,

94:     function getChainName() external view returns (string memory name);

183:         string calldata destinationChain,

210:         string calldata destinationChain,

227:         string calldata name,

228:         string calldata symbol,

247:         string calldata name,

248:         string calldata symbol,

252:         string calldata destinationChain,

275:         string calldata destinationChain,

341:         string memory sourceChain,
File: /contracts/its/interfaces/IRemoteAddressValidator.sol

14:     event TrustedAddressAdded(string souceChain, string sourceAddress);

14:     event TrustedAddressAdded(string souceChain, string sourceAddress);

15:     event TrustedAddressRemoved(string souceChain);

16:     event GatewaySupportedChainAdded(string chain);

17:     event GatewaySupportedChainRemoved(string chain);

25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool);

25:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool);

32:     function addTrustedAddress(string memory sourceChain, string memory sourceAddress) external;

32:     function addTrustedAddress(string memory sourceChain, string memory sourceAddress) external;

38:     function removeTrustedAddress(string calldata sourceChain) external;

45:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress);

45:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress);

51:     function supportedByGateway(string calldata chainName) external view returns (bool);

57:     function addGatewaySupportedChains(string[] calldata chainNames) external;

63:     function removeGatewaySupportedChains(string[] calldata chainNames) external;
File: /contracts/its/interfaces/IStandardizedTokenDeployer.sol

35:         string calldata name,

36:         string calldata symbol,
File: /contracts/its/interfaces/ITokenManager.sol

40:         string calldata destinationChain,

54:         string calldata destinationChain,

69:         string calldata destinationChain,
File: /contracts/its/remote-address-validator/RemoteAddressValidator.sol

15:     mapping(string => bytes32) public remoteAddressHashes;

16:     mapping(string => string) public remoteAddresses;

16:     mapping(string => string) public remoteAddresses;

19:     mapping(string => bool) public supportedByGateway;

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));

41:         (string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(params, (string[], string[]));

54:     function _lowerCase(string memory s) internal pure returns (string memory) {

54:     function _lowerCase(string memory s) internal pure returns (string memory) {

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {

69:     function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {

70:         string memory sourceAddressLC = _lowerCase(sourceAddress);

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {

83:     function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {

95:     function removeTrustedAddress(string calldata chain) external onlyOwner {

106:     function addGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

109:             string calldata chainName = chainNames[i];

119:     function removeGatewaySupportedChains(string[] calldata chainNames) external onlyOwner {

122:             string calldata chainName = chainNames[i];

133:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) {

133:     function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) {
File: /contracts/its/token-implementations/StandardizedToken.sol

23:     string public name;

24:     string public symbol;

53:             string memory tokenName;

54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));

54:             (tokenManager_, distributor_, tokenName, symbol, decimals) = abi.decode(params, (address, address, string, string, uint8));

63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));

63:             (, , , , , mintAmount, mintTo) = abi.decode(params, (address, address, string, string, uint8, uint256, address));
File: /contracts/its/token-manager/TokenManager.sol

84:         string calldata destinationChain,

110:         string calldata destinationChain,

138:         string calldata destinationChain,
File: /contracts/its/utils/ExpressCallHandler.sol

48:         string memory sourceChain,

112:         string memory sourceChain,

173:         string memory sourceChain,

233:         string memory sourceChain,
File: /contracts/its/utils/Multicall.sol

28:                 revert(string(result));
File: /contracts/its/utils/StandardizedTokenDeployer.sol

53:         string calldata name,

54:         string calldata symbol,

[GAS-19] USING > 0 COSTS MORE GAS THAN != 0 WHEN USED ON A UINT IN A REQUIRE() STATEMENT

Description:

When dealing with unsigned integer types, comparisons with != 0 are cheaper then with > 0. This change saves 6 gas per instance

Proof Of Concept
File: /contracts/cgp/AxelarGateway.sol

635:         if (limit > 0 && amount > limit) revert ExceedMintLimit(symbol);
File: /contracts/gmp-sdk/upgradable/Upgradable.sol

60:         if (params.length > 0) {
File: /contracts/interchain-governance-executor/InterchainProposalExecutor.sol

161:         if (result.length > 0) {
File: /contracts/interchain-governance-executor/InterchainProposalSender.sol

91:         if (interchainCall.gas > 0) {
File: /contracts/its/interchain-token-service/InterchainTokenService.sol

519:         if (version > 0) revert InvalidMetadataVersion(version);

690:         address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress;

714:         if (gasValue > 0) {
File: /contracts/its/token-implementations/StandardizedToken.sol

64:             if (mintAmount > 0) {

#0 - c4-judge

2023-09-04T19:22:51Z

berndartmueller marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter