Clumsy Topaz Pigeon USDT KNC Swaps Limited To First Swapper

by gitftunila 60 views
Iklan Headers

Introduction

In the realm of decentralized exchanges (DEXs), the seamless swapping of tokens is paramount. However, a critical issue has been identified within the DexSwap protocol, specifically affecting the usage of USDT and KNC as fromToken. This vulnerability, dubbed "Clumsy Topaz Pigeon," stems from the way the Permit2 contract interacts with tokens like USDT and KNC, which have unique approval behaviors. This article delves into the intricacies of this issue, its root cause, potential impact, and possible mitigation strategies. Understanding this issue is crucial for anyone involved in decentralized finance (DeFi) and token swapping protocols.

Summary of the Vulnerability

The core of the problem lies in the interaction between DexSwap's UniAdapter and the Permit2 contract when dealing with specific tokens like USDT and KNC. These tokens have a characteristic behavior where they do not allow approving an amount M > 0 when an existing amount N > 0 is already approved. According to the contest README, a token is considered valid if it possesses over 500,000 USDC in liquidity on various DEXs, including Uniswap V2-V4. This includes USDT, which has a WETH/USDT pool on Uniswap v3. The issue arises because the allowance granted by Permit2 to the Uniswap router may not be fully utilized during the first swap operation. This can occur if the price limit in the pool is reached, preventing the entire fromTokenAmount from being consumed. Consequently, subsequent swap attempts using the same fromToken (USDT or KNC) will fail, as the approve() function in Permit2 will revert due to the existing unspent allowance. This effectively restricts the usage of USDT/KNC as fromToken to the first swapper only, posing a significant limitation to the protocol's functionality.

Root Cause Analysis

The root cause of this vulnerability is found in UniAdapter.sol:42-44. In this section of the code, Permit2 is used to approve the Uni_Router. The problem is that the allowance granted might not be fully used by the router during a swap. This incomplete usage is particularly problematic for tokens like USDT and KNC, which, as mentioned earlier, do not permit increasing an existing allowance. The Uniswap V3 pool's behavior, as shown in the following snippet, illustrates why this can happen:

// continue swapping as long as we haven't used the entire input/output and haven't reached the price limit
while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {

This code segment demonstrates that the swap continues only as long as the entire input/output amount hasn't been used and the price limit hasn't been reached. If the price limit is hit before the full fromTokenAmount is utilized, the allowance remains partially unspent. The consequence is that subsequent swap attempts with USDT or KNC as fromToken are doomed to fail. Only the first swapper benefits, creating a bottleneck in the protocol's usability. This limitation directly contradicts the intended functionality of a decentralized and permissionless exchange, highlighting the severity of the issue.

Detailed Explanation of the Problem

The heart of the issue lies in the specific logic implemented by tokens like USDT and KNC for handling allowances. Unlike standard ERC-20 tokens, these tokens often prevent an increase in allowance if an existing allowance is already set. This design choice, intended to mitigate certain attack vectors, inadvertently introduces a compatibility issue with the Permit2 approval mechanism used in DexSwap. When a user initiates a swap using USDT or KNC as the fromToken, UniAdapter utilizes Permit2 to grant an allowance to the Uniswap router. However, if the swap doesn't consume the entire allowance (e.g., due to slippage or price limits), a residual allowance remains. Subsequent swap attempts by other users or even the same user will then fail because the Permit2 approve() function will revert when trying to increase the allowance, as the token's logic prohibits such operations. This creates a scenario where only the first swap using USDT or KNC as fromToken succeeds, effectively blocking subsequent swaps and severely impacting the usability of the DexSwap protocol. The interplay between the token's unique allowance behavior and the Permit2 mechanism is the crux of this vulnerability, underscoring the need for a robust solution to ensure seamless token swapping.

Attack Path: A Step-by-Step Scenario

To illustrate the vulnerability, consider the following attack scenario:

  1. Bob's Initial Swap: Bob wants to swap 2500 USDT for 1 WETH on the WETH/USDT pool on Uniswap.
  2. DexSwap and UniAdapter: Bob calls the swap() function on DexSwap, which utilizes UniAdapter to facilitate the trade.
  3. Partial Allowance Usage: The allowance granted by Permit2 to the Uniswap Router is not fully consumed during Bob's swap, perhaps due to price slippage or the trade hitting a price limit.
  4. Bob's Successful Swap: Bob's swap is successfully executed.
  5. Alice's Subsequent Swap: Alice now wants to swap 5000 USDT for 1 WETH on the same WETH/USDT pool.
  6. DexSwap and UniAdapter (Again): Alice calls the swap() function on DexSwap, again using UniAdapter.
  7. Approval Failure: Alice's call fails because Permit2's approve() function for the router reverts. This is because the previous allowance granted to the router by Bob's swap was not fully used, and USDT does not allow increasing an existing allowance.

This scenario highlights how the residual allowance from Bob's transaction prevents Alice from executing her swap, demonstrating the vulnerability's real-world impact. The failure stems from the interaction between the partial allowance consumption and the token's specific allowance rules, resulting in a critical disruption of the swap functionality.

Impact Assessment

The impact of this vulnerability is significant. The primary consequence is that unused allowance from previous swaps can lead to the failure of subsequent swap() executions. This limitation severely restricts the usability of USDT and KNC as fromToken within the DexSwap protocol, essentially rendering them unusable after the first swap. This is a critical issue because USDT is a major stablecoin, and its restriction greatly diminishes the protocol's utility for a broad range of users. Moreover, this issue extends beyond just USDT and KNC; it affects any token with similar allowance behavior, potentially impacting a significant portion of the tokens available for swapping. The disruption to swap functionality not only inconveniences users but also undermines the protocol's reputation and trustworthiness. The inability to reliably swap commonly used tokens like USDT can deter users from engaging with DexSwap, leading to a loss of volume and market share. Therefore, addressing this vulnerability is crucial for ensuring the protocol's long-term viability and success in the DeFi ecosystem.

Note: This issue also affects UniswapV4Executor under the same scenario, indicating a systemic problem within the interaction between the Permit2 mechanism and tokens with specific allowance behaviors across different executors.

Mitigation Strategies

While the original report doesn't provide specific mitigation strategies, several approaches can be considered to address this vulnerability. One potential solution is to implement a mechanism that resets the allowance after each swap. This could involve explicitly setting the allowance to zero after a swap transaction completes, ensuring that subsequent swaps start with a clean slate. Another approach is to use a different approval mechanism that is compatible with tokens that don't allow increasing allowances. This might involve using a