Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwapAction::getSwapToken will return wrong swap token for balancer EXACT_OUT swaps #248

Open
howlbot-integration bot opened this issue Aug 20, 2024 · 2 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working M-03 primary issue Highest quality submission among a set of duplicates 🤖_primary AI based primary recommendation 🤖_50_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") sufficient quality report This report is of sufficient quality

Comments

@howlbot-integration
Copy link

Lines of code

https://github.com/code-423n4/2024-07-loopfi/blob/main/src/proxy/SwapAction.sol#L320-L330

Vulnerability details

Impact

As known, when doing a Balancer EXACT_OUT batch swap, assets should be passed in reverse order, this is thoroughly documented here.

Swapping in USDC for an exact amount out of BAL
swapType = EXACT_OUT and assets = [BAL, WETH, DAI, USDC]:

However, in SwapAction::getSwapToken, for Balancer swaps it always returns the last asset in the assets array, which is correct for EXACT_IN but wrong for EXACT_OUT, where it should be the first asset in the assets array.

Proof of Concept

function test_wrongSwapTokenReturned() public {
    uint256 amount = 200 ether;

    deal(address(token), user, amount);
    deal(address(underlyingToken), user, amount);

    address[] memory assets = new address[](2);
    assets[0] = address(underlyingToken);
    assets[1] = address(token);

    SwapParams memory swapParams = SwapParams({
        swapProtocol: SwapProtocol.BALANCER,
        swapType: SwapType.EXACT_OUT,
        assetIn: address(token),
        amount: 1 ether,
        limit: 2 ether,
        recipient: user,
        deadline: block.timestamp,
        args: abi.encode(weightedPoolIdArray, assets)
    });

    vm.startPrank(user);

    token.approve(address(swapAction), amount);
    underlyingToken.approve(address(swapAction), amount);

    uint256 tokenBalanceBefore = token.balanceOf(address(user));
    uint256 underlyingTokenBalanceBefore = underlyingToken.balanceOf(address(user));

    // Swap token for underlying token, using EXACT_OUT
    swapAction.transferAndSwap(user, emptyPermitParams, swapParams);

    uint256 tokenBalanceAfter = token.balanceOf(address(user));
    uint256 underlyingTokenBalanceAfter = underlyingToken.balanceOf(address(user));

    // Verify that the out token is the underlying token
    assertLt(tokenBalanceAfter, tokenBalanceBefore);
    assertGt(underlyingTokenBalanceAfter, underlyingTokenBalanceBefore);

    // `getSwapToken` returns the out token as `token` which is wrong
    assertEq(swapAction.getSwapToken(swapParams), address(token));

    vm.stopPrank();
}

Tools Used

Manual review

Recommended Mitigation Steps

Add the following in SwapAction::getSwapToken:

if (swapParams.swapType == SwapType.EXACT_OUT) token = primarySwapPath[0];
else token = primarySwapPath[primarySwapPath.length - 1];

Assessed type

Error

@howlbot-integration howlbot-integration bot added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value 🤖_50_group AI based duplicate group recommendation 🤖_primary AI based primary recommendation bug Something isn't working primary issue Highest quality submission among a set of duplicates sufficient quality report This report is of sufficient quality labels Aug 20, 2024
howlbot-integration bot added a commit that referenced this issue Aug 20, 2024
@amarcu amarcu added the sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") label Sep 19, 2024
@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Sep 25, 2024
@c4-judge
Copy link
Contributor

koolexcrypto marked the issue as satisfactory

@c4-judge
Copy link
Contributor

c4-judge commented Oct 2, 2024

koolexcrypto marked the issue as selected for report

@c4-judge c4-judge added the selected for report This submission will be included/highlighted in the audit report label Oct 2, 2024
@C4-Staff C4-Staff added the M-03 label Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working M-03 primary issue Highest quality submission among a set of duplicates 🤖_primary AI based primary recommendation 🤖_50_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

3 participants