- vừa được xem lúc

Khốn vãi lò. Phần 4: Tick Bit Map

0 0 1

Người đăng: thiên thần gãy cánh

Theo Viblo Asia

4. Tick Bit Map

Nếu như các bạn để ý và nhớ lại kiến thức ở bài 1, thì ở bước swap, để xác định E là điểm nào không phải chuyện dễ, vì UniswapV3 muốn tạo ra sự linh hoạt cho user nên các price-range không bắt buộc có độ rộng bằng nhau, do đó cần phải có cách để xác định đâu là giới hạn của một price-range nhanh và hiệu quả nhất.

Xét ví dụ như sau:

Đầu tiên là Alice add 60L vào D-E, sau đó Bob add tiếp 60L vào F-G. Nếu Carol add tiếp 60L vào E-F, vậy 3 price-range D-E, E-F, F-G đều có L = 60 thì chúng có hợp nhất thành price-range lớn D-G có L = 60 hay không?

Câu trả lời là không!

Bởi vì, trong trường hợp nếu có 1 lệnh swap nào đó làm dịch chuyển price từ D-E sang E-F và kết thúc, thì lệnh swap đó không được quyền sử dụng liquidity mà Bob đã add vào, cũng như Bob không được hưởng fee từ lệnh swap đó.

Như vậy cần một cách đánh dấu đâu là một điểm dừng của một price-range chứ không thể dùng liquidityNet != 0 để đánh dấu, vì như hình ở trên ta thấy, mặc dù liquidityNet tại E,F sau khi Carol add liquidty là 0, nhưng chúng vẫn là điểm dừng của các price-range, cụ thể là:

  • D,E là giới hạn của price-range D-E
  • E,F là giới hạn của price-range E-F
  • F,G là giới hạn của price-range F-G

4.1 LiquidtyGross và tickInitialized

Ví dụ, Alice thêm 60L vào D-E và Bob thêm 60L vào F-G, lúc đó, liqudityGross và tickInitialized như sau:

Sau đó, Carols thêm 60L và0 E-F:

Như vậy, khi 1 tick có liquidityGross > 0, đồng nghĩa tick đó đang là điểm dừng của một price-range nào đó hoặc có thể nó là điểm dừng của cả 2 price-range lower và upper.

Một tick có liqudityGross > 0 thì tickInitialized của nó phải là true, nếu liquidityGross = 0, thì tickInitalized của nó phải là false => LiquidityGross của 1 tick phải luôn >= 0.

Đối chiếu vào trong code.

image.png

Hàm update() của file Tick.sol. LiquidityGross là kiểu uint không âm và liquidityGrossAfter đơn giản chỉ là =liquidityGrossBefore.addDelta(liquidityDelta).

Ở khối if(liquidityGrossBefore==0) thì info.initialized = true, tương đương là nếu liquidityGrossAfter > 0 thì info.initialized = true. Bởi vì liquidityDelta được truyền vào hàm này luôn khác 0 + liquidityGross phải luôn >= 0.

image.png

Thật vậy, hàm ticks.update() chỉ được gọi ở hàm _updatePosition() của UniswapV3Pool.sol khi liquidityDelta != 0

4.2 Tick bit map

Ở trên chúng ta đã hiểu chức năng của liquidityGross, nó đơn giản chỉ là đánh dấu xem tại tick đó có phải là một ranh giới của price-range nào không.

Tuy nhiên nếu chúng ta sử dụng vòng for để chạy hết tất cả các tick có tickIndex % tickSpacing = 0 để xem tại đó liqudityGross > 0 hay initialized = true hay không để xác định ranh giới sẽ rất tốn gas. Do đó, chúng ta cần một cách tìm nhanh hơn.

Bit map là một kỹ thuật phổ biến để index data bằng cách ngắn gọn

Ví dụ:

Với những tick có liquidityGross > 0 (initialized = true) thi sẽ tương ứng với 1, ngược lại sẽ là 0.

image.png

Ở dòng 130, nếu có sự thay đổi của liquidityGross, thì chúng ta phải lật bit tại tick đó lên:

  • Nếu liquidityGross thay đổi từ 0 thành một số lớn hơn 0, nên được set là 1 tại tick đó
  • Nếu liquidityGross thay đổi từ một số lớn hơn 0 thành 0, nên được set là 0 tại tick đó

Và chúng ta chỉ cần lập bit map cho các tick có tickIndex % tickSpacing = 0. Map sẽ được chia thành các words, mỗi words có 256 bits.

Ví dụ, pool ở trên có tick-spacing là 20 thì bit map cụ thể của nó sẽ như sau:

  • Word 1: chứa bit map của các tick: 5120, 5140, 5160, 5180,...10220.
  • Word 2: chứa bit map của các tick: 10240, 10260, 10280, 10300,...15340.
  • Word 3: chứa bit map của các tick: 15360, 15380, 15400,..., 20460.
  • Word 4: chưa bit map của các tick: 20480,..25580.
  • Word 5: chứa bit map của các tick: 25600,...

Chúng ta cùng nhìn lại vòng while trong hàm swap trong file UniswapV3Pool.sol image.png

hàm này sử dụng hàm nextInitializedTickWithinOneOneWord() để tìm:

  • tick được initialized trong word đó theo chiều swap
  • hoặc tick đầu tiên của word tiếp theo chiều swap

Hàm này trong file TickBitMap.sol: image.png

Về cách hoạt động của hàm này có thể xem thêm tại https://uniswapv3book.com/milestone_2/tick-bitmap-index.html#bitmap

Như vậy, với pool ở trên, nếu có 1 lệnh swap nào đó swap token1 lấy token0, làm giá rơi vào 1 tick nào đó thuộc word 4, thì vòng while sẽ được chạy qua 5 lần như sau:

Mặc dù thực tế chỉ có các price-range là D-E, E-F, F-G, nhưng khi swap sẽ xuẩt hiện thêm các price-range tạm thời của là E-E1, E1-F, F-F1.

Tuy nhiên chúng ta chỉ thực hiện cross-tick ( L = L.addDelta(liquiditiyNet) ) khi thực sự cross qua tick là ranh giới của một price-range thực tế (các tick có bit trong bit map là 1)

image.png

4.4 Swap qua các gaps

Giá sử E-F không có thanh khoảng, 1 lệnh swap có thể xuyên qua E-F và đi thẳng vào F-G hay không?

Câu trả lời là có!

Nhớ lại bài 1, khi price cross qua E, đi vào E-F thì lúc này L sau khi addDelta(liqidityNet_E) chắc chắn phải bằng 0. Chúng ta sẽ có 2 loop ở đây là loop2, loop3 với L = 0 => do đó amountRemainning đi vào rồi đi ra hàm computeSwapStep() sẽ được giữ nguyên và không có lượng output token nào được ghi nhận cho user ở 2 loop này. image.png

Có thể dễ dàng tìm thấy test case của việc này ở file UniswapV3.spec.ts image.png

Bình luận

Bài viết tương tự

- vừa được xem lúc

[Blockchain] Road to Bitcoin

. Chắc mọi người hẳn đã không còn xa lạ gì với anh chàng tỷ phú đã ném vỡ cửa kính ô tô nhà mình cùng với siêu năng lực điều khiển vật giá chỉ bằng lời nói, người đã đẩy định giá Bitcoin trên thị trường vượt ngưỡng 50K dolar/coin với những bài twitter để đời . .

0 0 64

- vừa được xem lúc

Khi Ethereum có chi phí giao dịch quá đắt đỏ - Tương lai cho layer2 ?

Với sự phát triển như vũ bão của Blockchain, ETH dường như đang quá tải và hệ quả là chi phí Gas đã lên đến 1000Gwei, phí để tạo những transaction phức tạp đã xấp xỉ 500$ . Và một giải pháp cứu cánh cho các sản phẩm Defi trên ETH chính là Layer2, và trong nhiệm vụ lần này Matic đang thể hiện khả năn

0 0 90

- vừa được xem lúc

Blockchain với Java - Tại sao không?

Cuộc cách mạng công nghiệp 4.0 ra đời kéo theo nhiều sự thay đổi và xu hướng mới được hình thành. Riêng đối với lĩnh vực CNTT cũng không nằm ngoài vùng ảnh hưởng mạnh mẽ. Chính làn sóng 4.

0 0 95

- vừa được xem lúc

Phân loại và tầm quan trọng của các node trong mạng blockchain

Trước khi đi vào phân loại và nêu rõ được tầm quan trọng của các node trọng mạng blockchain thì mình xin được trích dẫn khái niệm về blockchain từ Wikipedia như sau:. .

0 1 66

- vừa được xem lúc

Code Smart Contract bằng Assembly ?

Introduction. Hồi còn học trong ghế nhà trường bộ môn lập trình tốn nhiều não nhất của mình là code assembly. Nôm na thì bất cứ ngôn ngữ bậc cao nào như C , Go, Java,... được sinh ra để người dễ hiểu và dễ code , tuy nhiên chúng đều sẽ được compiled down xuống assembly một ngôn ngữ bậc thấp để máy h

0 0 60

- vừa được xem lúc

Dextool - Công cụ phân tích Decentralized Exchange tuyệt vời

. Trend Defi mặc dù đã bớt nhiệt nhưng những sản phẩm nổi bật của làn sóng này mang lại thì vẫn rất được người dùng ưa chuộng. Đặc biệt là các nền tảng Decentralized Exchange, tiêu biểu là Uniswap, SushiSwap, 1inch Exchange, FalconSwap,... Nhưng khi đã sử dụng các nền tảng DEx này mà không biết đến

0 0 108