📢 Gate Square Exclusive: #WXTM Creative Contest# Is Now Live!
Celebrate CandyDrop Round 59 featuring MinoTari (WXTM) — compete for a 70,000 WXTM prize pool!
🎯 About MinoTari (WXTM)
Tari is a Rust-based blockchain protocol centered around digital assets.
It empowers creators to build new types of digital experiences and narratives.
With Tari, digitally scarce assets—like collectibles or in-game items—unlock new business opportunities for creators.
🎨 Event Period:
Aug 7, 2025, 09:00 – Aug 12, 2025, 16:00 (UTC)
📌 How to Participate:
Post original content on Gate Square related to WXTM or its
7 Practical Tips for Learning Mainstream DEX Contract Development
Tips for Contract Development: Lessons Learned from Uniswap
Recently, while developing a decentralized exchange project, I referred to the code implementation of a well-known DEX and learned many useful knowledge points. As a beginner who has just started with Defi contract development, these techniques have been very enlightening for me, and I believe they will also be helpful for others who want to learn about smart contract development.
Predictable Contract Address
The addresses obtained from deploying contracts usually appear random because they are related to the nonce. However, in certain scenarios, we need to infer the contract address through transaction information, such as determining transaction permissions or obtaining liquidity pool addresses.
This can be achieved by creating a contract using the CREATE2 method. The specific approach is to add a salt parameter when creating the contract:
solidity pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());
The contract address generated this way is predictable and follows the logic below:
New address = hash("0xFF", creator address, salt, initcode)
Reasonable Use of Callback Functions
In some scenarios, mutual calls between contracts can be very useful. For example, method A calls method B, and B calls back to A in the method that was called.
In a certain DEX, when calling the swap method for trading, it will call swapCallback, passing in the calculated Token actually needed for this transaction. The caller needs to transfer the required Token into the trading pool in the callback, rather than splitting the swap method. This ensures the complete execution of the swap method without cumbersome variable records to guarantee security.
Use Exception to Pass Information
When estimating a trade, we need to simulate the swap method, but we won't actually swap the tokens, which will result in an error. A certain DEX achieves estimation by throwing a special error in the trading callback function, then catching that error and parsing the required information.
This method seems to be a shortcut, but it is very practical. There is no need to modify the swap method for estimated demand, making the logic simpler.
Using Big Numbers to Solve Precision Issues
In code involving calculations, it is important to avoid losing precision during division operations. A certain DEX frequently uses "<< FixedPoint96.RESOLUTION" operation, which is equivalent to multiplying by 2^96. By left shifting and then performing division, precision can be ensured without overflow.
solidity uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96; amount0 = numerator1 * numerator2 / (sqrtRatioBX96 * sqrtRatioAX96);
Although there may still be a loss of precision in theory, it is usually just a loss of the smallest unit, which is acceptable.
Calculation of Earnings by Share Method
For the fee income calculation of liquidity provider (LP), it cannot record every transaction, as this would consume a large amount of Gas. Some DEXs adopt the method of recording the total fees and the fees to be allocated to each liquidity provider.
When extracting LP fees, the withdrawable amount is calculated based on the liquidity held. It's similar to holding company stocks; when extracting profits, you only need to know the historical earnings per share and the earnings from the last withdrawal.
Reasonable Choice of Information Acquisition Methods
On-chain storage is relatively expensive, and not all information needs to be on-chain or retrieved from the chain. For example, transaction pool lists and information can be stored in a regular database and synchronized from the chain periodically.
Some blockchain RPC providers offer advanced interfaces for quicker data retrieval. However, key transactions still need to be conducted on-chain.
Contract Splitting and Standard Contract Reuse
A project may contain multiple contracts, and even if a single contract is actually deployed, it can be split into multiple contracts for maintenance through inheritance.
The NFT position management contract of a certain DEX inherits multiple contracts:
solidity contract NonfungiblePositionManager is INonfungiblePositionManager, Multicall, PeripheryImmutableState, PoolInitializer, LiquidityManagement, PeripheryValidation, SelfPermit, ERC721Permit {...}
At the same time, it also uses OpenZeppelin's ERC721 standard contract, which facilitates position management and improves development efficiency.
Summary
Developing a simple decentralized exchange by yourself will allow you to gain a deeper understanding of the code implementation of mature projects and learn more practical knowledge points. I hope these tips inspire you, and I wish you smooth development!