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

Odaily星球日报Xuất bản vào 2024-11-02Cập nhật gần nhất vào 2024-11-02

Tóm tắt

没想到合约还能这么写?这是笔者最近发出的最多的感慨了~

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

合约开发的大佬可以直接前往 https://github.com/WTFAcademy/WTF-Dapp一起来贡献代码,为 Web3 添砖加瓦~

接下来就让我们看看这些小技巧吧,有的甚至称得上是奇技淫巧。

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

我们一般部署合约得到的都是一个看上去随机的地址,因为和「 nonce 」有关,所以合约地址不好预测。但是在 Uniswap 中,我们会有这样的需求:需要通过交易对和相关信息就能推理出合约的地址。这在很多情况下很管用,比如判断交易的权限,或者获取池子的地址等。

在 Uniswap 中,创建合约是通过「 pool = address(new Uniswap V3 Pool{salt: keccak 256(abi.encode(token 0, token 1, fee))}()); 」这样的代码来创建的。通过添加了「 salt 」来使用 CREATE 2  (https://github.com/AmazingAng/WTF-Solidity/blob/main/25_Create2/readme.md)的方式来创建合约,这样的好处是创建出来的合约地址是可预测的,地址生成的逻辑是「 新地址 = hash("0x FF",创建者地址, salt, initcode)」 。

这部分内容你可以查看 WTF-DApp 课程的 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P103_Factory/readme.md这一章来了解更多。

善用回调函数

在 Solidity 中,合约之间可以互相调用。有一种场景是 A 在某个方法调用 B,B 在被调用的方法中回调 A,这在某些场景中也很管用。

在 Uniswap 中,当你调用「 Uniswap V3 Pool 」合约的「 swap 」方法交易时,它会回调「 swapCallback 」,回调会传入计算出来的本次交易实际需要的「 Token 」,调用方需要在回调中将交易需要的 Token 转入「 Uniswap V3 Pool 」,而不是把「 swap 」方法拆开为两部分让调用方调用,这样确保了「 swap 」方法的安全性,确保整个逻辑都是被完整执行的,而不需要繁琐的变量记录来确保安全性。

代码片段如下:

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

你可以学习课程中关于交易的部分内容了解更多 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P106_PoolSwap/readme.md

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

在参考 Uniswap 的代码时,我们发现在它的 https://github.com/Uniswap/v3-periphery/blob/main/contracts/lens/Quoter.sol 这个合约中,把「 Uniswap V3 Pool 」的「 swap 」方法用「 try catch 」包住执行了一下:

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

这个是为啥呢?因为我们需要模拟「 swap 」方法来预估交易需要的 Token,但是因为预估的时候并不会实际产生 Token 的交换,所以会报错。在 Uniswap 中,它通过在交易的回调函数中抛出一个特殊的错误,然后捕获这个错误,从错误信息中解析出需要的信息。

看上去挺 Hack 的,但是也很实用。这样就不需要针对预估交易的需求去改造 swap 方法了,逻辑也更简单。在我们的课程中,我们也参考这个逻辑实现了 https://github.com/WTFAcademy/WTF-Dapp/blob/main/demo-contract/contracts/wtfswap/SwapRouter.sol这个合约。

用大数来解决精度问题

在 Uniswap 的代码中,有很多的计算逻辑,比如按照当前价格和流动性计算交换的 Token,那这个过程中我们要避免除法操作的时候丢失精度。在 Uniswap 中,计算过程会经常用到「 << FixedPoint 96.RESOLUTION 」这个操作,它代表左移 96 位,相当于乘以「 2 ^ 96 」。左移之后再做除法运算,这样可以在正常交易不溢出(一般用「 uint 256 」来计算,还足够)的情况下保证精度。

代码如下(通过价格和流动性计算交易所需要的 Token 数):

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

可以看到,首先在 Uniswap 中价格都是用平方根乘以「 2 ^ 96 」(对应上面代码中的「 sqrtRatioAX 96 」和「 sqrtRatioBX 96 」),然后流动性「 liquidity 」会左移计算出「 numerator 1 」。在下面的计算中,「 2 ^ 96 」会在计算过程中被约掉,得到最后的结果。

当然,不管如何,理论上还是会有精度的丢失的,不过这种情况都是最小单位的丢失了,是可以接受的。

更多内容你可以学习 https://github.com/WTFAcademy/WTF-Dapp/blob/main/P106_PoolSwap/readme.md这一篇课程了解更多。

用 Share 的方式来计算收益

在 Uniswap 中,我们需要记录 LP(流动性提供者)的手续费收益。显然,我们不能在每次交易的时候都给每个 LP 记录各自的手续费,这样会消耗大量的 Gas。那怎么处理呢?

在 Uniswap 中,我们可以看到「 Position 」中定义了如下结构体:

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

其中包含了「 feeGrowthInside0LastX128 和 feeGrowthInside1LastX128 」,他们记录了每个头寸(Position)上一次提取手续费时候每个流动性应该收到的手续费。

简单点说,我只要记录总的手续费和每个流动性应该分配到多少手续费即可,这样 LP 提取手续费的时候按照手中的流动性就可以计算出他有多少可以提取的手续费。就好像你持有某个公司的股票,你要提取股票收益的时候只要知道公司历史的每股得收益,以及你上次提取时的收益即可。

之前我们在《巧妙的合约设计,看看 stETH 如何按天自动发放收益?让你的 ETH 参与质押获取稳定利息》这篇文章中也介绍过 stETH 的收益计算方法,也是类似的道理。

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

链上的存储是相对昂贵的,所以我们并不是所有的信息都要上链,或者从链上获取。比如 Uniswap 前端网站调用的很多接口就是传统的 Web2 的接口。

交易池的列表、交易池的信息等都可以存储在普通的数据库中,有的可能需要定期从链上同步,但是我们并不需要去实时调用链或者节点服务提供的 PRC 接口来获取相关数据。

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

当然,关键的交易肯定是在链上进行的。

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

一个项目可能包含多个实际部署的合约,即便是实际部署只有一个合约,但是我们代码可以通过继承的方式把合约拆分为多个合约来维护。

比如在 Uniswap 中,https://github.com/Uniswap/v3-periphery/blob/main/contracts/NonfungiblePositionManager.sol 合约就继承了很多合约,代码如下:

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

而且你在看「 ERC 721 Permit 」合约的实现时,你会发现它直接使用了「 @openzeppelin/contracts/token/ERC 721/ERC 721.sol 」合约,这样一方面方便通过 NFT 的方式来管理头寸,另外一方面也可以用已有的标准的合约来提高合约的开发效率。

在我们的课程中,你可以学习 https://github.com/WTFAcademy/WTF-Dapp/blob/main/ P 108 _PositionManager /readme.md尝试开发一个简单的 ERC 721 的合约来管理头寸。

总结

看再多的文章也不如自己上手开发来得实在,在尝试自己实现一个简易版的去中心化交易所的过程中能让你更深刻的理解 Uniswap 的代码实现,也可以学习到更多实际项目中会体会到的知识点。

WTF-DApp 课程是 ZAN 的开发者社区和 WTF Academy 开发者社区同学共同完成的开源课程。如果你也对 Web3,对 Defi 项目开发感兴趣,你可以参考我们的实战课程 https://github.com/WTFAcademy/WTF-Dapp,一步一步完成一个简易版的交易所,相信一定会对你有所帮助~

本文由 ZAN Team(X 账号 @zan_team) 的 Fisher(X 账号 @yudao 1024 )撰写。

Nội dung Liên quan

Ethereum và Bitcoin đối mặt với đợt siết nguồn cung lịch sử – 2 chỉ số này tiết lộ điều gì sắp xảy ra

Dù thị trường biến động nhiều tháng qua, nhưng các nhà nắm giữ Ethereum và Bitcoin vẫn thể hiện ít quan tâm đến việc chuyển coin trở lại các sàn giao dịch. Điều này phản ánh nhiều hơn là sự giảm nhiệt tình giao dịch của nhà đầu tư. Các khoản rút tiền liên tục tiếp tục làm giảm nguồn cung lưu động sẵn có trên thị trường. Số lượng Bitcoin trên các sàn đang ở mức thấp nhất kể từ năm 2017, trong khi số Ethereum (ETH) trên sàn cũng ở mức thấp kỷ lục kể từ năm 2015. Dòng chảy ròng âm liên tục cho thấy các tổ chức và nhà nắm giữ dài hạn đang ưa chuộng các mô hình tự lưu ký như ETF hoặc kho bạc công ty. Sự di chuyển này sẽ loại bỏ thêm coin khỏi áp lực bán tiềm năng, tạo ra sự khan hiếm và có thể khuếch đại biến động giá nếu nhu cầu phục hồi. Ở phía sau, các Nhà Nắm Giữ Dài Hạn Bitcoin đang ổn định hấp thụ nguồn cung lưu hành. Chỉ số Thay đổi Vị thế Ròng của Nhà Nắm Giữ Dài Hạn đã trở lại vùng tích cực, xác nhận sự chuyển dịch từ phân phối sang tích lũy. Nguồn cung do Nhà Nắm Giữ Dài Hạn nắm giữ đang tiến gần 15 triệu BTC, trong khi nguồn cung của Nhà Nắm Giữ Ngắn Hạn giảm xuống khoảng 16,75 triệu BTC. Hành vi này cho thấy Bitcoin đang chuyển từ những người tham gia ngắn hạn sang những người nắm giữ có niềm tin vững chắc hơn. Tóm lại, mặc dù nguồn cung trên sàn của cả Bitcoin và Ethereum đang thắt chặt, củng cố xu hướng tích lũy dài hạn, nhưng Bitcoin vẫn cần nhu cầu mua mạnh mẽ hơn để duy trì đà phục hồi bền vững giữa bối cảnh nguồn cung đang thu hẹp.

ambcrypto2 giờ trước

Ethereum và Bitcoin đối mặt với đợt siết nguồn cung lịch sử – 2 chỉ số này tiết lộ điều gì sắp xảy ra

ambcrypto2 giờ trước

AxBlade × AWS Hong Kong Summit Kết Thúc: Định Nghĩa Tính Chịu Trách Nhiệm cho Physical AI

AxBlade, lớp trách nhiệm giải trình cho AI tự trị, đã đồng tổ chức sự kiện bên lề độc quyền "Từ AI Tác nhân đến AI Vật lý: Điều gì sẽ được tài trợ sau Làn sóng Mô hình?" cùng với AWS Summit Hong Kong. Sự kiện chỉ dành cho khách mời, quy tụ hơn 100 nhà sáng lập, nhà nghiên cứu, lãnh đạo doanh nghiệp và nhà đầu tư để thảo luận về khoảng trống hạ tầng quan trọng giữa demo AI và triển khai thực tế. Các phiên thảo luận đi đến đồng thuận: nếu không có danh tính có thể xác minh, môi trường thực thi đáng tin cậy và hồ sơ hoạt động có thể chứng minh bằng mật mã, AI Vật lý không thể chuyển từ phòng thí nghiệm sang sản xuất. Các chủ đề bao gồm xu hướng đầu tư vào hạ tầng, các thách thức về trách nhiệm pháp lý, an toàn, quản trị và phần mềm trung gian kỹ thuật cần thiết để chuyển từ demo sang triển khai doanh nghiệp. Là lớp hạ tầng blockchain duy nhất được giới thiệu tại hội nghị, AxBlade trình bày giải pháp kết hợp Blockchain Layer 2, Danh tính AI (DID), Môi trường Thực thi Tin cậy (TEE) và Bằng chứng Không tiết lộ Thông tin về Hành vi (PoB) để giải quyết khoảng trống trách nhiệm giải trình, giúp các hệ thống tự trị có thể kiểm tra, truy xuất nguồn gốc và tuân thủ.

TheNewsCrypto3 giờ trước

AxBlade × AWS Hong Kong Summit Kết Thúc: Định Nghĩa Tính Chịu Trách Nhiệm cho Physical AI

TheNewsCrypto3 giờ trước

CFTC cáo buộc nhà quản lý quỹ che giấu thua lỗ crypto, hợp đồng tương lai sau lợi nhuận giả mạo cho nhà đầu tư

Ủy ban Giao dịch Hàng hóa Tương lai Hoa Kỳ (CFTC) đã cáo buộc Trevor L. Vernon và công ty Argent Capital Management LLC ở North Carolina thực hiện hành vi gian lận. Họ bị cáo buộc đã huy động hơn 14 triệu USD từ ít nhất 60 nhà đầu tư thông qua một quỹ đầu tư (commodity pool), đồng thời che giấu những tổn thất giao dịch lớn trong lĩnh vực tương lai, quyền chọn và tài sản tiền mã hóa. Theo đơn khiếu nại, từ tháng 3/2022 đến tháng 2/2026, các bị cáo đã trình bày quỹ như một khoản đầu tư luôn có lãi, phân phối báo cáo hiệu suất và báo cáo thuế giả mạo để thể hiện lợi nhuận không có thực. Trên thực tế, họ đã phải chịu tổn thất hơn 8,6 triệu USD, bao gồm hơn 108.000 USD từ giao dịch Bitcoin và Ether trên các sàn tiền mã hóa cá nhân. CFTC cáo buộc một phần tiền của nhà đầu tư mới đã được sử dụng để trả cho người tham gia trước đó, theo mô hình giống như Ponzi. Ngoài cáo buộc gian lận, CFTC còn cho rằng công ty này hoạt động mà không đăng ký với tư cách nhà điều hành quỹ hàng hóa theo quy định. CFTC đang yêu cầu bồi thường cho các nhà đầu tư, tịch thu lợi nhuận bất hợp pháp, phạt tiền, áp dụng lệnh cấm giao dịch vĩnh viễn và các biện pháp ngăn chặn vi phạm. Các cáo buộc hiện chưa được chứng minh và vụ việc sẽ được xét xử tại tòa án liên bang.

ambcrypto3 giờ trước

CFTC cáo buộc nhà quản lý quỹ che giấu thua lỗ crypto, hợp đồng tương lai sau lợi nhuận giả mạo cho nhà đầu tư

ambcrypto3 giờ trước

Primit Chính Thức Triển Khai Trên Avalanche, Khởi Động Chương Trình Khuyến Khích Giao Dịch Mùa 1

Primit đã chính thức triển khai trên mạng Avalanche và sẽ khởi động Chương trình khuyến khích giao dịch Mùa 1 có tên "On-Chain Perp Frenzy" vào ngày 15 tháng 7. Sự kiện kéo dài 14 ngày này có tổng giải thưởng lên tới 100,000 USD tương đương bằng AVAX, mở cửa cho tất cả các nhà giao dịch hợp đồng vĩnh cửu trên chuỗi. Primit chọn Avalanche nhờ khả năng hoàn tất giao dịch trong chưa đầy một giây và chi phí gas tối thiểu, lý tưởng cho các giao dịch phái sinh cần độ trễ thấp. Mục tiêu của Mùa 1 là chứng minh năng lực xử lý nhu cầu giao dịch chuyên nghiệp trên chuỗi. Chương trình khuyến khích bao gồm bốn cơ chế phần thưởng: Phần thưởng Ngẫu nhiên Hàng ngày (20 người dùng chia sẻ $400 mỗi ngày), Phần thưởng Đóng góp trên Twitter ($3,000 cho nội dung chất lượng), Cơ chế Hoàn trả Giới thiệu ($50,000 chia theo khối lượng giới thiệu) và Bảng xếp hạng Khối lượng Giao dịch ($37,800 cho 120 nhà giao dịch hàng đầu). Các cặp giao dịch liên quan đến AVAX được áp dụng hệ số nhân 1.5x khi tính khối lượng. Song song với sự kiện, Primit cũng ra mắt cấu trúc phí Maker/Taker phân cấp dựa trên khối lượng giao dịch tích lũy, sẽ trở thành tiêu chuẩn lâu dài của nền tảng. **Cổng thông tin sự kiện:** https://primit.io/ hoặc https://app.primit.io/trade **Thời gian sự kiện:** 15/7/2026 – 28/7/2026

TheNewsCrypto4 giờ trước

Primit Chính Thức Triển Khai Trên Avalanche, Khởi Động Chương Trình Khuyến Khích Giao Dịch Mùa 1

TheNewsCrypto4 giờ trước

Giao dịch

Giao ngay
活动图片