Web3 新手系列:我从 Uniswap 代码中学到的合约开发小技巧

2024年11月01日 21:04:02 加密货币 互联网

撰文:Fisher,ZAN TeamP9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

没想到合约还能这么写?这是笔者最近发出的最多的感慨了~P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

最近在写一个去中心化交易所开发的教程 https://github.com/WTFAcademy/WTF-Dapp,参考了 Uniswap V3 的代码实现,学习到了很多知识点。笔者之前开发过简单的 NFT 合约,这次是第一次尝试开发 Defi 的合约,相信这些小技巧会对想要学习合约开发的小白会很有帮助。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

合约开发的大佬可以直接前往 https://github.com/WTFAcademy/WTF-Dapp 一起来贡献代码,为 Web3 添砖加瓦~P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

接下来就让我们看看这些小技巧吧,有的甚至称得上是奇技淫巧。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

合约部署的合约地址有办法做到是可预测的


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

我们一般部署合约得到的都是一个看上去随机的地址,因为和「 nonce 」有关,所以合约地址不好预测。但是在 Uniswap 中,我们会有这样的需求:需要通过交易对和相关信息就能推理出合约的地址。这在很多情况下很管用,比如判断交易的权限,或者获取池子的地址等。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Uniswap 中,创建合约是通过「 pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}()); 」这样的代码来创建的。通过添加了「 salt 」来使用 CREATE2 (https://github.com/AmazingAng/WTF-Solidity/blob/main/25_Create2/readme.md) 的方式来创建合约,这样的好处是创建出来的合约地址是可预测的,地址生成的逻辑是「 新地址 = hash("0xFF",创建者地址, salt, initcode)」 。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

这部分内容你可以查看 WTF-DApp 课程的 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P103_Factory/readme.md 这一章来了解更多。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

善用回调函数


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Solidity 中,合约之间可以互相调用。有一种场景是 A 在某个方法调用 B,B 在被调用的方法中回调 A,这在某些场景中也很管用。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Uniswap 中,当你调用「 UniswapV3Pool 」合约的「 swap 」方法交易时,它会回调「 swapCallback 」,回调会传入计算出来的本次交易实际需要的「 Token 」,调用方需要在回调中将交易需要的 Token 转入「 UniswapV3Pool 」,而不是把「 swap 」方法拆开为两部分让调用方调用,这样确保了「 swap 」方法的安全性,确保整个逻辑都是被完整执行的,而不需要繁琐的变量记录来确保安全性。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

代码片段如下:P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

你可以学习课程中关于交易的部分内容了解更多 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P106_PoolSwap/readme.md。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

用异常来传递信息,用 try catch 来实现交易的预估


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在参考 Uniswap 的代码时,我们发现在它的 https://github.com/Uniswap/v3-periphery/blob/main/contracts/lens/Quoter.sol 这个合约中,把「 UniswapV3Pool 」的「 swap 」方法用「 try catch 」包住执行了一下:P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

这个是为啥呢?因为我们需要模拟「 swap 」方法来预估交易需要的 Token,但是因为预估的时候并不会实际产生 Token 的交换,所以会报错。在 Uniswap 中,它通过在交易的回调函数中抛出一个特殊的错误,然后捕获这个错误,从错误信息中解析出需要的信息。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

看上去挺 Hack 的,但是也很实用。这样就不需要针对预估交易的需求去改造 swap 方法了,逻辑也更简单。在我们的课程中,我们也参考这个逻辑实现了 https://github.com/WTFAcademy/WTF-Dapp/blob/main/demo-contract/contracts/wtfswap/SwapRouter.sol 这个合约。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

用大数来解决精度问题


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Uniswap 的代码中,有很多的计算逻辑,比如按照当前价格和流动性计算交换的 Token,那这个过程中我们要避免除法操作的时候丢失精度。在 Uniswap 中,计算过程会经常用到「 << FixedPoint96.RESOLUTION 」这个操作,它代表左移 96 位,相当于乘以「 2^96 」。左移之后再做除法运算,这样可以在正常交易不溢出(一般用「 uint256 」来计算,还足够)的情况下保证精度。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

代码如下(通过价格和流动性计算交易所需要的 Token 数):P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

可以看到,首先在 Uniswap 中价格都是用平方根乘以「 2^96 」(对应上面代码中的「 sqrtRatioAX96 」和「 sqrtRatioBX96 」),然后流动性「 liquidity 」会左移计算出「 numerator1 」。在下面的计算中,「 2^96 」会在计算过程中被约掉,得到最后的结果。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

当然,不管如何,理论上还是会有精度的丢失的,不过这种情况都是最小单位的丢失了,是可以接受的。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

更多内容你可以学习 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P106_PoolSwap/readme.md 这一篇课程了解更多。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

用 Share 的方式来计算收益


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Uniswap 中,我们需要记录 LP(流动性提供者)的手续费收益。显然,我们不能在每次交易的时候都给每个 LP 记录各自的手续费,这样会消耗大量的 Gas。那怎么处理呢?P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在 Uniswap 中,我们可以看到「 Position 」中定义了如下结构体:P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

其中包含了「 feeGrowthInside0LastX128 和 feeGrowthInside1LastX128 」,他们记录了每个头寸(Position)上一次提取手续费时候每个流动性应该收到的手续费。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

简单点说,我只要记录总的手续费和每个流动性应该分配到多少手续费即可,这样 LP 提取手续费的时候按照手中的流动性就可以计算出他有多少可以提取的手续费。就好像你持有某个公司的股票,你要提取股票收益的时候只要知道公司历史的每股得收益,以及你上次提取时的收益即可。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

之前我们在《巧妙的合约设计,看看 stETH 如何按天自动发放收益?让你的 ETH 参与质押获取稳定利息》这篇文章中也介绍过 stETH 的收益计算方法,也是类似的道理。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

不是所有信息都需要从链上获取


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

链上的存储是相对昂贵的,所以我们并不是所有的信息都要上链,或者从链上获取。比如 Uniswap 前端网站调用的很多接口就是传统的 Web2 的接口。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

交易池的列表、交易池的信息等都可以存储在普通的数据库中,有的可能需要定期从链上同步,但是我们并不需要去实时调用链或者节点服务提供的 PRC 接口来获取相关数据。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

当然现在很多区块链 PRC 的供应商都提供了一些高级的接口,你可以以更快速更便宜的方式获取到一些数据,这也是类似的道理。比如 ZAN 就提供了类似获取某个用户下所有 NFT 的接口,这些信息显然是可以通过缓存来提高性能和效率的,你可以访问 https://zan.top/service/advance-api 这个获取更多。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

当然,关键的交易肯定是在链上进行的。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

学会合约的拆分,还要学会利用类似 ERC721 这样已有的标准合约


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

一个项目可能包含多个实际部署的合约,即便是实际部署只有一个合约,但是我们代码可以通过继承的方式把合约拆分为多个合约来维护。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

比如在 Uniswap 中,https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol 合约就继承了很多合约,代码如下:P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

而且你在看「 ERC721Permit 」合约的实现时,你会发现它直接使用了「 @openzeppelin/contracts/token/ERC721/ERC721.sol 」合约,这样一方面方便通过 NFT 的方式来管理头寸,另外一方面也可以用已有的标准的合约来提高合约的开发效率。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

在我们的课程中,你可以学习 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P108_PositionManager/readme.md 尝试开发一个简单的 ERC721 的合约来管理头寸。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

总结


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

看再多的文章也不如自己上手开发来得实在,在尝试自己实现一个简易版的去中心化交易所的过程中能让你更深刻的理解 Uniswap 的代码实现,也可以学习到更多实际项目中会体会到的知识点。P9K币学堂 - 比特币圈新手入门基础知识教程科普平台


P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

WTF-DApp 课程是 ZAN 的开发者社区和 WTF Academy 开发者社区同学共同完成的开源课程。如果你也对 Web3,对 Defi 项目开发感兴趣,你可以参考我们的实战课程 https://github.com/WTFAcademy/WTF-Dapp,一步一步完成一个简易版的交易所,相信一定会对你有所帮助~P9K币学堂 - 比特币圈新手入门基础知识教程科普平台

欧易

欧易OKX交易所

全球三大交易所之一,注册领取价值6,0000元数字货币盲盒

APP下载    官网注册
最新区块链知识
全球各国比特币兴趣指数排行:前十名欧洲国家占 7 席

全球各国比特币兴趣指数排行:前十名欧洲国家占 7 席

撰文:Bitcoin Magazine编译:Felix,PANews 比特币流行度指数(BPI)是同类中第一个全面的搜索研究。该指数旨在通过对 Google 搜索查询的广泛分析,来衡量比特币的全球影响力。 与许多

2024年11月01日 0阅读
临近美国大选的民调:谁将赢得未来选举的关键选民?

临近美国大选的民调:谁将赢得未来选举的关键选民?

原文标题:《October 2024 Public Opinion Poll》撰文:Justin Slaughter、Dominique Little编译:Odaily 星球日报 夫如何 在即将到来的 2024 年 11 月美国大选中,加密货币的影响

2024年11月01日 0阅读
AI Meme 成加密市场新宠,昙花一现还是真有价值?

AI Meme 成加密市场新宠,昙花一现还是真有价值?

撰文:木沐 最近,一种叫做 AI Meme 的粉丝代币正在加密社区中流行。与以前的 Meme 代币不同,AI Meme 由人工智能生成和推动:由 AI 在社交媒体上为 Meme 币创造 IP 角色,连推广都由

2024年11月01日 0阅读
解读 Jito 再质押,如何让你 SOL 收益最大化?

解读 Jito 再质押,如何让你 SOL 收益最大化?

原文标题:《Jito (Re)staking is here- Who will win the Solana restaking race?》撰文:flow,crypto 研究员编译:zhouzhou,BlockBeats 编者按:这篇文章介绍了 Jito Labs 在 Solan

2024年11月01日 0阅读
一览美国财政部加密资产与国债市场报告

一览美国财政部加密资产与国债市场报告

编译:Pzai,Foresight News 加密资产增长和使用趋势 尽管基数较小,但加密资产仍经历了快速增长。增长既来自比特币和以太坊等原生加密货币,也来自稳定币。 加密货币总市值图表 迄

2024年11月01日 0阅读
DeFiance Capital 过去两周购买约 320 万美元的 AERO

DeFiance Capital 过去两周购买约 320 万美元的 AERO

据 Nansen 数据,The Spartan Group 在过去 24 小时内已累积购买 336,332 枚 AERO(约合 38 万美元),The Spartan Group 于 10 月 7 日首次购买了 443,851 枚 AERO ,此后一直稳定增

2024年11月01日 0阅读
Solana 上某 Rug Pull NFT 项目开发者被判共谋电信欺诈和洗钱罪

Solana 上某 Rug Pull NFT 项目开发者被判共谋电信欺诈和洗钱罪

美国佛罗里达州联邦陪审团已认定 21 岁的 NFT 开发者 Berman Jerry Nowlin(又名 Repulse 和 Zayous)犯有共谋电信欺诈和洗钱罪,最高将被判处五年监禁,量刑定于 2025 年 1 月 23

2024年11月01日 0阅读
Tether 将在 TON 上推出与阿联酋迪拉姆挂钩的稳定币

Tether 将在 TON 上推出与阿联酋迪拉姆挂钩的稳定币

Tether 高级战略合作伙伴经理 Alessandro Giori 在迪拜举行的 TON Gateway 活动中宣布 Tether 与阿联酋迪拉姆挂钩的稳定币将在 TON 区块链上发行。

2024年11月01日 0阅读
ZachXBT:初步追踪盗取 Truth Terminal 创建者 X 账号的黑客,其中一人疑似为 FWOG 巨鲸

ZachXBT:初步追踪盗取 Truth Terminal 创建者 X 账号的黑客,其中一人疑似为 FWOG 巨鲸

链上侦探 ZachXBT 表示,其对盗取 Truth Terminal 创建者 Andy Ayrey X 账号的黑客行为进行了初步追踪,该黑客通过部署多个 Meme 代币盗取了超过 150 万美元,发现其中一个人似乎

2024年11月01日 0阅读
Tether CEO:11 月计划发布两款新产品

Tether CEO:11 月计划发布两款新产品

Tether 首席执行官 Paolo Ardoino 表示,Tether 已经准备好在 11 月发布两款新产品,细节暂无披露。

2024年11月01日 0阅读
猜你感兴趣
Harmony最新价格,ONE实时行情,Harmony走势图2024年10月03日

Harmony最新价格,ONE实时行情,Harmony走势图2024年10月03日

2024年10月03日Harmony今日价格实时行情:Harmony 当前价格为 $0.01205629,其 24 小时的交易量为 $6,520,680.58。Harmony 在过去 24 小时内下跌了 -1.07%。目前的 加密货币市

2024年10月03日 0阅读
Bridge Oracle (BRG)币今日实时价格行情最新消息2024年04月07日

Bridge Oracle (BRG)币今日实时价格行情最新消息2024年04月07日

截止至2024年04月07日,Bridge Oracle (BRG)今日实时最新价格是0.001402美元,约等于人民币0.0101元。 Bridge Oracle (BRG)24H最高价$0.001528美元,24H最低价$0.001377美元,24H成

2024年07月24日 166阅读
BABB (BAX)是什么币种?BAX币值得投资吗?

BABB (BAX)是什么币种?BAX币值得投资吗?

BABB (BAX)行情BABB (BAX) 最新的价格是 $0.000173,24 小时的交易量是$243,948. BAX的价格在过去 24 小时内下跌了-5.78%。BABB的流通量为:730.5亿 BAX,最大供应量:1,000亿,总供

2024年07月24日 129阅读
交易所充值购买usdtethbtc后未到账怎么办图文教程

交易所充值购买usdtethbtc后未到账怎么办图文教程

交易所充值购买USDT/ETH/BTC后未到账怎么办在数字货币交易过程中,有时充值购买的USDT、ETH或BTC可能出现未到账的情况。这可能是因为交易所网络延迟、手续费设置不当等原因所

2024年07月24日 123阅读
Base网络TVL已增长至超过35亿美元

Base网络TVL已增长至超过35亿美元

据The Block数据显示,Base网络TVL已增长至超过35亿美元。此外,Base的交易量在整个第四季度保持了强劲势头,单日处理交易量超过800万笔,自3月以来,该网络一直保持稳定增长,交易量从

2024年12月27日 0阅读
UTK币今日价格行情_3月22日UTK币实时行情走势分析

UTK币今日价格行情_3月22日UTK币实时行情走势分析

UTK币今日价格行情_3月22日UTK币实时行情走势分析 截止至2024年03月22日,UTK币今日最新价格为0.124615美元,约合人民币0.8973元。在过去的24小时内,UTK币的最高价为0.149426美

2024年07月24日 106阅读