📢 Gate广场 #创作者活动第一期# 火热开启,助力 PUMP 公募上线!
Solana 爆火项目 Pump.Fun($PUMP)现已登陆 Gate 平台开启公开发售!
参与 Gate广场创作者活动,释放内容力量,赢取奖励!
📅 活动时间:7月11日 18:00 - 7月15日 22:00(UTC+8)
🎁 活动总奖池:$500 USDT 等值代币奖励
✅ 活动一:创作广场贴文,赢取优质内容奖励
📅 活动时间:2025年7月12日 22:00 - 7月15日 22:00(UTC+8)
📌 参与方式:在 Gate 广场发布与 PUMP 项目相关的原创贴文
内容不少于 100 字
必须带上话题标签: #创作者活动第一期# #PumpFun#
🏆 奖励设置:
一等奖(1名):$100
二等奖(2名):$50
三等奖(10名):$10
📋 评选维度:Gate平台相关性、内容质量、互动量(点赞+评论)等综合指标;参与认购的截图的截图、经验分享优先;
✅ 活动二:发推同步传播,赢传播力奖励
📌 参与方式:在 X(推特)上发布与 PUMP 项目相关内容
内容不少于 100 字
使用标签: #PumpFun # Gate
发布后填写登记表登记回链 👉 https://www.gate.com/questionnaire/6874
🏆 奖励设置:传播影响力前 10 名用户,瓜分 $2
Uniswap V3代码解析:7个实用合约开发技巧
从 Uniswap 代码中学到的合约开发小技巧
最近在编写去中心化交易所开发教程时,参考了 Uniswap V3 的代码实现,学到了许多宝贵的知识点。作为一名之前只开发过简单 NFT 合约的开发者,这次尝试 Defi 合约开发让我有了不少新的收获。相信这些小技巧对想要学习合约开发的新手会很有帮助。
接下来让我们一起来看看这些实用的开发技巧,其中有些甚至可以称得上是奇技淫巧。
可预测的合约部署地址
通常部署合约得到的是一个看似随机的地址,因为与 nonce 相关,所以合约地址难以预测。但在某些情况下,我们需要通过交易对和相关信息推断出合约地址,比如判断交易权限或获取池子地址等。
Uniswap 通过添加 salt 参数使用 CREATE2 方式创建合约,使得创建的合约地址可预测。地址生成逻辑为:新地址 = hash("0xFF",创建者地址, salt, initcode)。
善用回调函数
Solidity 中合约之间可以互相调用。在某些场景下,A 调用 B 的方法,B 在被调用的方法中回调 A 是很有用的。
Uniswap 中,调用 UniswapV3Pool 合约的 swap 方法交易时,它会回调 swapCallback,回调会传入计算出的本次交易实际需要的 Token。调用方需要在回调中将交易所需 Token 转入 UniswapV3Pool,而不是将 swap 方法拆分为两部分让调用方调用。这确保了 swap 方法的安全性,保证整个逻辑被完整执行,无需繁琐的变量记录来确保安全性。
用异常传递信息,用 try catch 实现交易预估
Uniswap 的某些合约中,将 UniswapV3Pool 的 swap 方法用 try catch 包裹执行。这是为了模拟 swap 方法来预估交易所需 Token。由于预估时不会实际产生 Token 交换,所以会报错。Uniswap 通过在交易回调函数中抛出特殊错误,然后捕获该错误,从错误信息中解析出所需信息。
这种方法看似有些取巧,但很实用。无需为预估交易需求改造 swap 方法,逻辑也更简单。
用大数解决精度问题
Uniswap 代码中有大量计算逻辑,如根据当前价格和流动性计算交换的 Token。为避免除法操作导致精度损失,计算过程中经常使用 << FixedPoint96.RESOLUTION 操作,即左移 96 位,相当于乘以 2^96。左移后再进行除法运算,在正常交易不溢出的情况下保证精度。
虽然理论上仍会有精度损失,但通常只是最小单位的损失,可以接受。
用 Share 方式计算收益
Uniswap 中需要记录 LP(流动性提供者)的手续费收益。显然不能在每次交易时都给每个 LP 记录各自的手续费,这会消耗大量 Gas。
Uniswap 的解决方案是在 Position 结构体中定义 feeGrowthInside0LastX128 和 feeGrowthInside1LastX128,记录每个头寸上次提取手续费时每个流动性应得的手续费。
简而言之,只需记录总手续费和每个流动性应分配的手续费即可。LP 提取手续费时,根据持有的流动性计算可提取的手续费。这类似于持有公司股票,提取股票收益时只需知道公司历史每股收益和上次提取时的收益。
不是所有信息都需要从链上获取
链上存储相对昂贵,并非所有信息都需要上链或从链上获取。例如,Uniswap 前端网站调用的许多接口是传统 Web2 接口。
交易池列表、交易池信息等可存储在普通数据库中,有些可能需要定期从链上同步,但无需实时调用链或节点服务提供的 RPC 接口获取相关数据。
当然,关键交易必须在链上进行。
学会合约拆分,利用已有标准合约
一个项目可能包含多个实际部署的合约。即使实际部署只有一个合约,我们也可以通过继承方式将合约拆分为多个合约来维护。
例如,Uniswap 中的某些合约继承了多个合约。在实现时,直接使用了 @openzeppelin/contracts/token/ERC721/ERC721.sol 合约,这样既方便通过 NFT 方式管理头寸,又可以利用已有标准合约提高开发效率。
总结
亲自动手开发比阅读文章更能加深理解。尝试实现一个简易版去中心化交易所的过程能让你更深入理解 Uniswap 的代码实现,也能学习到更多实际项目中的知识点。