Futures
Access hundreds of perpetual contracts
CFD
Gold
One platform for global traditional assets
Options
Hot
Trade European-style vanilla options
Unified Account
Maximize your capital efficiency
Demo Trading
Introduction to Futures Trading
Learn the basics of futures trading
Futures Events
Join events to earn rewards
Demo Trading
Use virtual funds to practice risk-free trading
Launch
CandyDrop
Collect candies to earn airdrops
Launchpool
Quick staking, earn potential new tokens
HODLer Airdrop
Hold GT and get massive airdrops for free
Pre-IPOs
Unlock full access to global stock IPOs
Alpha Points
Trade on-chain assets and earn airdrops
Futures Points
Earn futures points and claim airdrop rewards
Promotions
AI
Gate AI
Your all-in-one conversational AI partner
Gate AI Bot
Use Gate AI directly in your social App
GateClaw
Gate Blue Lobster, ready to go
Gate for AI Agent
AI infrastructure, Gate MCP, Skills, and CLI
Gate Skills Hub
10K+ Skills
From office tasks to trading, the all-in-one skill hub makes AI even more useful.
GateRouter
Smartly choose from 40+ AI models, with 0% extra fees
The contract development skills I learned from reading Uniswap code are way more interesting than textbooks
Recently, while doing a tutorial on developing decentralized exchanges, I delved into how Uniswap V3 is implemented and discovered some really clever techniques. I had only written simple NFT contracts before; this was my first serious deep dive into DeFi contract code, and I found many things worth sharing with friends who want to learn about Uniswap.
Let me start with one of the most surprising things — can contract addresses actually be predicted?
Typically, deployed contract addresses seem random, but Uniswap uses a smart method. It employs the CREATE2 opcode with a salt parameter during contract creation, making the generated address predictable. The specific approach is something like “pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());”. This way, as long as you know the token pair and fee info, you can calculate the pool’s contract address without deploying it first. This is especially useful for verifying transaction permissions or quickly locating pools.
The callback function design is also quite ingenious.
In Uniswap, when you call the swap method to perform a trade, it triggers the swapCallback function, passing the calculated token amounts needed. You then transfer the tokens within the callback. The benefit is that the entire trading logic is executed atomically, without needing multiple steps or complex variable tracking to ensure security. Essentially, it’s like A calls B, and B calls back to A, forming a closed loop.
The way they estimate trades is also quite hacky — using exceptions to pass information.
Since the estimation doesn’t actually execute token swaps, it will throw errors. Uniswap’s approach is to throw a special error in the callback, then catch it with try-catch, parsing the needed data from the error message. It looks a bit rough, but it’s very practical — you can implement estimation without modifying the swap method itself.
The solution to precision issues is worth learning.
When calculating token swaps, doing direct division can cause precision loss. Uniswap’s method is to left-shift by 96 bits (equivalent to multiplying by 2^96), then perform division, and finally remove the 2^96 factor during the calculation. This ensures high precision within uint256 range without overflow. The variables like sqrtRatioAX96 and sqrtRatioBX96 in the code follow this logic — it looks complex but the reasoning is clear.
The way they calculate fee earnings is also very clever.
Instead of recording fees for each LP on every trade (which would consume a lot of gas), they record total fees and the proportion of liquidity that should receive them. When LPs withdraw, they just multiply their held liquidity by the historical per-share fee to get their earnings — similar to shareholders claiming dividends based on per-share profit. This share calculation method is widely used in many projects.
Not all information needs to be on-chain — this is also very important.
Lists of pools, basic info, etc., can be stored in traditional databases and synchronized periodically from the chain, rather than calling RPCs in real-time. Many blockchain service providers now offer advanced APIs that allow you to access data more quickly and cheaply — that’s the same idea.
Finally, the way the code is organized.
A complex project usually splits contracts into multiple parts for maintainability. Uniswap inherits many contracts and also makes good use of existing standards, like directly using OpenZeppelin’s ERC721 for position management. This improves development efficiency and code quality.
Honestly, reading articles is not as good as hands-on experience. Building a simple decentralized exchange helps you truly understand why Uniswap is designed this way. The WTF-DApp course is based on this idea, guiding you step-by-step through a practical Uniswap tutorial project. I believe it will be very helpful for your contract development.