Description
The createChannelWithPermit function is flawed. It correctly uses permit to grant an allowance from the payer to address(this). However, it then calls the internal _createERC20Channel function, which is hardcoded to use msg.sender for all allowance checks and safeTransferFrom calls.
In the permit flow, msg.sender can be relayer (any arbitrary address), not the payer who signed the permit. As a result, the allowance check will fail, and the safeTransferFrom will attempt to pull tokens from the relayer's address, not the payer's.
Code snippet
// Inside _createERC20Channel
uint256 allowance = IERC20(token).allowance(msg.sender, address(this));
if (allowance < amount) revert InsufficientAllowance(amount, allowance);
// Pull tokens from payer into this contract
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
Recommendation
Refactor the internal channel creation functions (_createERC20Channel, _createNativeChannel, and _initChannel) to accept payer as an argument.
createChannel should call them with msg.sender as the payer.
createChannelWithPermit should call them with the payer address provided as an argument.
_createERC20Channel must then use this payer argument (instead of msg.sender) in its allowance check and safeTransferFrom call.
Description
The
createChannelWithPermitfunction is flawed. It correctly uses permit to grant an allowance from thepayertoaddress(this). However, it then calls the internal_createERC20Channelfunction, which is hardcoded to usemsg.senderfor allallowancechecks andsafeTransferFromcalls.In the permit flow,
msg.sendercan berelayer(any arbitrary address), not thepayerwho signed the permit. As a result, theallowancecheck will fail, and thesafeTransferFromwill attempt to pull tokens from the relayer's address, not the payer's.Code snippet
Recommendation
Refactor the internal channel creation functions (
_createERC20Channel,_createNativeChannel, and_initChannel) to acceptpayeras an argument.createChannelshould call them with msg.sender as the payer.createChannelWithPermitshould call them with thepayeraddress provided as an argument._createERC20Channelmust then use thispayerargument (instead ofmsg.sender) in itsallowancecheck andsafeTransferFromcall.