Assessment reports>WOOFi Swap>Informational findings>Bridge fee only charged on convenience swap
Category: Business Logic

Bridge fee only charged on convenience swap

Informational Severity
Informational Impact
High Likelihood

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.

Zellic © 2024Back to top ↑