Bridge fee only charged on convenience swap
Description
The function crossSwap
is called on WooCrossChainRouterV4 to initiate a cross-chain swap:
function crossSwap(
uint256 refId,
address payable to,
SrcInfos memory srcInfos,
DstInfos calldata dstInfos,
Src1inch calldata src1inch,
Dst1inch calldata dst1inch
) external payable whenNotPaused nonReentrant {
// [...]
uint256 fee = 0;
// Step 1: transfer
// [...]
// Step 2: local swap by 1inch router
if (srcInfos.fromToken != srcInfos.bridgeToken) {
TransferHelper.safeApprove(srcInfos.fromToken, address(wooRouter), srcInfos.fromAmount);
if (src1inch.swapRouter != address(0)) {
// external swap via 1inch
bridgeAmount = wooRouter.externalSwap(
src1inch.swapRouter,
src1inch.swapRouter,
srcInfos.fromToken,
srcInfos.bridgeToken,
srcInfos.fromAmount,
srcInfos.minBridgeAmount,
payable(address(this)),
src1inch.data
);
fee = (bridgeAmount * srcExternalFeeRate) / FEE_BASE;
} else {
// swap via WOOFi
bridgeAmount = wooRouter.swap(
srcInfos.fromToken,
srcInfos.bridgeToken,
srcInfos.fromAmount,
srcInfos.minBridgeAmount,
payable(address(this)),
to
);
}
} else {
require(
srcInfos.fromAmount == srcInfos.minBridgeAmount,
"WooCrossChainRouterV4: !srcInfos.minBridgeAmount"
);
bridgeAmount = srcInfos.fromAmount;
}
// Step 3: deduct the swap fee
bridgeAmount -= fee;
require(bridgeAmount >= srcInfos.minBridgeAmount, "WooCrossChainRouterV4: !srcInfos.minBridgeAmount");
// Step 4: cross chain swap by StarGateRouter
_bridgeByStargate(refId, to, msgValue, bridgeAmount, srcInfos, dstInfos, dst1inch);
// [...]
}
Note that the bridge charges an additional fee
of the srcExternalFeeRate
only when an external swap is done on the source chain before bridging.
However, a user can just do the same swap externally before calling the bridge and avoid this fee. Note that the external swap itself could charge fees, and if it does, those fees would be on top of the fee
charged here.
Impact
This fee can be avoided by users externally doing the swap themselves.
Recommendations
We recommend charging a fee to use the bridge, instead of charging a fee to transactionally externally swap before using the bridge and allowing users who notice this discrepancy to essentially use the bridge for free. This fee model better aligns the charged fee with what the users are deriving value from.
Remediation
Additionally, the WOOFI team has stated that:
It is by design. And we only charge the fee for external swap in destination chain, and decided in the meeting to not charge extra bridge fee.