When a user withdraws the native token through the Cross Domain Messenger, the L1 result is that the token is approved, a callback is sent to the target address, and then the approval is removed. Since EOAs cannot act on a callback, the result is that all withdrawals of a native token to an EOA target will fail.
Root Cause
When native token is withdrawn through the Cross Domain Messenger, we send the tokens by (a) approving the token to the target address, (b) calling the target address with arbitrary calldata, and (c) revoking the approval. Here is the implementation:
This pattern requires that the receiver is a contract with the ability to call safeTransfer() on the native token during that callback. This is of course not possible for EOAs, for whom the above call will be a no-op.
As issue similar to this seems to be mentioned in the Known Issues:
"Especially, in case of _tx.data.length is not 0 and _tx.data includes function relayMessage(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _minGasLimit, bytes calldata _message), user may lose funds even if _sender is EOA"
But that issue focuses on the _sender being an EOA.
This issue highlights the 100% losses that will occur in the event that the _target is an EOA.
Internal Preconditions
None
External Preconditions
None
Attack Path
Any funds are sent to the L2 Cross Domain Messenger with _to as an L1 EOA address.
Impact
Anyone withdrawing a native token to an EOA wallet will lose their funds.
PoC
N/A
Mitigation
There are numerous possible solutions here. Some top contenders I'd recommend considering:
1) If the address is an EOA (or if some flag is set in the withdrawal), send the funds instead of approving them.
2) Keep the approvals set after the relayMessage() call, so the EOA can transfer them later (this would require using something like increaseAllowance() instead of approve()).
obront
High
All native token withdrawals to EOA will fail
Summary
When a user withdraws the native token through the Cross Domain Messenger, the L1 result is that the token is approved, a callback is sent to the target address, and then the approval is removed. Since EOAs cannot act on a callback, the result is that all withdrawals of a native token to an EOA target will fail.
Root Cause
When native token is withdrawn through the Cross Domain Messenger, we send the tokens by (a) approving the token to the target address, (b) calling the target address with arbitrary calldata, and (c) revoking the approval. Here is the implementation:
This pattern requires that the receiver is a contract with the ability to call
safeTransfer()
on the native token during that callback. This is of course not possible for EOAs, for whom the above call will be a no-op.As issue similar to this seems to be mentioned in the Known Issues:
But that issue focuses on the
_sender
being an EOA.This issue highlights the 100% losses that will occur in the event that the
_target
is an EOA.Internal Preconditions
None
External Preconditions
None
Attack Path
_to
as an L1 EOA address.Impact
Anyone withdrawing a native token to an EOA wallet will lose their funds.
PoC
N/A
Mitigation
There are numerous possible solutions here. Some top contenders I'd recommend considering: 1) If the address is an EOA (or if some flag is set in the withdrawal), send the funds instead of approving them. 2) Keep the approvals set after the
relayMessage()
call, so the EOA can transfer them later (this would require using something likeincreaseAllowance()
instead ofapprove()
).