Axelar Network v2 contest - Bnke0x0's results

Decentralized interoperability network.

General Information

Platform: Code4rena

Start Date: 29/07/2022

Pot Size: $50,000 USDC

Total HM: 6

Participants: 75

Period: 5 days

Judge: GalloDaSballo

Total Solo HM: 3

Id: 149

League: ETH

Axelar Network

Findings Distribution

Researcher Performance

Rank: 14/75

Findings: 2

Award: $195.99

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

[L-01] Unused receive() function will lock Ether in contract :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositReceiver.sol#L29 :

    receive() external payable {}

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L13 :

    receive() external payable override {}

[L-02] Missing checks for address(0x0) when assigning values to address state variables :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L37 :

    xc20Codehash = codehash_;

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L45 :

    xc20Codehash = newCodehash;

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L52 :

    'AUTH_MODULE = authModule;'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L53 :

    TOKEN_DEPLOYER_IMPLEMENTATION = tokenDeployerImplementation;

  5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L24 :

    gateway = gateway_;

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L27 :

    gatewayAddress = gatewayAddress_;

[L-03] address.call{value:x}() should be used instead of payable.transfer() :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L63 :

    payable(msg.sender).transfer(address(this).balance);

[L-04] approve should be replaced with safeApprove or safeIncreaseAllowance() / safeDecreaseAllowance() :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L30 :

    IERC20(wrappedTokenAddress).approve(gateway, amount);

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/ReceiverImplementation.sol#L38 :

    IERC20(tokenAddress).approve(gateway, amount);

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/ReceiverImplementation.sol#L64 :

    'IERC20(wrappedTokenAddress).approve(gateway, amount);'

[L-05] Low level calls don’t check for contract existence :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L320 :

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

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L460#L463 :

    function _callERC20Token(address tokenAddress, bytes memory callData) internal returns (bool) { (bool success, bytes memory returnData) = tokenAddress.call(callData); return success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); }

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L158 :

    '(bool success, bytes memory returnData) = tokenAddress.call(abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount));'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L172#L174 :

    (bool success, bytes memory returnData) = tokenAddress.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount) );

  5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L71 :

    (bool success, bytes memory returnData) = tokenAddress.call(abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount));

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L95 :

    (bool success, bytes memory returnData) = tokenAddress.call(abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount));

  7. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L106#L108 :

    (bool success, bytes memory returnData) = tokenAddress.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount) );

[L-06] an unbounded loop on array can lead to DoS :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L123L#124 :

    for (uint256 i; i < tokens.length; i++) { address token = tokens[i];

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L168#L169 :

    for (uint256 i; i < refundTokens.length; i++) { refundToken = refundTokens[i];

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L116#L120 :

    'for (uint256 i; i < accounts.length - 1; ++i) { if (accounts[i] >= accounts[i + 1]) { return false; } }'

[N-01] Adding a return statement when the function defines a named return variable, is redundant:-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L182 :

    return _adminEpoch();

[N-02] require()/revert() statements should have descriptive reason strings :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L55#L58 :

    revert('NotAxelarToken()'); revert('NotXc20Token()'); revert('AlreadyWrappingAxelarToken()'); revert('AlreadyWrappingXC20Token()');

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L60#L61 :

    revert('NotOwner()'); revert('CannotSetMetadata()');

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L68 :

    'revert('NotAxelarToken()');'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L70 :

    revert('NotWrappingToken()');

  5. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L78#L79 :

    revert('NotAxelarToken()'); revert('CannotMint()');

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L84#L86 :

    revert('NotXc20Token()'); revert('InsufficientBalance()'); revert('CannotBurn()');

  7. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L98 :

    'revert('TransferFailed()');'

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L111 :

    revert('TransferFailed()');

[N-03] Use a more recent version of solidity (Use a solidity version of at least 0.8.12 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>)) :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L3 :

    pragma solidity 0.8.9;

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L3 :

    pragma solidity 0.8.9;

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L3 :

    'pragma solidity 0.8.9;'

[N-04] Event is missing indexed fields (Each event should use three indexed fields if there are three or more fields) :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarGasService.sol#L13#L57 :

    ` event GasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress );

    event GasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress );

    event NativeGasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress );

    event NativeGasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress );

    event GasAdded(bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress);

    event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress);`

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarAuthWeighted.sol#L14 :

    event OperatorshipTransferred(address[] newOperators, uint256[] newWeights, uint256 newThreshold);

[N-05] Use of sensitive/non-inclusive terms :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L496 :

    bool burnSuccess;

[N-06] public functions not called by the contract should be declared external instead () :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L152#L178 :

    ` function tokenDailyMintLimit(string memory symbol) public view override returns (uint256) { return getUint(_getTokenDailyMintLimitKey(symbol)); }

    function tokenDailyMintAmount(string memory symbol) public view override returns (uint256) { return getUint(_getTokenDailyMintAmountKey(symbol, block.timestamp / 1 days)); }

    function allTokensFrozen() external pure override returns (bool) { return false; }

    function implementation() public view override returns (address) { return getAddress(KEY_IMPLEMENTATION); }

    function tokenAddresses(string memory symbol) public view override returns (address) { return getAddress(_getTokenAddressKey(symbol)); }

    function tokenFrozen(string memory) external pure override returns (bool) { return false; }

    function isCommandExecuted(bytes32 commandId) public view override returns (bool) { return getBool(_getIsCommandExecutedKey(commandId)); }`

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L56#L61 :

    function addressForNativeDeposit( bytes32 salt, address refundAddress, string calldata destinationChain, string calldata destinationAddress ) public view returns (address) {

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L241 :

    'function contractId() public pure returns (bytes32) {'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L41#L47 :

    ` function wrappedToken() public view returns (address) { return IAxelarGateway(gateway).tokenAddresses(wrappedSymbol()); }

    // @dev Converts bytes32 from immutable storage into a string function wrappedSymbol() public view returns (string memory symbol) { bytes32 symbolData = wrappedSymbolBytes;`

  5. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L30#L32 :

    'function gateway() public view override returns (IAxelarGateway) { return IAxelarGateway(gatewayAddress); }'

  6. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L40#L42 :

    ' function contractId() public pure returns (bytes32) { return keccak256('xc20-wrapper'); }'

[N-07] public functions not called by the contract should be declared external instead () :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IDepositBase.sol#L5 :

    interface IDepositBase {

[N-08] public functions not called by the contract should be declared external instead () :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L4 :

    uint8 internal constant OLD_KEY_RETENTION = 16;

[N-09] Use a more recent version of solidity :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L1 :

    // SPDX-License-Identifier: MIT

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IDepositBase.sol#L1 :

    // SPDX-License-Identifier: MIT

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L1 :

    '// SPDX-License-Identifier: MIT'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasServiceProxy.sol#L1 :

    // SPDX-License-Identifier: MIT

  5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarAuth.sol#L1 :

    // SPDX-License-Identifier: MIT

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarGasService.sol#L1 :

    // SPDX-License-Identifier: MIT

  7. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarDepositService.sol#L1 :

    '// SPDX-License-Identifier: MIT'

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarAuthWeighted.sol#L1 :

    // SPDX-License-Identifier: MIT

  9. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositReceiver.sol#L1 :

    // SPDX-License-Identifier: MIT

  10. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L1 :

    // SPDX-License-Identifier: MIT

  11. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L1 :

    '// SPDX-License-Identifier: MIT'

  12. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/ReceiverImplementation.sol#L1 :

    // SPDX-License-Identifier: MIT

  13. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L1 :

    // SPDX-License-Identifier: MIT

  14. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L1 :

    // SPDX-License-Identifier: MIT

  15. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L1 :

    '// SPDX-License-Identifier: MIT'

#0 - re1ro

2022-08-05T02:20:45Z

L1

Dup #2

L2

Dup #3

L3

Dup #4

L4

Dup #3

L5

Good spot

sponsor confirmed

Almost all those functions have code length check in the end tokenAddress.code.length == 0

Only .2 is valid _callERC20Token https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L460#L463

Mitigated

https://github.com/axelarnetwork/axelar-cgp-solidity/pull/138

L6

Not applicable. Those functions are called by out services with a small arrays

N1

Dup #13

N2

Dup #13

N3

Dup #3

N4

You can't index strings without loosing the data

N5

Ack

N6 - N8

Those are used in the contract

N9

Dup #3

#1 - GalloDaSballo

2022-08-28T22:09:50Z

[L-01] Unused receive() function will lock Ether in contract :-

L because of DepositService, the one for deposit Receiver is used by WETH

[L-02] Missing checks for address(0x0) when assigning values to address state variables :-

L

[L-03] address.call{value:x}() should be used instead of payable.transfer() :-

L

[L-04] approve should be replaced with safeApprove or safeIncreaseAllowance() / safeDecreaseAllowance() :-

L

[L-05] Low level calls don’t check for contract existence :-

Only applies to this, rest has the check https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/AxelarGateway.sol#L460

[L-06] an unbounded loop on array can lead to DoS :-

These are self-inflicted and easily avoidable - NC

[N-01] Adding a return statement when the function defines a named return variable, is redundant:-

Looks invalid

[N-02] require()/revert() statements should have descriptive reason strings :-

Disagree, descriptions are fine

[N-03] Use a more recent version of solidity (Use a solidity version of at least 0.8.12 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>)) :-

NC

[N-04] Event is missing indexed fields (Each event should use three indexed fields if there are three or more fields) :-

Disputed in lack of an example of what should be indexed

[N-05] Use of sensitive/non-inclusive terms :-

Disputed

[N-06] public functions not called by the contract should be declared external instead () :-

NC

[N-07] public functions not called by the contract should be declared external instead () :-

Wrong

4L 3NC

[G-01] State variables only set in the constructor should be declared immutable:-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L23 :

    bytes32 public xc20Codehash;

[G-02] x = x + y is cheaper than x += y :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L70 :

    totalWeight += newWeights[i];

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L105:

    weight += weights[operatorIndex];

[G-03] <array>.length should not be looked up in every loop of a for-loop :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L207 :

    for (uint256 i = 0; i < symbols.length; i++) {

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L123 :

    for (uint256 i; i < tokens.length; i++) {

  3. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L114 :

    for (uint256 i; i < refundTokens.length; i++) {

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L168 :

    for (uint256 i; i < refundTokens.length; i++) {

  5. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L204 :

    for (uint256 i; i < refundTokens.length; i++) {

  6. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L17 :

    for (uint256 i; i < recentOperators.length; ++i) {

  7. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L98 :

    for (uint256 i = 0; i < signatures.length; ++i) {

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L116 :

    for (uint256 i; i < accounts.length - 1; ++i) {

[G-04] Use prefix not postfix in loops (Using a prefix increment (++i) instead of a postfix increment (i++) saves gas for each loop cycle and so can have a big gas impact when the loop executes on a large number of elements.) :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L207 :

    for (uint256 i = 0; i < symbols.length; i++) {

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L123 :

    for (uint256 i; i < tokens.length; i++) {

  3. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L114 :

    for (uint256 i; i < refundTokens.length; i++) {

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L168 :

    for (uint256 i; i < refundTokens.length; i++) {

  5. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L204 :

    for (uint256 i; i < refundTokens.length; i++) {

  6. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L17 :

    for (uint256 i; i < recentOperators.length; ++i) {

  7. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L98 :

    for (uint256 i = 0; i < signatures.length; ++i) {

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L116 :

    for (uint256 i; i < accounts.length - 1; ++i) {

  9. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L195 :

    for (uint256 i; i < adminCount; ++i) {

  10. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L292 :

    ffor (uint256 i; i < commandsLength; ++i) {

  11. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L69 :

    for (uint256 i = 0; i < weightsLength; ++i) {

[G-05] Not using the named return variables when a function returns, wastes deployment gas :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L182 :

    return _adminEpoch();

[G-06] It costs more gas to initialize variables to zero than to let the default of zero be applied :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L207 :

    for (uint256 i = 0; i < symbols.length; i++) {

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L98 :

    for (uint256 i = 0; i < signatures.length; ++i) {

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L116 :

  4. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L69 :

    for (uint256 i = 0; i < weightsLength; ++i) {

[G-07] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L14 :

    uint8 internal constant OLD_KEY_RETENTION = 16;

[G-08] Expressions for constant values such as a call to keccak256(), should use immutable rather than constant :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L30#L43 :

    `bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed'); bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address'); bytes32 internal constant PREFIX_TOKEN_TYPE = keccak256('token-type'); bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED = keccak256('contract-call-approved'); bytes32 internal constant PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT = keccak256('contract-call-approved-with-mint'); bytes32 internal constant PREFIX_TOKEN_DAILY_MINT_LIMIT = keccak256('token-daily-mint-limit'); bytes32 internal constant PREFIX_TOKEN_DAILY_MINT_AMOUNT = keccak256('token-daily-mint-amount');

bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken');
bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken'); bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken'); bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL = keccak256('approveContractCall'); bytes32 internal constant SELECTOR_APPROVE_CONTRACT_CALL_WITH_MINT = keccak256('approveContractCallWithMint'); bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship');`

[G-09] Use custom errors rather than revert()/require() strings to save deployment gas :-

  1. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L55#L58 :

    revert('NotAxelarToken()'); revert('NotXc20Token()'); revert('AlreadyWrappingAxelarToken()'); revert('AlreadyWrappingXC20Token()');

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L60#L61 :

    revert('NotOwner()'); revert('CannotSetMetadata()');

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L68 :

    'revert('NotAxelarToken()');'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L70 :

    revert('NotWrappingToken()');

  5. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L78#L79 :

    revert('NotAxelarToken()'); revert('CannotMint()');

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L84#L86 :

    revert('NotXc20Token()'); revert('InsufficientBalance()'); revert('CannotBurn()');

  7. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L98 :

    'revert('TransferFailed()');'

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L111 :

    revert('TransferFailed()');

[G-09] Functions guaranteed to revert when called by normal users can be marked payable (If a function modifier such as onlyOwner 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.) :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L204 :

    function setTokenDailyMintLimits(string[] calldata symbols, uint256[] calldata limits) external override onlyAdmin {

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L217#L221 :

    function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata setupParams ) external override onlyAdmin {

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L331 :

    'function deployToken(bytes calldata params, bytes32) external onlySelf {'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L367 :

    function mintToken(bytes calldata params, bytes32) external onlySelf {

  5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L373 :

    function burnToken(bytes calldata params, bytes32) external onlySelf {

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L397 :

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

  7. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L411 :

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

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L437 :

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

  9. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L120 :

    function collectFees(address payable receiver, address[] calldata tokens) external onlyOwner {

  10. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L136#L140 :

    function refund( address payable receiver, address token, uint256 amount ) external onlyOwner {

  11. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L47 :

    'function transferOperatorship(bytes calldata params) external onlyOwner {'

  12. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L44 :

    function setXc20Codehash(bytes32 newCodehash) external onlyOwner {

  13. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L48#L53 :

    function addWrapping( string calldata symbol, address xc20Token, string memory newName, string memory newSymbol ) external payable onlyOwner {

  14. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L66 :

    function removeWrapping(string calldata symbol) external onlyOwner {

  15. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L411 :

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

  16. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L437 :

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

[G-10] Use a more recent version of solidity :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L3 :

    pragma solidity 0.8.9;

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IDepositBase.sol#L3 :

    pragma solidity 0.8.9;

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L3 :

    'pragma solidity 0.8.9;'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasServiceProxy.sol#L3 :

    pragma solidity 0.8.9;

  5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarAuth.sol#L3 :

    pragma solidity 0.8.9;

  6. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarGasService.sol#L3 :

    pragma solidity 0.8.9;

  7. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarDepositService.sol#L3 :

    'pragma solidity 0.8.9;'

  8. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/interfaces/IAxelarAuthWeighted.sol#L3 :

    pragma solidity 0.8.9;

  9. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositReceiver.sol#L3 :

    pragma solidity 0.8.9;

  10. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositService.sol#L3 :

    pragma solidity 0.8.9;

  11. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositBase.sol#L3 :

    'pragma solidity 0.8.9;'

  12. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/ReceiverImplementation.sol#L3 :

    pragma solidity 0.8.9;

  13. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L3 :

    pragma solidity 0.8.9;

  14. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L3 :

    pragma solidity 0.8.9;

  15. File: https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L3 :

    'pragma solidity 0.8.9;'

[G-11] internal functions only called once can be inlined to save gas :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L460 :

    function _callERC20Token(address tokenAddress, bytes memory callData) internal returns (bool) {

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L465#L469 :

    function _mintToken( string memory symbol, address account, uint256 amount ) internal {

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L485#L489 :

    'function _burnTokenFrom( address sender, string memory symbol, uint256 amount ) internal {'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L539#L557 :

    `function _getTokenDailyMintLimitKey(string memory symbol) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PREFIX_TOKEN_DAILY_MINT_LIMIT, symbol)); }

function _getTokenDailyMintAmountKey(string memory symbol, uint256 day) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(PREFIX_TOKEN_DAILY_MINT_AMOUNT, symbol, day)); } function _getTokenTypeKey(string memory symbol) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PREFIX_TOKEN_TYPE, symbol)); } function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PREFIX_TOKEN_ADDRESS, symbol)); } function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId)); }`

5. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/AxelarGateway.sol#L559#L658 :

` function _getIsContractCallApprovedKey( bytes32 commandId, string memory sourceChain, string memory sourceAddress, address contractAddress, bytes32 payloadHash ) internal pure returns (bytes32) { return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); } function _getIsContractCallApprovedWithMintKey( bytes32 commandId, string memory sourceChain, string memory sourceAddress, address contractAddress, bytes32 payloadHash, string memory symbol, uint256 amount ) internal pure returns (bytes32) { return keccak256( abi.encode( PREFIX_CONTRACT_CALL_APPROVED_WITH_MINT, commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount ) ); } /********************\ |* Internal Getters *| \********************/ function _getTokenType(string memory symbol) internal view returns (TokenType) { return TokenType(getUint(_getTokenTypeKey(symbol))); } /********************\ |* Internal Setters *| \********************/ function _setTokenDailyMintLimit(string memory symbol, uint256 limit) internal { _setUint(_getTokenDailyMintLimitKey(symbol), limit); emit TokenDailyMintLimitUpdated(symbol, limit); } function _setTokenDailyMintAmount(string memory symbol, uint256 amount) internal { uint256 limit = tokenDailyMintLimit(symbol); if (limit > 0 && amount > limit) revert ExceedDailyMintLimit(symbol); _setUint(_getTokenDailyMintAmountKey(symbol, block.timestamp / 1 days), amount); } function _setTokenType(string memory symbol, TokenType tokenType) internal { _setUint(_getTokenTypeKey(symbol), uint256(tokenType)); } function _setTokenAddress(string memory symbol, address tokenAddress) internal { _setAddress(_getTokenAddressKey(symbol), tokenAddress); } function _setCommandExecuted(bytes32 commandId, bool executed) internal { _setBool(_getIsCommandExecutedKey(commandId), executed); } function _setContractCallApproved( bytes32 commandId, string memory sourceChain, string memory sourceAddress, address contractAddress, bytes32 payloadHash ) internal { _setBool(_getIsContractCallApprovedKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash), true); } function _setContractCallApprovedWithMint( bytes32 commandId, string memory sourceChain, string memory sourceAddress, address contractAddress, bytes32 payloadHash, string memory symbol, uint256 amount ) internal { _setBool( _getIsContractCallApprovedWithMintKey(commandId, sourceChain, sourceAddress, contractAddress, payloadHash, symbol, amount), true ); } function _setImplementation(address newImplementation) internal { _setAddress(KEY_IMPLEMENTATION, newImplementation); }

}`

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L150#L154 :

    function _safeTransfer( address tokenAddress, address receiver, uint256 amount ) internal {

  2. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/gas-service/AxelarGasService.sol#L164#L168 :

    'function _safeTransferFrom( address tokenAddress, address from, uint256 amount ) internal {'

[G-12] Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/xc20/contracts/XC20Wrapper.sol#L20#L21 :

    mapping(address => address) public wrapped; mapping(address => address) public unwrapped;

[G-13] Empty blocks should be removed or emit something :-

  1. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/DepositReceiver.sol#L29 :

    receive() external payable {}

  2. https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L13 :

    receive() external payable override {}

  3. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/deposit-service/ReceiverImplementation.sol#L12 :

    'constructor(address gateway, string memory wrappedSymbol) DepositBase(gateway, wrappedSymbol) {}'

  4. File: https://github.com/code-423n4/2022-07-axelar/blob/main/contracts/auth/AxelarAuthWeighted.sol#L101 :

    for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {}

#0 - re1ro

2022-08-05T00:20:36Z

1

Not applicable. There is setXc20Codehash() that changes the storage.

2

Yup. Dup #2

3

Yup. Dup #2

4

Yup. Dup #2

5

Correct. Good spot

6

Yup. Dup #2

7

Yup. Dup #7

8

Yup. Dup #12

9

Good spot

Mitigated

https://github.com/axelarnetwork/axelar-xc20-wrapper/pull/4

9.5

Yup. Dup #7

#10 Dup #3

#11 We prefer cleaner code.

#12 Not applicable. Dup #2

#13 Not applicable. Dup #2

#1 - GalloDaSballo

2022-08-20T22:30:33Z

[G-01] State variables only set in the constructor should be declared immutable:-

Contracts are upgradeable, cannot be done

[G-08] Expressions for constant values such as a call to keccak256(), should use immutable rather than constant :-

Not true https://twitter.com/GalloDaSballo/status/1543729080926871557

Less than 500 gas saved in total

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