Kỹ thuật phát triển hợp đồng: Những kinh nghiệm quý giá học được từ mã Uniswap
Gần đây, khi viết hướng dẫn phát triển sàn giao dịch phi tập trung, tôi đã học được nhiều kỹ năng phát triển hợp đồng thông qua việc nghiên cứu mã nguồn của Uniswap V3. Là một người mới bắt đầu tìm hiểu về phát triển hợp đồng Defi, những mẹo nhỏ này đã mang lại cho tôi nhiều cảm hứng, và tôi tin rằng nó cũng sẽ hữu ích cho những người mới muốn học phát triển hợp đồng khác.
Địa chỉ triển khai hợp đồng có thể dự đoán
Thông thường, địa chỉ nhận được từ việc triển khai hợp đồng có vẻ ngẫu nhiên, khó dự đoán. Nhưng trong một số tình huống, chúng ta cần suy luận địa chỉ hợp đồng thông qua cặp giao dịch và thông tin liên quan, chẳng hạn như xác định quyền giao dịch hoặc lấy địa chỉ của bể.
Uniswap sử dụng phương pháp CREATE2 để tạo hợp đồng, thông qua việc thêm tham số "salt" để làm cho địa chỉ hợp đồng được tạo ra có thể dự đoán. Logic tạo địa chỉ mới như sau: hash("0xFF", địa chỉ của người tạo, salt, initcode). Phương pháp này rất hữu ích trong nhiều trường hợp.
Sử dụng hàm callback một cách hiệu quả
Hợp đồng trong Solidity có thể gọi lẫn nhau. Đôi khi A gọi phương thức của B, B trong phương thức được gọi sẽ gọi lại A, điều này rất hữu ích trong một số tình huống.
Ví dụ trong phương thức swap của Uniswap, hợp đồng UniswapV3Pool sẽ gọi lại swapCallback, truyền vào Token thực tế cần thiết cho giao dịch này. Bên gọi cần chuyển Token cần thiết vào UniswapV3Pool trong callback, thay vì tách biệt phương thức swap. Điều này đảm bảo tính an toàn và thực hiện đầy đủ của phương thức swap, không cần ghi chép biến phức tạp.
Sử dụng ngoại lệ để truyền thông tin, sử dụng try catch để thực hiện ước lượng giao dịch
Trong hợp đồng Quoter của Uniswap, sử dụng try catch để bao bọc việc thực hiện phương thức swap của UniswapV3Pool. Điều này nhằm mô phỏng việc swap để ước lượng Token cần thiết cho giao dịch. Khi ước lượng sẽ không thực sự hoán đổi Token, vì vậy sẽ báo lỗi. Uniswap thông qua việc ném ra lỗi đặc biệt trong hàm callback, sau đó bắt lỗi đó và phân tích thông tin cần thiết.
Phương pháp này có vẻ như là một mẹo, nhưng rất thực tế. Không cần phải cải tiến phương pháp swap để ước lượng nhu cầu giao dịch, logic trở nên đơn giản hơn.
Giải quyết vấn đề độ chính xác của số lớn
Mã Uniswap liên quan đến nhiều logic tính toán, chẳng hạn như tính toán Token được hoán đổi dựa trên giá hiện tại và tính thanh khoản. Để tránh mất độ chính xác trong phép chia, quá trình tính toán thường sử dụng "<< FixedPoint96.RESOLUTION" để dịch trái 96 bit, tương đương với việc nhân với 2^96. Sau khi dịch trái, thực hiện phép chia, đảm bảo độ chính xác trong trường hợp giao dịch không bị tràn.
Mặc dù về lý thuyết vẫn có sự mất mát độ chính xác nhỏ, nhưng đã có thể chấp nhận.
Tính toán lợi nhuận theo phương thức chia sẻ
Uniswap cần ghi lại lợi nhuận phí giao dịch của nhà cung cấp thanh khoản LP(. Rõ ràng là không thể ghi lại phí cho mỗi nhà cung cấp thanh khoản trong mỗi giao dịch, điều này sẽ tiêu tốn một lượng lớn Gas.
Cấu trúc Position của Uniswap bao gồm feeGrowthInside0LastX128 và feeGrowthInside1LastX128, ghi lại phí giao dịch mà mỗi thanh khoản nên nhận được khi rút phí lần cuối cho mỗi vị trí.
Chỉ cần ghi lại tổng phí giao dịch và phí giao dịch nên được phân bổ cho mỗi thanh khoản, phí giao dịch có thể rút khi LP rút tiền sẽ được tính dựa trên thanh khoản nắm giữ. Tương tự như việc nắm giữ cổ phiếu công ty, khi rút lợi nhuận chỉ cần biết lợi nhuận mỗi cổ phiếu trong quá khứ và lợi nhuận tại lần rút trước.
![Web3 người mới series: Những mẹo nhỏ trong phát triển hợp đồng mà tôi học được từ mã Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Thông tin không quan trọng không cần phải đưa lên chuỗi
Lưu trữ trên chuỗi tương đối đắt đỏ, không phải tất cả thông tin đều cần phải lên chuỗi hoặc lấy từ chuỗi. Ví dụ, nhiều giao diện mà front-end Uniswap gọi là giao diện Web2 truyền thống.
Danh sách hồ giao dịch, thông tin, v.v. có thể được lưu trữ trong cơ sở dữ liệu thông thường, một phần cần được đồng bộ từ chuỗi theo định kỳ. Không cần gọi giao diện RPC của chuỗi hoặc dịch vụ nút theo thời gian thực để lấy dữ liệu liên quan.
Tất nhiên, các giao dịch quan trọng phải được thực hiện trên chuỗi.
Phân tách hợp đồng và sử dụng hợp đồng tiêu chuẩn
Một dự án có thể bao gồm nhiều hợp đồng được triển khai thực tế. Ngay cả khi chỉ có một hợp đồng được triển khai thực tế, nó cũng có thể được chia thành nhiều hợp đồng để bảo trì thông qua kế thừa.
Hợp đồng NonfungiblePositionManager của Uniswap kế thừa từ nhiều hợp đồng khác nhau. Trong đó, ERC721Permit sử dụng trực tiếp hợp đồng ERC721 của OpenZeppelin, vừa thuận tiện cho việc quản lý vị thế qua NFT, vừa nâng cao hiệu quả phát triển.
Kết luận
Thực hành phát triển một sàn giao dịch phi tập trung đơn giản sẽ giúp bạn hiểu sâu hơn về cách triển khai mã của Uniswap, và học hỏi nhiều kiến thức từ các dự án thực tế. Đọc nhiều bài viết cũng không bằng thực hành, hy vọng những kinh nghiệm này sẽ hữu ích cho những người mới muốn học phát triển hợp đồng.
![Web3 Người mới bắt đầu: Những mẹo nhỏ phát triển hợp đồng tôi học được từ mã Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
20 thích
Phần thưởng
20
10
Đăng lại
Chia sẻ
Bình luận
0/400
GasGuzzler
· 07-18 21:18
Kệ, đừng chơi sâu với người mới.
Xem bản gốcTrả lời0
LowCapGemHunter
· 07-17 14:17
Mẹo cần thiết cho các lập trình viên kỳ cựu đây!
Xem bản gốcTrả lời0
SmartMoneyWallet
· 07-15 22:24
Giao dịch on-chain nào cũng không thoát khỏi mắt tôi.
Xem bản gốcTrả lời0
WalletDetective
· 07-15 22:24
v3 đơn giản như vậy sao? Xem xong mới phát hiện tôi chẳng hiểu gì cả.
Xem bản gốcTrả lời0
gas_guzzler
· 07-15 22:21
Lại đang dựa vào khả năng để Phiếu giảm giá
Xem bản gốcTrả lời0
AllInDaddy
· 07-15 21:55
Mã của V3 thật sự rất cứng.
Xem bản gốcTrả lời0
SleepyValidator
· 07-15 21:55
Nói chi tiết như vậy còn không bằng tự mình cuộn mã nguồn.
7 mẹo phát triển hợp đồng Uniswap: Nâng cao hiệu quả và tính an toàn cho dự án Tài chính phi tập trung
Kỹ thuật phát triển hợp đồng: Những kinh nghiệm quý giá học được từ mã Uniswap
Gần đây, khi viết hướng dẫn phát triển sàn giao dịch phi tập trung, tôi đã học được nhiều kỹ năng phát triển hợp đồng thông qua việc nghiên cứu mã nguồn của Uniswap V3. Là một người mới bắt đầu tìm hiểu về phát triển hợp đồng Defi, những mẹo nhỏ này đã mang lại cho tôi nhiều cảm hứng, và tôi tin rằng nó cũng sẽ hữu ích cho những người mới muốn học phát triển hợp đồng khác.
Địa chỉ triển khai hợp đồng có thể dự đoán
Thông thường, địa chỉ nhận được từ việc triển khai hợp đồng có vẻ ngẫu nhiên, khó dự đoán. Nhưng trong một số tình huống, chúng ta cần suy luận địa chỉ hợp đồng thông qua cặp giao dịch và thông tin liên quan, chẳng hạn như xác định quyền giao dịch hoặc lấy địa chỉ của bể.
Uniswap sử dụng phương pháp CREATE2 để tạo hợp đồng, thông qua việc thêm tham số "salt" để làm cho địa chỉ hợp đồng được tạo ra có thể dự đoán. Logic tạo địa chỉ mới như sau: hash("0xFF", địa chỉ của người tạo, salt, initcode). Phương pháp này rất hữu ích trong nhiều trường hợp.
Sử dụng hàm callback một cách hiệu quả
Hợp đồng trong Solidity có thể gọi lẫn nhau. Đôi khi A gọi phương thức của B, B trong phương thức được gọi sẽ gọi lại A, điều này rất hữu ích trong một số tình huống.
Ví dụ trong phương thức swap của Uniswap, hợp đồng UniswapV3Pool sẽ gọi lại swapCallback, truyền vào Token thực tế cần thiết cho giao dịch này. Bên gọi cần chuyển Token cần thiết vào UniswapV3Pool trong callback, thay vì tách biệt phương thức swap. Điều này đảm bảo tính an toàn và thực hiện đầy đủ của phương thức swap, không cần ghi chép biến phức tạp.
Sử dụng ngoại lệ để truyền thông tin, sử dụng try catch để thực hiện ước lượng giao dịch
Trong hợp đồng Quoter của Uniswap, sử dụng try catch để bao bọc việc thực hiện phương thức swap của UniswapV3Pool. Điều này nhằm mô phỏng việc swap để ước lượng Token cần thiết cho giao dịch. Khi ước lượng sẽ không thực sự hoán đổi Token, vì vậy sẽ báo lỗi. Uniswap thông qua việc ném ra lỗi đặc biệt trong hàm callback, sau đó bắt lỗi đó và phân tích thông tin cần thiết.
Phương pháp này có vẻ như là một mẹo, nhưng rất thực tế. Không cần phải cải tiến phương pháp swap để ước lượng nhu cầu giao dịch, logic trở nên đơn giản hơn.
Giải quyết vấn đề độ chính xác của số lớn
Mã Uniswap liên quan đến nhiều logic tính toán, chẳng hạn như tính toán Token được hoán đổi dựa trên giá hiện tại và tính thanh khoản. Để tránh mất độ chính xác trong phép chia, quá trình tính toán thường sử dụng "<< FixedPoint96.RESOLUTION" để dịch trái 96 bit, tương đương với việc nhân với 2^96. Sau khi dịch trái, thực hiện phép chia, đảm bảo độ chính xác trong trường hợp giao dịch không bị tràn.
Mặc dù về lý thuyết vẫn có sự mất mát độ chính xác nhỏ, nhưng đã có thể chấp nhận.
Tính toán lợi nhuận theo phương thức chia sẻ
Uniswap cần ghi lại lợi nhuận phí giao dịch của nhà cung cấp thanh khoản LP(. Rõ ràng là không thể ghi lại phí cho mỗi nhà cung cấp thanh khoản trong mỗi giao dịch, điều này sẽ tiêu tốn một lượng lớn Gas.
Cấu trúc Position của Uniswap bao gồm feeGrowthInside0LastX128 và feeGrowthInside1LastX128, ghi lại phí giao dịch mà mỗi thanh khoản nên nhận được khi rút phí lần cuối cho mỗi vị trí.
Chỉ cần ghi lại tổng phí giao dịch và phí giao dịch nên được phân bổ cho mỗi thanh khoản, phí giao dịch có thể rút khi LP rút tiền sẽ được tính dựa trên thanh khoản nắm giữ. Tương tự như việc nắm giữ cổ phiếu công ty, khi rút lợi nhuận chỉ cần biết lợi nhuận mỗi cổ phiếu trong quá khứ và lợi nhuận tại lần rút trước.
![Web3 người mới series: Những mẹo nhỏ trong phát triển hợp đồng mà tôi học được từ mã Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Thông tin không quan trọng không cần phải đưa lên chuỗi
Lưu trữ trên chuỗi tương đối đắt đỏ, không phải tất cả thông tin đều cần phải lên chuỗi hoặc lấy từ chuỗi. Ví dụ, nhiều giao diện mà front-end Uniswap gọi là giao diện Web2 truyền thống.
Danh sách hồ giao dịch, thông tin, v.v. có thể được lưu trữ trong cơ sở dữ liệu thông thường, một phần cần được đồng bộ từ chuỗi theo định kỳ. Không cần gọi giao diện RPC của chuỗi hoặc dịch vụ nút theo thời gian thực để lấy dữ liệu liên quan.
Tất nhiên, các giao dịch quan trọng phải được thực hiện trên chuỗi.
Phân tách hợp đồng và sử dụng hợp đồng tiêu chuẩn
Một dự án có thể bao gồm nhiều hợp đồng được triển khai thực tế. Ngay cả khi chỉ có một hợp đồng được triển khai thực tế, nó cũng có thể được chia thành nhiều hợp đồng để bảo trì thông qua kế thừa.
Hợp đồng NonfungiblePositionManager của Uniswap kế thừa từ nhiều hợp đồng khác nhau. Trong đó, ERC721Permit sử dụng trực tiếp hợp đồng ERC721 của OpenZeppelin, vừa thuận tiện cho việc quản lý vị thế qua NFT, vừa nâng cao hiệu quả phát triển.
Kết luận
Thực hành phát triển một sàn giao dịch phi tập trung đơn giản sẽ giúp bạn hiểu sâu hơn về cách triển khai mã của Uniswap, và học hỏi nhiều kiến thức từ các dự án thực tế. Đọc nhiều bài viết cũng không bằng thực hành, hy vọng những kinh nghiệm này sẽ hữu ích cho những người mới muốn học phát triển hợp đồng.
![Web3 Người mới bắt đầu: Những mẹo nhỏ phát triển hợp đồng tôi học được từ mã Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(