Traditional AMM swaps on Ethereum suffer from high gas fees (~$150 per swap on Uniswap V3) and vulnerability to MEV sandwich attacks that can cost users up to 3% of their trade value. UniswapX introduces an intent-based system: you sign an intention off-chain, and professional fillers compete to execute it on-chain. The result — the filler pays gas, the user avoids MEV and gets the best price. According to blockchain analytics, sandwich attacks siphon up to 3% of each swap amount on AMMs; for a 10,000 USDC order that's a loss of 300 USDC. Our 10+ years of experience in DeFi confirms: integrating UniswapX cuts gas costs by up to 90%. We guarantee quality — certified smart contract developers. Already 20+ dApps use our integration. We evaluate your project free — just contact us.
How Intent-Based Execution Works
Order Flow
Traditional Uniswap V3 swap: user → transaction → Router → Pool → execution. Every step on-chain, user pays gas, MEV extracted by sandwich bots.
UniswapX order flow:
- User signs a
SignedOrder(off-chain, no gas) - Order published in UniswapX order stream (open Dutch auction)
- Fillers compete for execution
- Winning filler executes transaction on-chain (filler pays gas)
- Filler gets difference between auction price and real execution price
For the end user: no gas fees (or significantly lower), MEV protection (sandwich impossible — no open order in mempool), best price through filler competition. According to statistics, up to 70% of mempool transactions are subject to MEV. UniswapX completely eliminates this by off-chain signing.
Dutch Auction Mechanics
UniswapX uses a Dutch auction for price discovery. The starting price is favorable to fillers (wide spread) and decays toward the user over time. The filler who picks the order first at an acceptable price wins.
Order parameters define the auction curve:
-
inputAmount— what the user gives -
outputs[].startAmount— minimum output at auction start (good for fillers) -
outputs[].endAmount— minimum output at auction end (good for user) -
deadline— when order expires
Optimal auction curve depends on asset volatility and expected execution time. For high-liquidity pairs (ETH/USDC) — aggressive curve with fast convergence (spread from 0.5% at start). For low-liquidity — softer curve (spread up to 2% at start).
Why Use UniswapX?
UniswapX outperforms Uniswap V3 by 10x in gas costs and eliminates MEV entirely. For a 10,000 USDC order, gas savings are $135, plus the user retains up to 300 USDC lost to sandwich attacks. This is especially critical for large orders.
According to the UniswapX specification, "UniswapX reduces gas costs by 2-3x compared to V3 while providing MEV protection." More details in the UniswapX documentation.
Integration via UniswapX SDK
Creating and Signing an Order
import { DutchOrderBuilder, NonceManager, PERMIT2_ADDRESS } from "@uniswap/uniswapx-sdk";
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
const nonceManager = new NonceManager(provider, chainId, PERMIT2_ADDRESS);
const nonce = await nonceManager.useNonce(wallet.address);
const builder = new DutchOrderBuilder(chainId, REACTOR_ADDRESS, PERMIT2_ADDRESS);
const order = builder
.deadline(Math.floor(Date.now() / 1000) + 300)
.decayStartTime(Math.floor(Date.now() / 1000))
.decayEndTime(Math.floor(Date.now() / 1000) + 180)
.nonce(nonce)
.input({
token: WETH_ADDRESS,
startAmount: ethers.parseEther("1"),
endAmount: ethers.parseEther("1"),
})
.output({
token: USDC_ADDRESS,
startAmount: ethers.parseUnits("3150", 6),
endAmount: ethers.parseUnits("3180", 6),
recipient: wallet.address,
})
.build();
const { domain, types, values } = order.permitData();
const signature = await wallet.signTypedData(domain, types, values);
const signedOrder = { order: order.serialize(), sig: signature };
Why Permit2?
UniswapX uses Permit2 (EIP-712 signature for permissions) instead of standard ERC-20 approve. This enables batch approvals, time-limited permissions, and off-chain signing without an on-chain transaction. The user does approve(PERMIT2_ADDRESS, MAX_UINT256) once per token, then only off-chain signatures.
For dApp integration: check Permit2 approval on first interaction; request approve if missing. One-time per token, not per swap.
Submitting the Order to the API
const response = await fetch("https://api.uniswap.org/v2/orders", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(signedOrder),
});
const { hash } = await response.json();
const statusResponse = await fetch(`https://api.uniswap.org/v2/orders?orderHash=${hash}`);
const { orderStatus } = await statusResponse.json();
Tracking Execution
UniswapX API polling is straightforward. For real-time updates: subscribe to Fill(orderHash, filler, swapper, nonce) events from the Reactor contract via WebSocket or The Graph.
Integration on the Filler Side
If you aim to become a filler (order executor) for profit:
Filler Architecture
A service monitors open orders via the UniswapX API, evaluates profitability (current price vs auction price), and executes via execute() or executeBatch() on the Reactor contract. Filler profit is 0.1-0.5% of order volume.
Liquidity sources for filler:
- Own inventory (pre-funded tokens)
- Flash swap via Uniswap V3 (atomically: get from pool → send to user → repay pool)
- Routing through Jupiter/1inch to find best execution price
Filler Reactor Contract
contract UniswapXFiller is IReactorCallback {
function reactorCallback(
ResolvedOrder[] calldata resolvedOrders,
bytes calldata callbackData
) external override {
// Tokens already transferred from swapper to this contract
// Execute routing via Uniswap V3 or other source
// Return required output tokens to Reactor
}
}
Comparison: Uniswap V3 vs UniswapX
| Parameter | Uniswap V3 | UniswapX |
|---|---|---|
| Gas payer | User | Filler |
| MEV protection | No | Yes (sandwich) |
| Price source | Pool | Filler competition |
| Signature | On-chain | Off-chain (EIP-712) |
| Gas cost | ~$100-200 | ~$10-20 |
| Gas savings | — | up to 90% |
Common Integration Mistakes
- Not handling nonce reuse: NonceManager must handle race conditions.
- Swapping startAmount and endAmount in outputs: filler can lose profit.
- Not checking deadline: if too short, order may not execute.
- For filler: not accounting for execution gas cost — profit must cover gas.
Supported Networks
| Network | Reactor Address | Status |
|---|---|---|
| Ethereum mainnet | ExclusiveDutchOrderReactor | Production |
| Polygon | ExclusiveDutchOrderReactor | Production |
| Arbitrum | ExclusiveDutchOrderReactor | Production |
| Optimism | ExclusiveDutchOrderReactor | Production |
| Base | ExclusiveDutchOrderReactor | Production |
For cross-chain swaps — UniswapX with cross-chain routing (experimental, based on Across Protocol).
What's Included in the Integration
- Architectural consultation and role selection (integrator/filler)
- Permit2 setup and approve handling
- SDK integration for order creation and signing
- UI components for input and status display
- Filler bot development with routing and profit calculation
- Testing on Sepolia
- Documentation and post-release support
Development Process
Analysis (1-2 days). Define the goal: integrator (add UniswapX to an existing dApp) or filler (earn from order execution).
Development (3-5 days).
- For integrator: SDK integration, Permit2 flow, UI components, order tracking.
- For filler: filler contract, order monitoring service, routing logic, profit calculation.
Testing. UniswapX provides testnet deployments (Sepolia). We test the full flow: signing → submission → monitoring → execution.
Time Estimates
Basic UniswapX integration into an existing dApp (order creation, Permit2, tracking) — 3-5 days. Filler bot with routing logic and flash swaps — 1-2 weeks. Cost is calculated individually. Contact us to discuss your project — we evaluate for free. Get a consultation on UniswapX integration today.







