Lucene search

K
code423n4Code4renaCODE423N4:2022-07-AXELAR-FINDINGS-ISSUES-165
HistoryAug 03, 2022 - 12:00 a.m.

Did Not Approve To Zero First

2022-08-0300:00:00
Code4rena
github.com
8

Lines of code
<https://github.com/code-423n4/2022-07-axelar/blob/3729dd4aeff8dc2b8b9c3670a1c792c81fc60e7c/contracts/deposit-service/ReceiverImplementation.sol#L38&gt;
<https://github.com/code-423n4/2022-07-axelar/blob/3729dd4aeff8dc2b8b9c3670a1c792c81fc60e7c/contracts/deposit-service/ReceiverImplementation.sol#L44&gt;

Vulnerability details

Some ERC20 tokens (like USDT) do not work when changing the allowance from an existing non-zero allowance value. For example Tether (USDT)'s approve() function will revert if the current approval is not zero, to protect against front-running changes of approvals.

The following functions approve the gateway to send the tokens on their behalf. However, if the token involved is an ERC20 token that does not work when changing the allowance from an existing non-zero allowance value, it will break the following key functions or features of the protocol. For instance, users will not be able to send certain ERC20 tokens to another chain via Axelar’s DepositService.

<https://github.com/code-423n4/2022-07-axelar/blob/3729dd4aeff8dc2b8b9c3670a1c792c81fc60e7c/contracts/deposit-service/AxelarDepositService.sol#L23&gt;

function sendNative(string calldata destinationChain, string calldata destinationAddress) external payable {
    address wrappedTokenAddress = wrappedToken();
    uint256 amount = msg.value;

    if (amount == 0) revert NothingDeposited();

    IWETH9(wrappedTokenAddress).deposit{ value: amount }();
    IERC20(wrappedTokenAddress).approve(gateway, amount);
    IAxelarGateway(gateway).sendToken(destinationChain, destinationAddress, wrappedSymbol(), amount);
}

<https://github.com/code-423n4/2022-07-axelar/blob/3729dd4aeff8dc2b8b9c3670a1c792c81fc60e7c/contracts/deposit-service/ReceiverImplementation.sol#L38&gt;

// @dev This function is used for delegate by DepositReceiver deployed above
// Context: msg.sender == AxelarDepositService, this == DepositReceiver
function receiveAndSendToken(
    address payable refundAddress,
    string calldata destinationChain,
    string calldata destinationAddress,
    string calldata symbol
) external {
	..SNIP..
    // Sending the token trough the gateway
    IERC20(tokenAddress).approve(gateway, amount);
    IAxelarGateway(gateway).sendToken(destinationChain, destinationAddress, symbol, amount);
}

<https://github.com/code-423n4/2022-07-axelar/blob/3729dd4aeff8dc2b8b9c3670a1c792c81fc60e7c/contracts/deposit-service/ReceiverImplementation.sol#L44&gt;

function receiveAndSendNative(
    address payable refundAddress,
    string calldata destinationChain,
    string calldata destinationAddress
) external {
    ..SNIP..
    // Wrapping the native currency and sending WETH-like token through the gateway
    IWETH9(wrappedTokenAddress).deposit{ value: amount }();
    IERC20(wrappedTokenAddress).approve(gateway, amount);
    IAxelarGateway(gateway).sendToken(destinationChain, destinationAddress, wrappedSymbol(), amount);
}

Recommendation

It is recommended to set the allowance to zero before increasing the allowance and use safeApprove/safeIncreaseAllowance.

SafeERC20.safeApprove(tokenAddress, gateway, 0);
SafeERC20.safeIncreaseAllowance(tokenAddress, gateway, amount);  

The text was updated successfully, but these errors were encountered:

All reactions