Muscular Ceramic Dragonfly
Medium
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.
In Bracket.sol:526, there is a missing check for the success of the call to the swap target.
No response
No response
- The user calls performUpkeep() to execute a trade.
- The contract attempts to execute the swap call without validating the success of the call.
- An attacker observes the transaction and frontruns it, adjusting the swap parameters to their advantage.
- The trade either fails or executes unfavorably for the user, leading to a loss of funds.
The users suffer an approximate loss of their funds due to unfavorable trades executed by the attacker.
No response
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);
}
}