# ERC20 Approval Reset Requirement

{% hint style="info" %}
[**Book an audit with Zokyo**](https://www.zokyo.io/)
{% endhint %}

{% hint style="info" %}
This type of vulnerability is prevalent in decentralized exchanges (DEX)
{% endhint %}

ERC20 tokens like Tether (USDT) pose unique challenges due to their requirement of resetting approval to zero before setting a new approval amount. This requirement, aimed at mitigating front-running attacks, could lead to transaction failures if not properly managed.

Consider the following function, `_swapAssetOut()`, where an asset is swapped via a stable swap pool:

```
// Original code
SafeERC20.safeApprove(IERC20(_assetIn), address(pool), _amountIn);
amountIn = pool.swapExactOut(_amountOut, _assetIn, _assetOut, _maxIn);
```

In the above snippet, the `safeApprove` function sets the approval for the `_assetIn` amount, and then `swapExactOut` is used to perform the actual swap. This code might fail if `_assetIn` is a token like USDT, which requires that an existing non-zero approval be reset to zero before assigning it a new value.

The failure happens because `safeApprove` attempts to change the approval from a non-zero value to another non-zero value, which USDT does not permit. Hence, the function reverts, leading to the failure of the entire transaction.

To solve this problem, the approval must first be set to zero, and only then can the new approval value be set. This procedure can be performed using the `safeApprove` and `safeIncreaseAllowance` functions, as follows:

```
// Revised code
SafeERC20.safeApprove(IERC20(_assetIn), address(pool), 0); // First reset the allowance to 0
SafeERC20.safeIncreaseAllowance(IERC20(_assetIn), address(pool), _amountIn); // Then set the new allowance
amountIn = pool.swapExactOut(_amountOut, _assetIn, _assetOut, _maxIn);
```

This revision takes into account the approval requirements of tokens like USDT, first resetting the allowance to zero before setting it to the desired value. This approach ensures the function's successful execution, even with tokens that require approval resetting. By adopting this pattern when dealing with ERC20 tokens, developers can prevent contract failures when interacting with tokens like USDT.

Real bug bounty examples:

* [\[L-06\] Unsafe approve](https://github.com/code-423n4/2021-07-connext-findings/issues/13)
* [\[M-17\] Unsafe approve would halt the auction and burn the bond](https://github.com/code-423n4/2021-09-defiprotocol-findings/issues/35)
* [\[M-05\] Did Not Approve To Zero First Causing Certain Token Transfer To Fail](https://github.com/code-423n4/2022-06-connext-findings/issues/154)

This vulnerability is generally classed as medium risk, but could be high risk depending on the implementation


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://zokyo-auditing-tutorials.gitbook.io/zokyo-tutorials/tutorials/tutorial-3-approvals-and-safe-approvals/vulnerability-examples/erc20-approval-reset-requirement.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
