Inconsistent handling of native token
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↗.