Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

Partial‐Approve Revert Vulnerability in UniswapV2Adapter

Summary

Zaros documentation states that the protocol will support USDT deposits that can be used as collateral for margin accounts.

The UniswapV2Adapter contract can revert on swap operations for tokens like USDT that have a non‐standard allowance mechanism. USDT historically reverts if you attempt to change an existing non‐zero allowance to another non‐zero value. Consequently, a leftover allowance or dust balance of USDT in the adapter can break all subsequent approvals.

Although the Zaros protocol vaults are not currently configured to accept USDT, the published documentation states that USDT support will be added. As of now, if USDT were used with the UniswapV2Adapter, it could cause DoS‐type reverts and prevent any further USDT swaps.

Vulnerability Details

USDT’s ERC‐20 implementation reverts on partial approval changes. Specifically, if the adapter already has a non‐zero allowance for USDT, a subsequent call to:

IERC20(tokenIn).approve(uniswapV2SwapStrategyRouter, amountIn);

where amountIn != 0, reverts under USDT’s rules unless the allowance is first reset to zero. This means a malicious actor (or an accidental leftover) could deposit a small USDT amount into the adapter, leaving a non‐zero allowance. Next time the adapter tries to set a new allowance for USDT, the transaction fails.

As a result, all USDT swaps will become blocked, causing a denial of service for that token. This vulnerability is specific to USDT or any similarly non‐compliant token.

The UniswapV2Adapter code repeatedly does:

IERC20(swapPayload.tokenIn).approve(router, swapPayload.amountIn);

With no zero‐allowance reset.

A malicious user can “dust” 1 unit of USDT or rely on leftover allowance, causing subsequent approvals to revert.

Impact

If the Zaros protocol adds USDT vaults or otherwise enables USDT liquidity, internal swap operations will be vulnerable to failure for USDT once an allowance mismatch arises.

Tools Used

Solodit + Manual Review

Recommendations

Before calling approve(newAmount), ensure allowance is zero if it is non‐zero:

uint256 currentAllowance = IERC20(token).allowance(address(this), router);
if (currentAllowance != 0) {
IERC20(token).approve(router, 0);
}
// Then set infinite or the exact newAmount
IERC20(token).approve(router, type(uint256).max);
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.