Assessment reports>Odos Cross-Chain Contracts>High findings>Inconsistent handling of native token
Category: Coding Mistakes

Inconsistent handling of native token

High Impact
High Severity
High Likelihood

Description

The OdosRouter and AcrossHook contracts use the zero address to represent the native token when interacting with the SpokePool contract. When the input token is the zero address, these contracts call the SpokePool's deposit function with value in Ether.

function _executeSpokePoolCall(address inputToken, uint256 amount, bytes memory callData) internal {
    if (inputToken != address(0)) {
        IERC20(inputToken).safeIncreaseAllowance(spokePool, amount);
    }

    (bool success, bytes memory returnData) = spokePool.call{value: inputToken == address(0) ? amount : 0}(callData);
// [...]

However, the SpokePool contract expects the WETH address for native token operations. The deposit function uses msg.value to convert Ether to WETH only when the input token matches the WETH address; otherwise, it requires msg.value to be 0. Consequently, transactions using the zero address as the input token will be reverted.

if (params.inputToken == address(wrappedNativeToken).toBytes32() && msg.value > 0) {
    if (msg.value != params.inputAmount) revert MsgValueDoesNotMatchInputAmount();
    wrappedNativeToken.deposit{ value: msg.value }();
    // Else, it is a normal ERC20. In this case pull the token from the caller as per normal.
    // Note: this includes the case where the L2 caller has WETH (already wrapped ETH) and wants to bridge them.
    // In this case the msg.value will be set to 0, indicating a "normal" ERC20 bridging action.
} else {
    // msg.value should be 0 if input token isn't the wrapped native token.
    if (msg.value != 0) revert MsgValueDoesNotMatchInputAmount();
// [....]

Impact

All transactions using the zero address as the input token will fail due to the incompatible native-token handling between the AcrossHook and SpokePool contracts. This misalignment violates the core design requirement that token addresses should not be zero, as specified in the AcrossHandler's invariants.

Recommendations

Replace the zero address with the WETH address when interacting with the SpokePool contract to maintain consistency with the SpokePool's native-token--handling mechanism.

Remediation

This issue has been acknowledged by Odos, and a fix was implemented in PR #3.

Zellic © 2025Back to top ↑