Fund can be lost if the L1 call value provided is insufficient to cover maxSubmissionCost_.
OutboundTransfer in L1Sender does not check if the call value is sufficient.
Vulnerability Details
function sendDepositToken(
uint256 gasLimit_,
uint256 maxFeePerGas_,
uint256 maxSubmissionCost_
) external payable onlyDistribution returns (bytes memory) {
DepositTokenConfig storage config = depositTokenConfig;
uint256 amountUnwrappedToken_ = IERC20(unwrappedDepositToken).balanceOf(address(this));
uint256 amount_ = IWStETH(config.token).wrap(amountUnwrappedToken_);
bytes memory data_ = abi.encode(maxSubmissionCost_, "");
return
IGatewayRouter(config.gateway).outboundTransfer{value: msg.value}(
config.token,
config.receiver,
amount_,
gasLimit_,
maxFeePerGas_,
data_
);
}
Recommendations
Add check similar to the one used in L1GatewayRouter provided by Arbitrum team
https://github.com/OffchainLabs/arbitrum/blob/b8366005a697000dda1f57a78a7bdb2313db8fe2/packages/arb-bridge-peripherals/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L236
uint256 expectedEth = _maxSubmissionCost + (_maxGas * _gasPriceBid);
require(_maxSubmissionCost > 0, "NO_SUBMISSION_COST");
require(msg.value == expectedEth, "WRONG_ETH_VALUE");