Stratax Contracts

First Flight #57
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Tether (USDT) Non-Standard ERC20 Behavior Can Cause Flash Loan Reverts and Protocol Denial of Service

Tether (USDT) Non-Standard ERC20 Behavior Can Cause Flash Loan Reverts and Protocol Denial of Service

Description:

The Stratax contract performs multiple direct calls to IERC20.transfer, transferFrom, and approve, assuming strict ERC-20 compliance (i.e., returning bool and supporting standard allowance behavior).

However, Tether (USDT), issued by Tether Limited, is a well-known non-standard ERC-20 implementation with the following characteristics:

  • transfer and transferFrom may not return a boolean value.

  • approve may revert if attempting to change a non-zero allowance directly to another non-zero value.

  • It does not strictly comply with the expected ERC-20 return value behavior.

The contract includes multiple unsafe calls such as:

IERC20(_token).transfer(...)
IERC20(_token).transferFrom(...)
IERC20(_token).approve(...)

without:

  • Using SafeERC20

  • Verifying return values

  • Resetting allowance to zero before updating it

When interacting with USDT, these assumptions may cause unexpected reverts.

Impact:

Severity: High

If USDT is used as:

  • Flash loan token

  • Collateral token

  • Borrow token

the protocol may experience:

  • Reverts during createLeveragedPosition

  • Reverts inside _executeOpenOperation

  • Reverts inside _executeUnwindOperation

  • Reverts in recoverTokens

  • Full flash loan transaction failure

Since flash loans must complete atomically, any revert inside transfer or approval logic will revert the entire transaction.

This may result in:

  • Inability to open leveraged positions

  • Inability to unwind positions

  • Operational denial of service when USDT is used

  • Incompatibility with a major Aave-supported asset

Given USDT’s widespread use in DeFi, this significantly impacts protocol reliability and usability.

Proof of Concept:

Scenario:

  1. A user opens a leveraged position using USDT as _flashLoanToken.

  2. Inside _executeOpenOperation, the contract executes:

IERC20(_asset).approve(address(aavePool), totalCollateral);

If:

  • A previous allowance already exists and is non-zero, and

  • The token is USDT,

the call may revert because USDT requires:

approve(spender, 0);
approve(spender, newAmount);

instead of directly updating a non-zero allowance.

As a result:

  • The approve call reverts

  • The flash loan callback fails

  • The entire transaction reverts

The same issue can occur when approving tokens for the 1inch router or during unwind operations.

Recommended Mitigation:

Use OpenZeppelin’s SafeERC20 for all ERC-20 interactions:

import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;

Replace:

  • transfer with safeTransfer

  • transferFrom with safeTransferFrom

  • approve with forceApprove (recommended if available)

If forceApprove is not available, use the reset-to-zero pattern:

function _safeApprove(IERC20 token, address spender, uint256 amount) internal {
token.safeApprove(spender, 0);
token.safeApprove(spender, amount);
}

Apply these changes to:

  • createLeveragedPosition

  • _executeOpenOperation

  • _executeUnwindOperation

  • recoverTokens

Updates

Lead Judging Commences

izuman Lead Judge 16 days ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

WEIRD ERC20 Tokens

Currently there is no support for weird ERC20 tokens i.e. FOT tokens, missing return values, reentrancy etc.

Support

FAQs

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

Give us feedback!