
Identifying Arbitrage Opportunities in DeFi Through Code
TechFlow Selected TechFlow Selected

Identifying Arbitrage Opportunities in DeFi Through Code
This article will analyze potential arbitrage opportunities in the smart contract code of certain decentralized exchanges and aggregators.
Overview
Decentralized Finance (DeFi) refers to financial services built on blockchain technology that do not rely on traditional financial intermediaries such as brokers, exchanges, or banks. Instead, DeFi leverages smart contracts deployed on blockchains to facilitate financial activities. Within the DeFi ecosystem, numerous arbitrage opportunities exist, including liquidations and price arbitrage across markets. This article analyzes potential arbitrage opportunities in the contract code of several decentralized exchanges (DEXs) and aggregators.
Analysis
Uniswap
Uniswap is a decentralized cryptocurrency exchange platform based on an Automated Market Maker (AMM) model. Currently, two popular versions are in use: Uniswap V2 and Uniswap V3. We will analyze potential arbitrage opportunities in each version separately.
Uniswap V2 Router
In Uniswap V2, users typically interact with Pair and Factory contracts through the Router contract. Normally, the Router acts only as an intermediary for token transfers and does not store tokens. However, due to various reasons such as airdrops or mistaken transfers, some tokens may accumulate within the Router contract. How can these tokens be extracted?
By analyzing the code of the Uniswap V2 Router02 contract, we find the function removeLiquidityETHSupportingFeeOnTransferTokens:

This function removes liquidity from a pool where one token is WETH. Internally, when calling removeLiquidity, it sets the recipient address to address(this), meaning both tokens are first transferred to the Router contract before being forwarded to the specified recipient. While the amount of WETH withdrawn is determined by the return value of removeLiquidity and cannot be manipulated, the amount of the other token transferred is calculated using balanceOf(address(this))—i.e., the current balance of that token in the Router contract.
Based on this behavior, we can outline the following arbitrage process:
- Monitor the Router02 contract for any ERC-20 tokens;
- Call
addLiquidityETHto add liquidity for the detected ERC-20 token and WETH; - Call
removeLiquidityETHSupportingFeeOnTransferTokensto remove the liquidity.
Limitations:
- If the token has never been paired with WETH before, adding initial liquidity incurs a small loss due to
MINIMUM_LIQUIDITY; - Currently, there is no known method to extract WETH or ETH held directly in the Router02 contract.
Uniswap V2 Pair
The Uniswap V2 Pair contract, also known as a liquidity pool, holds two tokens provided as liquidity. Since the Pair contract uses reserve variables to track balances rather than relying solely on balanceOf(address(this)), discrepancies can occur if someone mistakenly sends tokens directly to the contract. In such cases, the actual token balance exceeds the recorded reserve.
To address this, the Pair contract includes a function called skim, which allows extraction of the excess token amounts:

As shown, this function transfers the difference between the actual balance and the recorded reserve of both pooled tokens to the specified to address.
Besides the two main tokens, liquidity pools may also hold other ERC-20 tokens due to accidental transfers or airdrops. Can these extraneous tokens be retrieved?
Code analysis reveals that extracting arbitrary ERC-20 tokens is generally not possible—except in one special case: when the pool contains its own LP token.
In this scenario, we can call the burn function on the Pair contract to remove liquidity and withdraw the corresponding two underlying tokens:

Uniswap V3 SwapRouter
Similar to Uniswap V2, the Uniswap V3 SwapRouter contract may accumulate ERC-20 tokens and ETH due to user errors or airdrops. Fortunately, the SwapRouter provides several functions to facilitate token recovery.
To extract ERC-20 tokens, we can use the sweepToken function:

To extract ETH, we can use the refundETH function:

We can also directly call unwrapWETH9 to unwrap WETH into ETH and withdraw it:

The above covers the arbitrage analysis of the Uniswap V3 SwapRouter contract.
After analyzing the Uniswap V3 Pool contract, no mechanism was found to extract unrelated tokens, nor any discrepancy between internal reserves and actual balances like in Uniswap V2 Pairs.
SushiSwap
SushiSwap originated as a fork of Uniswap but has since evolved into an independent ecosystem offering various financial products and services.
Because SushiSwap shares significant similarities with Uniswap V2, the same arbitrage techniques applicable to Uniswap V2 also apply here.
SushiXSwap
SushiXSwap is a cross-chain swap protocol launched by SushiSwap based on LayerZero, supporting networks including Optimism, Arbitrum, Fantom, BNB Chain, Polygon, and Avalanche. It enables users to perform cross-chain swaps across supported chains and assets.
How can tokens within the SushiXSwap contract be extracted?
The core functionality of SushiXSwap is implemented via the cook function, which supports a list of operations:

One operation, ACTION_DST_WITHDRAW_TOKEN, is particularly relevant. Its implementation is as follows:

It decodes input data passed to cook, checks whether the amount is zero, and if so, sets the amount to the full balance of the specified ERC-20 token or ETH in the contract. Then it calls _transferTokens to send the tokens to the designated address:

Thus, by crafting appropriate actions and datas inputs—setting actions to ACTION_DST_WITHDRAW_TOKEN and encoding the desired token, recipient address, and amount—we can withdraw any token held in the SushiXSwap contract.
Sushi BentoBox
Sushi BentoBox is a component within the SushiSwap ecosystem—a highly flexible DeFi yield optimization product. Essentially, it's a smart contract platform allowing users to deposit, borrow, and earn interest. BentoBox aims to maximize user returns in the DeFi space.
The Ethereum-based BentoBox contract holds large quantities of various tokens. Does it present any arbitrage opportunities?
Users can deposit tokens into BentoBox via the deposit function, implemented as follows:

The function takes parameters including token address, sender (from), receiver (to), amount, and shares. After performing validations, lines 195–198 include a key check: amount <= _tokenBalanceOf(token).sub(total.elastic).
In BentoBox, the total balance of a given token is tracked via total.elastic, similar to reserve in Uniswap Pairs. Under certain conditions, this value may differ from the actual contract balance returned by _tokenBalanceOf(token). We can exploit this gap using the deposit function to convert the difference into legitimate internal shares.
Specifically, set token to the token with a balance discrepancy, amount to the difference, from to the BentoBox contract address, and to to your own address. On line 207, because from == address(this), no actual transfer occurs—only the internal accounting is adjusted, effectively crediting the difference as your share within BentoBox.
DODO
DODO is a decentralized trading platform that uses its proprietary Proactive Market Making (PMM) algorithm to provide efficient on-chain liquidity for Web3 assets. DODO sources liquidity both internally and by aggregating from other exchanges.
DODO consists of multiple contracts, with users typically interacting through the DODO V2 Proxy02 contract for token swaps. Like Uniswap’s Router, this contract may accumulate tokens due to errors or airdrops. How can we extract them?
DODO V2 Proxy02
The DODO V2 Proxy02 contract contains the externalSwap function, used to route swaps through external platforms such as 0x or 1inch. The implementation is shown below:

Lines 1719–1721 validate input parameters. Line 1724 checks whether fromToken is ETH; if not, it attempts to transfer tokens from the caller to the contract and approve spending. However, analysis of the DODOApprove contract shows that setting fromTokenAmount to 0 bypasses the approval requirement:

Next, the contract verifies that swapTarget is in a whitelist. Both swapTarget and calldataConcat are user-controlled, so we can set swapTarget to a whitelisted address (e.g., 0x or 1inch) and calldataConcat to encoded data for a view function that returns true, thereby passing the require check:

Afterward, all toToken (ERC-20 or ETH) in the contract is sent to the caller. Finally, a minimum output check is performed using minReturnAmount; setting this to a negligible value ensures success. The last two function calls are inconsequential.

Using this method, we can extract both ERC-20 tokens and ETH from the DODO V2 Proxy02 contract.
1inch
1inch is a decentralized exchange (DEX) aggregator that pools liquidity from multiple DEXs to offer users optimal token swap rates. By consolidating liquidity across sources, 1inch helps users optimize trades and access the best prices with minimal slippage. Its smart contracts automatically execute trades across different platforms, enabling seamless access to favorable rates. Additionally, 1inch offers features such as liquidity mining and a governance token.
The primary contract in 1inch is the AggregationRouter, with versions V4 and V5 being most widely used. These routers may accumulate tokens due to user errors or airdrops. By carefully constructing input parameters, we can extract these tokens.
AggregationRouterV5
The AggregationRouterV5 contract includes a swap function, implemented as follows:

After validating minReturnAmount from the desc struct, it extracts srcToken and dstToken. Lines 986–997 can be bypassed by manipulating flags and srcToken in the desc struct:

Then _execute is called, which performs a low-level call. Since executor is user-supplied, we can use the zero address to skip execution while still returning success:

Next, the contract balance of dstToken is read. Lines 1007–1018 can be bypassed by adjusting flags and setting minReturnAmount to a very low value:

Finally, all dstToken balance in the contract is sent to dstReceiver, which is fully controlled by the caller:

By following these steps, we can construct parameters to the swap function and drain tokens from the AggregationRouterV5 contract.
AggregationRouterV4
AggregationRouterV4 is largely similar to V5, also featuring a swap function:

The implementation is nearly identical to V5, with minor optimizations in the call logic. Therefore, the same extraction method used for V5 applies to AggregationRouterV4.
Conclusion
This article briefly introduced several decentralized exchanges and aggregators, exploring potential arbitrage opportunities at the smart contract level. While the theoretical mechanisms have been analyzed, practical success depends on various factors such as gas costs and node propagation speed.
Join TechFlow official community to stay tuned
Telegram:https://t.me/TechFlowDaily
X (Twitter):https://x.com/TechFlowPost
X (Twitter) EN:https://x.com/BlockFlow_News














