DEX Router Drain: How an Unverified Uniswap V3 Callback Can Steal User Funds | PandaSecurity
Web3 Security

DEX Router Drain: How an Unverified Uniswap V3 Callback Can Steal User Funds

PandaSecurity Team •
#Smart Contract Audit#Uniswap V3#DEX Router
DEX router drain attack caused by an unverified Uniswap V3 callback

A recent BNB Chain exploit highlights an important issue in DEX router security: a router that fails to authenticate its Uniswap V3 callback can potentially turn users’ existing token approvals into a direct drain mechanism.

The incident resulted in approximately 62.28 WBNB of losses across 29 victims.

The vulnerability did not require an oracle attack, private-key compromise, or privileged access. Instead, the attacker combined three relatively simple conditions:

This is a good example of why DeFi smart contract security depends on understanding how contracts interact, rather than checking individual functions in isolation.

How the DEX Router Attack Worked

The vulnerable router exposed a permissionless swap entry point:

0x33411b5e

The route supplied by the caller included a pool address. The router then called:

pool.swap(...)

without verifying that the address was a legitimate V3 pool created by the expected factory.

This is the first critical security failure.

An attacker could deploy a simple fake pool that implemented the expected swap() function.

The execution then looked roughly like this:

Attacker
   ↓
DEX Router
   ↓
Fake Pool
   ↓
Uniswap V3 Callback
   ↓
transferFrom(victim, ...)

The fake pool did not need to behave like a real AMM. Its main purpose was to call the router’s callback.

The Uniswap V3 Callback Vulnerability

Uniswap V3-style swaps rely on callbacks. After the pool executes a swap, it calls the router’s callback so the router can provide the tokens owed to the pool.

A secure router must therefore verify:

Is the contract calling this callback actually a trusted V3 pool?

The vulnerable implementation failed to establish this trust relationship.

The router’s factoryV3() returned the zero address:

0x0000000000000000000000000000000000000000

As a result, the router could not derive or verify a legitimate pool through the factory.

The callback effectively trusted:

msg.sender

even though msg.sender could be an attacker-controlled contract.

That turns the callback into a powerful attack surface.

The More Dangerous Problem: Arbitrary payer

Pool authentication was not the only issue.

The callback also decoded a payer from callback data and eventually performed a transfer similar to:

IERC20(token).transferFrom(
    payer,
    msg.sender,
    amount
);

The important question is:

Who controls payer?

In this attack, the fake pool could provide a victim address as the payer.

If that victim had previously approved the router, the token contract would allow the transfer.

For example:

victim → approve(router, type(uint256).max)

could later become:

Fake Pool
    ↓
Router Callback
    ↓
transferFrom(victim, attacker, amount)

The victim did not need to sign a new transaction.

Their existing approval was enough.

Why Token Approvals Matter

This incident demonstrates an important risk that is sometimes underestimated during smart contract audits.

A vulnerability in a router does not necessarily affect only funds currently deposited into the router.

If users have previously granted the router large ERC-20 allowances, an exploitable spending path may potentially reach those users’ external token balances.

This is why we recommend treating:

approve() → router → transferFrom()

as a complete security flow during a smart contract audit.

The audit should identify:

  1. Who can trigger the spending operation?
  2. Who controls the from address?
  3. What contract is authorized to spend the tokens?
  4. Can callback data change the payer?
  5. Can the operation be repeated?

A vulnerability that looks like a callback validation issue can therefore become a much larger user-funds risk.

The Root Cause

The vulnerability can be summarized as four missing security controls:

1. No pool authentication

The router accepted an attacker-controlled pool address.

2. No callback authentication

The router did not verify that msg.sender was a legitimate factory-derived V3 pool.

3. Untrusted payer

The callback could derive the payer from attacker-influenced data.

4. Existing token approvals

Victims had previously approved the router, allowing transferFrom() to move their tokens.

Together, these created a direct token-draining primitive.

How to Secure a DEX Router

A secure Uniswap V3-style router should establish a strict trust relationship between the factory, pool, callback, and payer.

At minimum, the callback should verify that:

msg.sender == factory.getPool(
    token0,
    token1,
    fee
);

The router should also avoid allowing callback-controlled data to arbitrarily select the payer.

The payer should instead be tied to the original swap initiator or another explicitly authorized payment mechanism.

Similarly, any pool address supplied through user calldata should be validated before the router interacts with it.

The general rule is simple:

User-controlled calldata should never be allowed to define which contracts the router trusts.

Our Take at PandaSecurity

What makes this vulnerability interesting is that none of the individual components looks particularly unusual.

DEX routers use callbacks.

Users approve routers.

Routes contain pool addresses.

Contracts use transferFrom().

The problem appears when these components are combined without preserving the correct trust boundaries.

This is exactly the type of issue that can be missed by a purely function-by-function review.

At PandaSecurity, we focus on tracing complete execution paths across routers, pools, callbacks, token approvals, and external contracts. For DeFi protocols, understanding who controls each value at every stage of execution is often more important than simply looking for common Solidity bugs.

For projects using custom DEX routers, Uniswap V3 integrations, aggregators, or large token allowances, callback authentication and approval flows deserve particular attention.

PandaSecurity provides smart contract auditing and Web3 development services for EVM-based protocols, with a focus on practical DeFi security and real-world attack paths.

Related articles

← Back to Blog