Skip to content

Latest commit

 

History

History
86 lines (62 loc) · 2.71 KB

067.md

File metadata and controls

86 lines (62 loc) · 2.71 KB

Muscular Ceramic Dragonfly

Medium

An attacker can frontrun trades due to missing checks in Bracket.sol

Summary

The missing check in Bracket.sol will cause a complete loss of funds for users as an attacker will frontrun their transactions to exploit the lack of validation after executing trades.

Root Cause

In Bracket.sol:526, there is a missing check for the success of the call to the swap target.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. The user calls performUpkeep() to execute a trade.
  2. The contract attempts to execute the swap call without validating the success of the call.
  3. An attacker observes the transaction and frontruns it, adjusting the swap parameters to their advantage.
  4. The trade either fails or executes unfavorably for the user, leading to a loss of funds.

Impact

The users suffer an approximate loss of their funds due to unfavorable trades executed by the attacker.

PoC

No response

Mitigation

function execute(
        address target,
        bytes memory txData,
        uint256 amountIn,
        IERC20 tokenIn,
        IERC20 tokenOut,
        uint16 bips
    ) internal returns (uint256 swapAmountOut, uint256 tokenInRefund) {
        //update accounting
        uint256 initialTokenIn = tokenIn.balanceOf(address(this));
        uint256 initialTokenOut = tokenOut.balanceOf(address(this));

        //approve
        tokenIn.safeApprove(target, amountIn);

        //perform the call
    (bool success, bytes memory result) = target.call(txData);  
    require(success, "Swap execution failed"); // Check for successful execution  

        if (success) {
            uint256 finalTokenIn = tokenIn.balanceOf(address(this));
            require(finalTokenIn >= initialTokenIn - amountIn, "over spend");
            uint256 finalTokenOut = tokenOut.balanceOf(address(this));

            //if success, we expect tokenIn balance to decrease by amountIn
            //and tokenOut balance to increase by at least minAmountReceived
            require(
                finalTokenOut - initialTokenOut >
                    MASTER.getMinAmountReceived(
                        amountIn,
                        tokenIn,
                        tokenOut,
                        bips
                    ),
                "Too Little Received"
            );

            swapAmountOut = finalTokenOut - initialTokenOut;
            tokenInRefund = amountIn - (initialTokenIn - finalTokenIn);
        } else {
            //force revert
            revert TransactionFailed(result);
        }
    }