Khám phá các cơ chế cốt lõi của UniswapV4

Nâng cao12/24/2023, 2:50:42 PM
Bài viết này diễn giải ba tính năng cải tiến của UniswapV4 - Flash Accounting, Singleton Contract và Hooks Architecture - từ góc độ mã và triển khai.

Giới thiệu:

Kể từ khi UniswapV4 được công bố, nền tảng hoán đổi này đã trải qua một sự chuyển đổi đáng kể, phát triển từ một nền tảng hoán đổi đơn giản thành nhà cung cấp dịch vụ cơ sở hạ tầng. Đặc biệt, tính năng Hooks của V4 đã nhận được sự quan tâm rộng rãi. Sau khi nghiên cứu chuyên sâu, tôi đã biên soạn một số nội dung nhằm giúp mọi người hiểu rõ hơn về sự chuyển đổi này và cách thực hiện nó.

Trọng tâm đổi mới của UniswapV4 không chỉ là cải tiến công nghệ AMM mà còn là mở rộng hệ sinh thái. Cụ thể, sự đổi mới này bao gồm các tính năng chính sau:

  • Kế toán Flash
  • Hợp đồng đơn lẻ
  • Kiến trúc móc

Trong các phần sau, tôi sẽ giải thích chi tiết tầm quan trọng của các tính năng này và nguyên tắc triển khai chúng.

nguồn: https://twitter.com/jermywkh/status/1670779830621851650

Kế toán Flash

Kế toán kép

UniswapV4 áp dụng phương pháp lưu giữ hồ sơ tương tự như Sổ sách kế toán kép để theo dõi sự thay đổi số dư của các token tương ứng với từng hoạt động. Phương pháp ghi sổ kép này yêu cầu ghi lại đồng thời từng giao dịch trong nhiều tài khoản và đảm bảo số dư tài sản giữa các tài khoản này vẫn được cân bằng. Ví dụ: giả sử người dùng trao đổi 100 TokenA lấy 50 TokenB từ nhóm. Việc ghi vào sổ cái sẽ như sau:

  • NGƯỜI DÙNG: TokenA giảm 100 đơn vị (-100), trong khi TokenB tăng 50 đơn vị (+50).
  • POOL: TokenA tăng 100 đơn vị (+100), trong khi TokenB giảm 50 đơn vị (-50).

Token Delta và các hoạt động liên quan

Trong UniswapV4, phương pháp lưu giữ hồ sơ này chủ yếu được sử dụng cho các hoạt động chính và một biến lưu trữ có tên lockState.currencyDelta[currency] được sử dụng trong mã để ghi lại số lượng thay đổi số dư mã thông báo. Nếu giá trị của delta này là dương thì nó biểu thị mức tăng dự kiến về số lượng mã thông báo trong nhóm, trong khi giá trị âm biểu thị mức giảm dự kiến về số lượng mã thông báo. Ngoài ra, nếu giá trị dương, nó cho biết lượng token thiếu hụt trong nhóm (số tiền dự kiến sẽ nhận được), trong khi giá trị âm cho biết lượng token dư thừa trong nhóm (số tiền dự kiến để người dùng rút). Danh sách sau đây cho thấy tác động của các hoạt động khác nhau trên Token Delta:

  • sửa đổiPosition: Thể hiện hoạt động Thêm/Xóa tính thanh khoản. Để Thêm tính thanh khoản, TokenDelta được cập nhật bằng cách sử dụng phép cộng (thể hiện số lượng TokenA dự kiến sẽ được thêm vào nhóm). Để loại bỏ tính thanh khoản, TokenDelta được cập nhật bằng phép trừ (thể hiện số lượng TokenB dự kiến sẽ được rút khỏi nhóm).
  • trao đổi: Thể hiện hoạt động Hoán đổi. Lấy ví dụ về việc hoán đổi TokenA lấy TokenB, TokenADelta được cập nhật bằng phép cộng, trong khi TokenBDelta được cập nhật bằng phép trừ.
  • giải quyết: Đi kèm với việc chuyển mã thông báo vào nhóm. Nhóm tính toán mức tăng số lượng mã thông báo trước và sau và cập nhật TokenDelta bằng phép trừ. Nếu nhóm nhận được số lượng mã thông báo dự kiến, phép trừ sẽ tạo ra TokenDelta.
  • lấy: Đi kèm với việc rút mã thông báo khỏi nhóm. TokenDelta được cập nhật bằng cách sử dụng tính năng bổ sung, cho biết rằng các mã thông báo đã bị xóa khỏi nhóm.
  • mint: Hành vi cập nhật TokenDelta tương tự như "lấy", nhưng thay vì thực sự rút mã thông báo khỏi nhóm, mã thông báo ERC1155 được phát hành làm bằng chứng rút tiền, trong khi mã thông báo vẫn ở trong nhóm. Sau đó, người dùng có thể truy xuất mã thông báo từ nhóm bằng cách ghi mã thông báo ERC1155. Mục đích của phương pháp này có thể gồm hai phần: 1. Tiết kiệm chi phí gas cho việc chuyển mã thông báo ERC20 (gọi hợp đồng + ghi ít bộ nhớ hơn) và sử dụng tính năng ghi mã thông báo ERC1155 trong tương lai để cập nhật TokenDelta cho các giao dịch. 2. Duy trì tính thanh khoản trong nhóm để duy trì nhóm thanh khoản sâu nhằm mang lại trải nghiệm hoán đổi tốt hơn cho người dùng.
  • donate: Hoạt động này tuyên bố quyên góp mã thông báo cho nhóm, nhưng trên thực tế, mã thông báo vẫn cần được chuyển vào nhóm bằng cách sử dụng “giải quyết”. Do đó, TokenDelta được cập nhật bằng phép cộng trong trường hợp này.

Trong số các hoạt động này, chỉ có “thanh toán” và “nhận” liên quan đến việc chuyển mã thông báo thực tế, trong khi các hoạt động khác hoàn toàn chịu trách nhiệm cập nhật giá trị TokenDelta.

Ví dụ về đồng bằng mã thông báo

Ở đây chúng tôi sử dụng một ví dụ đơn giản để minh họa cách cập nhật TokenDelta. Giả sử hôm nay chúng ta đổi 100 TokenA lấy 50 TokenB:

  1. Trước khi giao dịch bắt đầu, cả TokenADelta và TokenBDelta đều bằng 0.
  2. swap: Tính toán số lượng TokenA mà Pool cần nhận và số lượng TokenB mà người dùng sẽ nhận được. Tại thời điểm này, TokenADelta = 100, TokenBDelta = -50.
  3. giải quyết: Gửi 100 TokenA vào Pool và cập nhật TokenADelta = 100 - 100 = 0.
  4. lấy: Chuyển 50 TokenB từ Pool vào tài khoản của người dùng và cập nhật TokenBDelta = -50 + 50 = 0.
  5. Sau khi giao dịch hoàn tất, cả TokenADelta và TokenBDelta đều bằng 0.

Khi toàn bộ hoạt động trao đổi hoàn tất, cả TokenADelta và TokenBDelta đều được đặt lại về 0. Điều này có nghĩa là hoạt động đã được cân bằng hoàn toàn, do đó đảm bảo tính nhất quán của số dư tài khoản.

EIP-1153: Mã hoạt động lưu trữ tạm thời

Trước đây, người ta đã đề cập rằng UniswapV4 sử dụng Biến lưu trữ để ghi lại TokenDelta. Tuy nhiên, trong hợp đồng, việc đọc và ghi vào Biến lưu trữ khá tốn kém. Điều này đưa chúng ta đến một EIP khác được Uniswap giới thiệu: EIP1153 - Transient Storage Opcodes.

UniswapV4 có kế hoạch sử dụng opcode TSTORE và TLOAD do EIP1153 cung cấp để cập nhật TokenDelta. Các Biến lưu trữ áp dụng Mã lưu trữ tạm thời sẽ bị loại bỏ sau khi kết thúc giao dịch (tương tự như Biến bộ nhớ), do đó giảm phí gas.

EIP1153 đã được xác nhận sẽ có trong bản nâng cấp Cancun sắp tới và UniswapV4 cũng đã tuyên bố rằng nó sẽ đi vào hoạt động sau bản nâng cấp Cancun, như đã báo cáo tại đây.

nguồn: https://etherworld.co/2022/12/13/transient-storage-for-beginners/

Kế toán Flash - Khóa

UniswapV4 giới thiệu cơ chế khóa, có nghĩa là trước khi thực hiện bất kỳ thao tác Pool nào, trước tiên bạn phải gọi PoolManager.lock() để lấy khóa. Trong quá trình thực thi lock(), nó sẽ kiểm tra xem giá trị TokenDelta có bằng 0 hay không, nếu không nó sẽ hoàn nguyên. Khi PoolManager.lock() được lấy thành công, nó sẽ gọi hàm lockAcquired() của msg.sender. Bên trong hàm lockAcquired(), các thao tác liên quan đến Nhóm, chẳng hạn như trao đổi và sửa đổi Vị trí, được thực hiện.

Quá trình này được minh họa dưới đây. Khi người dùng cần thực hiện thao tác Hoán đổi mã thông báo, họ phải gọi Hợp đồng thông minh có chức năng lockAcquired() (gọi tắt là Hợp đồng gọi lại). Hợp đồng gọi lại lần đầu tiên gọi PoolManager.lock(), và sau đó PoolManager gọi hàm lockAcquired() của Hợp đồng gọi lại. Bên trong hàm lockAcquired(), logic liên quan đến các hoạt động của Pool, chẳng hạn như trao đổi, giải quyết và lấy, được xác định. Cuối cùng, khi lock() sắp kết thúc, PoolManager sẽ kiểm tra xem TokenDelta được liên kết với thao tác này có được đặt lại về 0 hay không, đảm bảo số dư tài sản trong Pool vẫn còn nguyên.

Hợp đồng đơn lẻ

Hợp đồng Singleton có nghĩa là UniswapV4 đã từ bỏ mô hình Factory-Pool trước đó. Mỗi Nhóm không còn là một Hợp đồng Thông minh độc lập nữa mà tất cả các Nhóm đều có chung một hợp đồng đơn lẻ. Thiết kế này, kết hợp với cơ chế Flash Accounting, chỉ yêu cầu cập nhật các Biến lưu trữ cần thiết, giúp giảm hơn nữa độ phức tạp và chi phí vận hành.

Trong ví dụ bên dưới, lấy UniswapV3 làm ví dụ, việc trao đổi ETH lấy DAI sẽ yêu cầu ít nhất bốn lần chuyển Token (Hoạt động ghi lưu trữ). Điều này bao gồm nhiều thay đổi được ghi lại đối với các Token USDC, USDT và DAI. Tuy nhiên, với những cải tiến trong UniswapV4, kết hợp với cơ chế Flash Accounting, chỉ cần một lần chuyển Token (chuyển DAI từ Pool đến người dùng), giúp giảm đáng kể số lượng thao tác và chi phí.

nguồn: https://twitter.com/Uniswap/status/1671208668304486404

Kiến trúc móc

Trong bản cập nhật mới nhất của UniswapV4, tính năng đáng chú ý nhất là Hooks Architecture. Bản cập nhật này mang lại sự linh hoạt cao về tính khả dụng của Pool. Móc là các hành động bổ sung được kích hoạt thông qua Hợp đồng Móc khi thực hiện các hoạt động cụ thể trên Nhóm. Những hành động này được phân loại thành khởi tạo (tạo nhóm), sửa đổiPosition (thêm/xóa tính thanh khoản), hoán đổi và quyên góp. Mỗi danh mục có các hành động trước khi thực hiện và sau khi thực hiện.

  • beforeInitialize / afterInitialize
  • beforeModifyPosition / afterModifyPosition
  • trướcSwap / afterSwap
  • beforeDonate / afterDonate

Thiết kế này cho phép người dùng thực thi logic tùy chỉnh trước và sau các hoạt động cụ thể, giúp nó linh hoạt hơn và mở rộng chức năng của UniswapV4.

nguồn: https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf

Ví dụ về Hook - Hook giới hạn lệnh

Tiếp theo, chúng tôi sẽ sử dụng ví dụ về Lệnh giới hạn để giải thích quy trình hoạt động thực tế của Hooks trong UniswapV4. Trước khi bắt đầu, hãy giải thích ngắn gọn nguyên tắc triển khai Lệnh giới hạn trong UniswapV4.

Cơ chế đặt hàng giới hạn UniswapV4

Việc triển khai lệnh giới hạn UniswapV4 hoạt động bằng cách thêm thanh khoản vào một phạm vi giá cụ thể và sau đó thực hiện thao tác loại bỏ thanh khoản nếu thanh khoản trong phạm vi đó được hoán đổi.

Ví dụ: giả sử chúng tôi thêm tính thanh khoản trong phạm vi giá 1900-2000 cho ETH và sau đó giá ETH tăng từ 1800 lên 2100. Tại thời điểm này, tất cả thanh khoản ETH mà chúng tôi đã thêm trước đây trong phạm vi giá 1900-2000 đã được hoán đổi lấy USDC (giả sử trong nhóm ETH-USDC). Bằng cách loại bỏ tính thanh khoản tại thời điểm này, chúng tôi có thể đạt được hiệu quả tương tự như thực hiện lệnh thị trường ETH ở mức giá hiện tại là 1900-2000.

Hợp đồng móc lệnh giới hạn

Ví dụ này được lấy từ GitHub của UniswapV4. Trong ví dụ này, hợp đồng Limit Order Hook cung cấp hai hook, đó là afterInitialize và afterSwap. hook afterInitialize được sử dụng để ghi lại phạm vi giá (đánh dấu) khi tạo nhóm, nhằm xác định lệnh giới hạn nào đã được khớp sau khi ai đó hoán đổi.

Lập tức đăng ký

Khi người dùng cần đặt hàng, hợp đồng Hook sẽ thực hiện thao tác bổ sung thanh khoản dựa trên phạm vi giá và số lượng do người dùng chỉ định. Trong hợp đồng Hook cho các lệnh giới hạn, bạn có thể thấy hàm place() . Logic chính là gọi hàm lockAcquiredPlace() sau khi có được khóa để thực hiện thao tác bổ sung thanh khoản, tương đương với việc đặt lệnh giới hạn.

nguồn: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L246

sauSwap Hook

Sau khi người dùng hoàn thành Swap Token trong Pool này, Pool sẽ gọi hàm afterSwap() của hợp đồng Hook. Logic chính của afterSwap là loại bỏ tính thanh khoản của các lệnh đã đặt trước đó đã được khớp giữa phạm vi giá trước đó và phạm vi giá hiện tại. Hành vi này tương đương với đơn hàng đang được điền.

nguồn: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L192

Giới hạn dòng lệnh

Dưới đây là sơ đồ minh họa quá trình thực hiện lệnh giới hạn:

  1. Người đặt hàng sẽ gửi đơn đặt hàng đến hợp đồng Hook.
  2. Hợp đồng Hook thực hiện các hoạt động bổ sung thanh khoản dựa trên thông tin đơn hàng.
  3. Người dùng thông thường thực hiện các hoạt động Hoán đổi Token trong Pool.
  4. Sau khi hoàn thành thao tác Swap Token, Pool gọi hàm afterSwap() của hợp đồng Hook.
  5. Hợp đồng Hook thực hiện các hoạt động loại bỏ thanh khoản cho các lệnh giới hạn đã được thực hiện dựa trên sự thay đổi phạm vi giá của các token được hoán đổi.

Trên đây là toàn bộ quá trình thực hiện Limit-Order bằng cơ chế Hook.

Móc: Các tính năng khác

Hooks có một số điểm thú vị mà tôi thấy đáng chia sẻ.

Móc địa chỉ hợp đồng Bit

Quyết định thực hiện các thao tác cụ thể trước/sau được xác định bởi 1 byte ngoài cùng bên trái của địa chỉ hợp đồng Hook. 1 byte bằng 8 bit, tương ứng với 8 hành động bổ sung. Pool sẽ kiểm tra xem bit của hành động đó có phải là 1 hay không để xác định xem có gọi hàm hook tương ứng của hợp đồng Hook hay không. Điều này cũng có nghĩa là địa chỉ của hợp đồng Hook cần phải được thiết kế một cách cụ thể và không thể tự ý lựa chọn làm hợp đồng Hook. Thiết kế này chủ yếu nhằm mục đích giảm tiêu thụ khí đốt và chuyển chi phí sang triển khai theo hợp đồng để đạt được hoạt động hiệu quả hơn. (PS: Trong thực tế, các loại muối CREATE2 khác nhau có thể được sử dụng để tính toán các địa chỉ hợp đồng đáp ứng các điều kiện)

Phí động

Ngoài việc có thể thực hiện thêm các thao tác trước và sau mỗi hành động, Hooks còn hỗ trợ thực hiện tính phí động. Khi tạo Nhóm, bạn có thể chỉ định xem có bật phí động hay không. Nếu phí động được bật, hàm getFee() của hợp đồng Hook sẽ được gọi khi hoán đổi mã thông báo. Hợp đồng Hook có thể xác định số phí phải trả dựa trên trạng thái hiện tại của Pool. Thiết kế này cho phép tính phí linh hoạt theo tình hình thực tế, tăng tính linh hoạt của hệ thống.

Tạo hồ bơi

Mỗi Nhóm cần xác định hợp đồng Hook trong quá trình tạo và sau đó không thể thay đổi hợp đồng này (mặc dù các Nhóm khác nhau có thể chia sẻ cùng một hợp đồng Hook). Điều này chủ yếu là do Hook được coi là một phần của PoolKey và PoolManager sử dụng PoolKey để xác định Pool nào sẽ hoạt động. Ngay cả khi tài sản giống nhau, nếu hợp đồng Hook khác, nó sẽ được coi là một Pool khác. Thiết kế này đảm bảo rằng trạng thái và hoạt động của các Pool khác nhau có thể được quản lý độc lập, đảm bảo tính nhất quán của các Pool. Tuy nhiên, nó cũng làm tăng độ phức tạp của việc định tuyến khi số lượng Pool tăng lên (có lẽ UniswapX được thiết kế để giải quyết vấn đề này).

TL;DR

  • Flash Accounting được sử dụng để theo dõi sự thay đổi số lượng của từng mã thông báo nhằm đảm bảo rằng tất cả các thay đổi đều được loại bỏ sau khi hoàn tất giao dịch. Để tiết kiệm phí gas, Flash Accounting sử dụng phương pháp lưu trữ đặc biệt do EIP1153 cung cấp.
  • Thiết kế Hợp đồng Singleton giúp giảm mức tiêu thụ gas bằng cách tránh cập nhật nhiều biến lưu trữ.
  • Kiến trúc hook cung cấp các hoạt động bổ sung, được chia thành các giai đoạn trước khi thực hiện và sau khi thực hiện. Điều này cho phép linh hoạt hơn trong mỗi hoạt động của Pool nhưng cũng khiến việc định tuyến của Pool trở nên phức tạp hơn.

UniswapV4 nhấn mạnh rõ ràng việc mở rộng toàn bộ hệ sinh thái Uniswap, biến nó thành cơ sở hạ tầng để cho phép xây dựng nhiều dịch vụ hơn trên nền tảng của Uniswap Pools. Điều này giúp nâng cao khả năng cạnh tranh của Uniswap và giảm rủi ro cho các dịch vụ thay thế. Tuy nhiên, liệu nó có đạt được thành công như mong đợi hay không vẫn còn phải xem. Một số điểm nổi bật bao gồm sự kết hợp giữa Flash Accounting và EIP1153, đồng thời chúng tôi tin rằng sẽ có nhiều dịch vụ áp dụng các tính năng này trong tương lai, dẫn đến nhiều tình huống ứng dụng khác nhau. Đây là khái niệm cốt lõi của UniswapV4 và chúng tôi hy vọng nó cung cấp sự hiểu biết sâu sắc hơn về cách UniswapV4 hoạt động. Nếu bài viết có sai sót gì xin vui lòng chỉ ra. Chúng tôi cũng hoan nghênh các cuộc thảo luận và phản hồi.

Cuối cùng, chúng tôi xin cảm ơn Anton Cheng Ping Chen đã xem xét bài viết và đưa ra những phản hồi có giá trị!

Tuyên bố từ chối trách nhiệm:

  1. Bài viết này được in lại từ [Medium]. Mọi bản quyền đều thuộc về tác giả gốc [林瑋宸 Albert Lin]. Nếu có phản đối về việc tái bản này, vui lòng liên hệ với nhóm Gate Learn(gatelearn@gate.io ), và họ sẽ xử lý kịp thời.
  2. Tuyên bố miễn trừ trách nhiệm pháp lý: Các quan điểm và ý kiến trình bày trong bài viết này chỉ là của tác giả và không cấu thành bất kỳ lời khuyên đầu tư nào.
  3. Việc dịch bài viết sang các ngôn ngữ khác được thực hiện bởi nhóm Gate Learn. Trừ khi được đề cập, việc sao chép, phân phối hoặc đạo văn các bài viết đã dịch đều bị cấm.
* Đầu tư có rủi ro, phải thận trọng khi tham gia thị trường. Thông tin không nhằm mục đích và không cấu thành lời khuyên tài chính hay bất kỳ đề xuất nào khác thuộc bất kỳ hình thức nào được cung cấp hoặc xác nhận bởi Gate.io.
* Không được phép sao chép, truyền tải hoặc đạo nhái bài viết này mà không có sự cho phép của Gate.io. Vi phạm là hành vi vi phạm Luật Bản quyền và có thể phải chịu sự xử lý theo pháp luật.

Khám phá các cơ chế cốt lõi của UniswapV4

Nâng cao12/24/2023, 2:50:42 PM
Bài viết này diễn giải ba tính năng cải tiến của UniswapV4 - Flash Accounting, Singleton Contract và Hooks Architecture - từ góc độ mã và triển khai.

Giới thiệu:

Kể từ khi UniswapV4 được công bố, nền tảng hoán đổi này đã trải qua một sự chuyển đổi đáng kể, phát triển từ một nền tảng hoán đổi đơn giản thành nhà cung cấp dịch vụ cơ sở hạ tầng. Đặc biệt, tính năng Hooks của V4 đã nhận được sự quan tâm rộng rãi. Sau khi nghiên cứu chuyên sâu, tôi đã biên soạn một số nội dung nhằm giúp mọi người hiểu rõ hơn về sự chuyển đổi này và cách thực hiện nó.

Trọng tâm đổi mới của UniswapV4 không chỉ là cải tiến công nghệ AMM mà còn là mở rộng hệ sinh thái. Cụ thể, sự đổi mới này bao gồm các tính năng chính sau:

  • Kế toán Flash
  • Hợp đồng đơn lẻ
  • Kiến trúc móc

Trong các phần sau, tôi sẽ giải thích chi tiết tầm quan trọng của các tính năng này và nguyên tắc triển khai chúng.

nguồn: https://twitter.com/jermywkh/status/1670779830621851650

Kế toán Flash

Kế toán kép

UniswapV4 áp dụng phương pháp lưu giữ hồ sơ tương tự như Sổ sách kế toán kép để theo dõi sự thay đổi số dư của các token tương ứng với từng hoạt động. Phương pháp ghi sổ kép này yêu cầu ghi lại đồng thời từng giao dịch trong nhiều tài khoản và đảm bảo số dư tài sản giữa các tài khoản này vẫn được cân bằng. Ví dụ: giả sử người dùng trao đổi 100 TokenA lấy 50 TokenB từ nhóm. Việc ghi vào sổ cái sẽ như sau:

  • NGƯỜI DÙNG: TokenA giảm 100 đơn vị (-100), trong khi TokenB tăng 50 đơn vị (+50).
  • POOL: TokenA tăng 100 đơn vị (+100), trong khi TokenB giảm 50 đơn vị (-50).

Token Delta và các hoạt động liên quan

Trong UniswapV4, phương pháp lưu giữ hồ sơ này chủ yếu được sử dụng cho các hoạt động chính và một biến lưu trữ có tên lockState.currencyDelta[currency] được sử dụng trong mã để ghi lại số lượng thay đổi số dư mã thông báo. Nếu giá trị của delta này là dương thì nó biểu thị mức tăng dự kiến về số lượng mã thông báo trong nhóm, trong khi giá trị âm biểu thị mức giảm dự kiến về số lượng mã thông báo. Ngoài ra, nếu giá trị dương, nó cho biết lượng token thiếu hụt trong nhóm (số tiền dự kiến sẽ nhận được), trong khi giá trị âm cho biết lượng token dư thừa trong nhóm (số tiền dự kiến để người dùng rút). Danh sách sau đây cho thấy tác động của các hoạt động khác nhau trên Token Delta:

  • sửa đổiPosition: Thể hiện hoạt động Thêm/Xóa tính thanh khoản. Để Thêm tính thanh khoản, TokenDelta được cập nhật bằng cách sử dụng phép cộng (thể hiện số lượng TokenA dự kiến sẽ được thêm vào nhóm). Để loại bỏ tính thanh khoản, TokenDelta được cập nhật bằng phép trừ (thể hiện số lượng TokenB dự kiến sẽ được rút khỏi nhóm).
  • trao đổi: Thể hiện hoạt động Hoán đổi. Lấy ví dụ về việc hoán đổi TokenA lấy TokenB, TokenADelta được cập nhật bằng phép cộng, trong khi TokenBDelta được cập nhật bằng phép trừ.
  • giải quyết: Đi kèm với việc chuyển mã thông báo vào nhóm. Nhóm tính toán mức tăng số lượng mã thông báo trước và sau và cập nhật TokenDelta bằng phép trừ. Nếu nhóm nhận được số lượng mã thông báo dự kiến, phép trừ sẽ tạo ra TokenDelta.
  • lấy: Đi kèm với việc rút mã thông báo khỏi nhóm. TokenDelta được cập nhật bằng cách sử dụng tính năng bổ sung, cho biết rằng các mã thông báo đã bị xóa khỏi nhóm.
  • mint: Hành vi cập nhật TokenDelta tương tự như "lấy", nhưng thay vì thực sự rút mã thông báo khỏi nhóm, mã thông báo ERC1155 được phát hành làm bằng chứng rút tiền, trong khi mã thông báo vẫn ở trong nhóm. Sau đó, người dùng có thể truy xuất mã thông báo từ nhóm bằng cách ghi mã thông báo ERC1155. Mục đích của phương pháp này có thể gồm hai phần: 1. Tiết kiệm chi phí gas cho việc chuyển mã thông báo ERC20 (gọi hợp đồng + ghi ít bộ nhớ hơn) và sử dụng tính năng ghi mã thông báo ERC1155 trong tương lai để cập nhật TokenDelta cho các giao dịch. 2. Duy trì tính thanh khoản trong nhóm để duy trì nhóm thanh khoản sâu nhằm mang lại trải nghiệm hoán đổi tốt hơn cho người dùng.
  • donate: Hoạt động này tuyên bố quyên góp mã thông báo cho nhóm, nhưng trên thực tế, mã thông báo vẫn cần được chuyển vào nhóm bằng cách sử dụng “giải quyết”. Do đó, TokenDelta được cập nhật bằng phép cộng trong trường hợp này.

Trong số các hoạt động này, chỉ có “thanh toán” và “nhận” liên quan đến việc chuyển mã thông báo thực tế, trong khi các hoạt động khác hoàn toàn chịu trách nhiệm cập nhật giá trị TokenDelta.

Ví dụ về đồng bằng mã thông báo

Ở đây chúng tôi sử dụng một ví dụ đơn giản để minh họa cách cập nhật TokenDelta. Giả sử hôm nay chúng ta đổi 100 TokenA lấy 50 TokenB:

  1. Trước khi giao dịch bắt đầu, cả TokenADelta và TokenBDelta đều bằng 0.
  2. swap: Tính toán số lượng TokenA mà Pool cần nhận và số lượng TokenB mà người dùng sẽ nhận được. Tại thời điểm này, TokenADelta = 100, TokenBDelta = -50.
  3. giải quyết: Gửi 100 TokenA vào Pool và cập nhật TokenADelta = 100 - 100 = 0.
  4. lấy: Chuyển 50 TokenB từ Pool vào tài khoản của người dùng và cập nhật TokenBDelta = -50 + 50 = 0.
  5. Sau khi giao dịch hoàn tất, cả TokenADelta và TokenBDelta đều bằng 0.

Khi toàn bộ hoạt động trao đổi hoàn tất, cả TokenADelta và TokenBDelta đều được đặt lại về 0. Điều này có nghĩa là hoạt động đã được cân bằng hoàn toàn, do đó đảm bảo tính nhất quán của số dư tài khoản.

EIP-1153: Mã hoạt động lưu trữ tạm thời

Trước đây, người ta đã đề cập rằng UniswapV4 sử dụng Biến lưu trữ để ghi lại TokenDelta. Tuy nhiên, trong hợp đồng, việc đọc và ghi vào Biến lưu trữ khá tốn kém. Điều này đưa chúng ta đến một EIP khác được Uniswap giới thiệu: EIP1153 - Transient Storage Opcodes.

UniswapV4 có kế hoạch sử dụng opcode TSTORE và TLOAD do EIP1153 cung cấp để cập nhật TokenDelta. Các Biến lưu trữ áp dụng Mã lưu trữ tạm thời sẽ bị loại bỏ sau khi kết thúc giao dịch (tương tự như Biến bộ nhớ), do đó giảm phí gas.

EIP1153 đã được xác nhận sẽ có trong bản nâng cấp Cancun sắp tới và UniswapV4 cũng đã tuyên bố rằng nó sẽ đi vào hoạt động sau bản nâng cấp Cancun, như đã báo cáo tại đây.

nguồn: https://etherworld.co/2022/12/13/transient-storage-for-beginners/

Kế toán Flash - Khóa

UniswapV4 giới thiệu cơ chế khóa, có nghĩa là trước khi thực hiện bất kỳ thao tác Pool nào, trước tiên bạn phải gọi PoolManager.lock() để lấy khóa. Trong quá trình thực thi lock(), nó sẽ kiểm tra xem giá trị TokenDelta có bằng 0 hay không, nếu không nó sẽ hoàn nguyên. Khi PoolManager.lock() được lấy thành công, nó sẽ gọi hàm lockAcquired() của msg.sender. Bên trong hàm lockAcquired(), các thao tác liên quan đến Nhóm, chẳng hạn như trao đổi và sửa đổi Vị trí, được thực hiện.

Quá trình này được minh họa dưới đây. Khi người dùng cần thực hiện thao tác Hoán đổi mã thông báo, họ phải gọi Hợp đồng thông minh có chức năng lockAcquired() (gọi tắt là Hợp đồng gọi lại). Hợp đồng gọi lại lần đầu tiên gọi PoolManager.lock(), và sau đó PoolManager gọi hàm lockAcquired() của Hợp đồng gọi lại. Bên trong hàm lockAcquired(), logic liên quan đến các hoạt động của Pool, chẳng hạn như trao đổi, giải quyết và lấy, được xác định. Cuối cùng, khi lock() sắp kết thúc, PoolManager sẽ kiểm tra xem TokenDelta được liên kết với thao tác này có được đặt lại về 0 hay không, đảm bảo số dư tài sản trong Pool vẫn còn nguyên.

Hợp đồng đơn lẻ

Hợp đồng Singleton có nghĩa là UniswapV4 đã từ bỏ mô hình Factory-Pool trước đó. Mỗi Nhóm không còn là một Hợp đồng Thông minh độc lập nữa mà tất cả các Nhóm đều có chung một hợp đồng đơn lẻ. Thiết kế này, kết hợp với cơ chế Flash Accounting, chỉ yêu cầu cập nhật các Biến lưu trữ cần thiết, giúp giảm hơn nữa độ phức tạp và chi phí vận hành.

Trong ví dụ bên dưới, lấy UniswapV3 làm ví dụ, việc trao đổi ETH lấy DAI sẽ yêu cầu ít nhất bốn lần chuyển Token (Hoạt động ghi lưu trữ). Điều này bao gồm nhiều thay đổi được ghi lại đối với các Token USDC, USDT và DAI. Tuy nhiên, với những cải tiến trong UniswapV4, kết hợp với cơ chế Flash Accounting, chỉ cần một lần chuyển Token (chuyển DAI từ Pool đến người dùng), giúp giảm đáng kể số lượng thao tác và chi phí.

nguồn: https://twitter.com/Uniswap/status/1671208668304486404

Kiến trúc móc

Trong bản cập nhật mới nhất của UniswapV4, tính năng đáng chú ý nhất là Hooks Architecture. Bản cập nhật này mang lại sự linh hoạt cao về tính khả dụng của Pool. Móc là các hành động bổ sung được kích hoạt thông qua Hợp đồng Móc khi thực hiện các hoạt động cụ thể trên Nhóm. Những hành động này được phân loại thành khởi tạo (tạo nhóm), sửa đổiPosition (thêm/xóa tính thanh khoản), hoán đổi và quyên góp. Mỗi danh mục có các hành động trước khi thực hiện và sau khi thực hiện.

  • beforeInitialize / afterInitialize
  • beforeModifyPosition / afterModifyPosition
  • trướcSwap / afterSwap
  • beforeDonate / afterDonate

Thiết kế này cho phép người dùng thực thi logic tùy chỉnh trước và sau các hoạt động cụ thể, giúp nó linh hoạt hơn và mở rộng chức năng của UniswapV4.

nguồn: https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf

Ví dụ về Hook - Hook giới hạn lệnh

Tiếp theo, chúng tôi sẽ sử dụng ví dụ về Lệnh giới hạn để giải thích quy trình hoạt động thực tế của Hooks trong UniswapV4. Trước khi bắt đầu, hãy giải thích ngắn gọn nguyên tắc triển khai Lệnh giới hạn trong UniswapV4.

Cơ chế đặt hàng giới hạn UniswapV4

Việc triển khai lệnh giới hạn UniswapV4 hoạt động bằng cách thêm thanh khoản vào một phạm vi giá cụ thể và sau đó thực hiện thao tác loại bỏ thanh khoản nếu thanh khoản trong phạm vi đó được hoán đổi.

Ví dụ: giả sử chúng tôi thêm tính thanh khoản trong phạm vi giá 1900-2000 cho ETH và sau đó giá ETH tăng từ 1800 lên 2100. Tại thời điểm này, tất cả thanh khoản ETH mà chúng tôi đã thêm trước đây trong phạm vi giá 1900-2000 đã được hoán đổi lấy USDC (giả sử trong nhóm ETH-USDC). Bằng cách loại bỏ tính thanh khoản tại thời điểm này, chúng tôi có thể đạt được hiệu quả tương tự như thực hiện lệnh thị trường ETH ở mức giá hiện tại là 1900-2000.

Hợp đồng móc lệnh giới hạn

Ví dụ này được lấy từ GitHub của UniswapV4. Trong ví dụ này, hợp đồng Limit Order Hook cung cấp hai hook, đó là afterInitialize và afterSwap. hook afterInitialize được sử dụng để ghi lại phạm vi giá (đánh dấu) khi tạo nhóm, nhằm xác định lệnh giới hạn nào đã được khớp sau khi ai đó hoán đổi.

Lập tức đăng ký

Khi người dùng cần đặt hàng, hợp đồng Hook sẽ thực hiện thao tác bổ sung thanh khoản dựa trên phạm vi giá và số lượng do người dùng chỉ định. Trong hợp đồng Hook cho các lệnh giới hạn, bạn có thể thấy hàm place() . Logic chính là gọi hàm lockAcquiredPlace() sau khi có được khóa để thực hiện thao tác bổ sung thanh khoản, tương đương với việc đặt lệnh giới hạn.

nguồn: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L246

sauSwap Hook

Sau khi người dùng hoàn thành Swap Token trong Pool này, Pool sẽ gọi hàm afterSwap() của hợp đồng Hook. Logic chính của afterSwap là loại bỏ tính thanh khoản của các lệnh đã đặt trước đó đã được khớp giữa phạm vi giá trước đó và phạm vi giá hiện tại. Hành vi này tương đương với đơn hàng đang được điền.

nguồn: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L192

Giới hạn dòng lệnh

Dưới đây là sơ đồ minh họa quá trình thực hiện lệnh giới hạn:

  1. Người đặt hàng sẽ gửi đơn đặt hàng đến hợp đồng Hook.
  2. Hợp đồng Hook thực hiện các hoạt động bổ sung thanh khoản dựa trên thông tin đơn hàng.
  3. Người dùng thông thường thực hiện các hoạt động Hoán đổi Token trong Pool.
  4. Sau khi hoàn thành thao tác Swap Token, Pool gọi hàm afterSwap() của hợp đồng Hook.
  5. Hợp đồng Hook thực hiện các hoạt động loại bỏ thanh khoản cho các lệnh giới hạn đã được thực hiện dựa trên sự thay đổi phạm vi giá của các token được hoán đổi.

Trên đây là toàn bộ quá trình thực hiện Limit-Order bằng cơ chế Hook.

Móc: Các tính năng khác

Hooks có một số điểm thú vị mà tôi thấy đáng chia sẻ.

Móc địa chỉ hợp đồng Bit

Quyết định thực hiện các thao tác cụ thể trước/sau được xác định bởi 1 byte ngoài cùng bên trái của địa chỉ hợp đồng Hook. 1 byte bằng 8 bit, tương ứng với 8 hành động bổ sung. Pool sẽ kiểm tra xem bit của hành động đó có phải là 1 hay không để xác định xem có gọi hàm hook tương ứng của hợp đồng Hook hay không. Điều này cũng có nghĩa là địa chỉ của hợp đồng Hook cần phải được thiết kế một cách cụ thể và không thể tự ý lựa chọn làm hợp đồng Hook. Thiết kế này chủ yếu nhằm mục đích giảm tiêu thụ khí đốt và chuyển chi phí sang triển khai theo hợp đồng để đạt được hoạt động hiệu quả hơn. (PS: Trong thực tế, các loại muối CREATE2 khác nhau có thể được sử dụng để tính toán các địa chỉ hợp đồng đáp ứng các điều kiện)

Phí động

Ngoài việc có thể thực hiện thêm các thao tác trước và sau mỗi hành động, Hooks còn hỗ trợ thực hiện tính phí động. Khi tạo Nhóm, bạn có thể chỉ định xem có bật phí động hay không. Nếu phí động được bật, hàm getFee() của hợp đồng Hook sẽ được gọi khi hoán đổi mã thông báo. Hợp đồng Hook có thể xác định số phí phải trả dựa trên trạng thái hiện tại của Pool. Thiết kế này cho phép tính phí linh hoạt theo tình hình thực tế, tăng tính linh hoạt của hệ thống.

Tạo hồ bơi

Mỗi Nhóm cần xác định hợp đồng Hook trong quá trình tạo và sau đó không thể thay đổi hợp đồng này (mặc dù các Nhóm khác nhau có thể chia sẻ cùng một hợp đồng Hook). Điều này chủ yếu là do Hook được coi là một phần của PoolKey và PoolManager sử dụng PoolKey để xác định Pool nào sẽ hoạt động. Ngay cả khi tài sản giống nhau, nếu hợp đồng Hook khác, nó sẽ được coi là một Pool khác. Thiết kế này đảm bảo rằng trạng thái và hoạt động của các Pool khác nhau có thể được quản lý độc lập, đảm bảo tính nhất quán của các Pool. Tuy nhiên, nó cũng làm tăng độ phức tạp của việc định tuyến khi số lượng Pool tăng lên (có lẽ UniswapX được thiết kế để giải quyết vấn đề này).

TL;DR

  • Flash Accounting được sử dụng để theo dõi sự thay đổi số lượng của từng mã thông báo nhằm đảm bảo rằng tất cả các thay đổi đều được loại bỏ sau khi hoàn tất giao dịch. Để tiết kiệm phí gas, Flash Accounting sử dụng phương pháp lưu trữ đặc biệt do EIP1153 cung cấp.
  • Thiết kế Hợp đồng Singleton giúp giảm mức tiêu thụ gas bằng cách tránh cập nhật nhiều biến lưu trữ.
  • Kiến trúc hook cung cấp các hoạt động bổ sung, được chia thành các giai đoạn trước khi thực hiện và sau khi thực hiện. Điều này cho phép linh hoạt hơn trong mỗi hoạt động của Pool nhưng cũng khiến việc định tuyến của Pool trở nên phức tạp hơn.

UniswapV4 nhấn mạnh rõ ràng việc mở rộng toàn bộ hệ sinh thái Uniswap, biến nó thành cơ sở hạ tầng để cho phép xây dựng nhiều dịch vụ hơn trên nền tảng của Uniswap Pools. Điều này giúp nâng cao khả năng cạnh tranh của Uniswap và giảm rủi ro cho các dịch vụ thay thế. Tuy nhiên, liệu nó có đạt được thành công như mong đợi hay không vẫn còn phải xem. Một số điểm nổi bật bao gồm sự kết hợp giữa Flash Accounting và EIP1153, đồng thời chúng tôi tin rằng sẽ có nhiều dịch vụ áp dụng các tính năng này trong tương lai, dẫn đến nhiều tình huống ứng dụng khác nhau. Đây là khái niệm cốt lõi của UniswapV4 và chúng tôi hy vọng nó cung cấp sự hiểu biết sâu sắc hơn về cách UniswapV4 hoạt động. Nếu bài viết có sai sót gì xin vui lòng chỉ ra. Chúng tôi cũng hoan nghênh các cuộc thảo luận và phản hồi.

Cuối cùng, chúng tôi xin cảm ơn Anton Cheng Ping Chen đã xem xét bài viết và đưa ra những phản hồi có giá trị!

Tuyên bố từ chối trách nhiệm:

  1. Bài viết này được in lại từ [Medium]. Mọi bản quyền đều thuộc về tác giả gốc [林瑋宸 Albert Lin]. Nếu có phản đối về việc tái bản này, vui lòng liên hệ với nhóm Gate Learn(gatelearn@gate.io ), và họ sẽ xử lý kịp thời.
  2. Tuyên bố miễn trừ trách nhiệm pháp lý: Các quan điểm và ý kiến trình bày trong bài viết này chỉ là của tác giả và không cấu thành bất kỳ lời khuyên đầu tư nào.
  3. Việc dịch bài viết sang các ngôn ngữ khác được thực hiện bởi nhóm Gate Learn. Trừ khi được đề cập, việc sao chép, phân phối hoặc đạo văn các bài viết đã dịch đều bị cấm.
* Đầu tư có rủi ro, phải thận trọng khi tham gia thị trường. Thông tin không nhằm mục đích và không cấu thành lời khuyên tài chính hay bất kỳ đề xuất nào khác thuộc bất kỳ hình thức nào được cung cấp hoặc xác nhận bởi Gate.io.
* Không được phép sao chép, truyền tải hoặc đạo nhái bài viết này mà không có sự cho phép của Gate.io. Vi phạm là hành vi vi phạm Luật Bản quyền và có thể phải chịu sự xử lý theo pháp luật.
Bắt đầu giao dịch
Đăng ký và giao dịch để nhận phần thưởng USDTEST trị giá
$100
$5500