Quét để tải ứng dụng Gate
qrCode
Thêm tùy chọn tải xuống
Không cần nhắc lại hôm nay

Ma thuật đen của thao túng giá: Phân tích lỗ hổng tính toán biến không đổi của Balancer V2

Biên dịch: Ngôn ngữ thường về Blockchain

Vào ngày 3 tháng 11 năm 2025, các bể ổn định kết hợp (Composable Stable Pools) của Balancer V2 và một số dự án phân nhánh trên nhiều chuỗi đã bị tấn công phối hợp, dẫn đến tổng thiệt hại trên 1,25 triệu đô la. BlockSec đã phát đi cảnh báo ngay lập tức và sau đó công bố phân tích sơ bộ.

Đây là một cuộc tấn công có độ phức tạp cao. Cuộc điều tra của chúng tôi cho thấy, nguyên nhân gốc rễ là do mất chính xác trong việc tính toán bất biến (invariant) dẫn đến thao túng giá cả, từ đó làm sai lệch việc tính toán giá của BPT (Token của Pool Balancer). Việc thao túng bất biến này cho phép kẻ tấn công thu lợi từ một lần hoán đổi hàng loạt (batch swap) từ một hồ ổn định cụ thể. Mặc dù một số nhà nghiên cứu đã cung cấp phân tích sâu sắc, nhưng một số cách diễn giải lại gây hiểu lầm, nguyên nhân gốc rễ và quá trình tấn công vẫn chưa được làm rõ hoàn toàn. Blog này nhằm mục đích cung cấp một phân tích kỹ thuật toàn diện và chính xác về sự kiện này.

điểm chính (TL;DR)

  • Nguyên nhân gốc rễ: Sự không nhất quán trong làm tròn và mất độ chính xác
  • Các thao tác phóng to (upscaling) sử dụng làm tròn một chiều (làm tròn xuống), trong khi các thao tác thu nhỏ (downscaling) sử dụng làm tròn hai chiều (làm tròn lên và làm tròn xuống).
  • Sự không nhất quán này gây ra mất độ chính xác, khi được khai thác thông qua các đường trao đổi được thiết kế tỉ mỉ, vi phạm nguyên tắc tiêu chuẩn “việc làm tròn luôn phải có lợi cho giao thức”.
  • Thực hiện tấn công
  • Kẻ tấn công đã thiết kế cẩn thận các tham số, bao gồm số lần lặp và giá trị đầu vào, để tối đa hóa ảnh hưởng của việc mất độ chính xác.
  • Kẻ tấn công sử dụng phương pháp hai giai đoạn để tránh bị phát hiện: trước tiên thực hiện cuộc tấn công cốt lõi trong một giao dịch đơn lẻ mà không ngay lập tức thu lợi, sau đó trong một giao dịch khác để rút tài sản và đạt được lợi nhuận.
  • Tác động và khuếch đại hoạt động
  • Do một số hạn chế, giao thức không thể tạm dừng. Tình huống không thể ngừng hoạt động này đã làm trầm trọng thêm tác động của cuộc tấn công và dẫn đến nhiều cuộc tấn công tiếp theo hoặc bắt chước.

Trong phần tiếp theo, chúng tôi sẽ cung cấp thông tin cơ bản quan trọng về Balancer V2, sau đó phân tích sâu về các vấn đề đã được phát hiện và các cuộc tấn công liên quan.

0x1 Bối cảnh

1. Bể ổn định dạng tổ hợp của Balancer V2

Các thành phần bị ảnh hưởng trong cuộc tấn công lần này là các bể ổn định dạng tổ hợp của giao thức Balancer V2. Những bể này được thiết kế đặc biệt để duy trì gần như tỷ lệ 1:1 (hoặc giao dịch với tỷ giá đã biết) cho các tài sản, và cho phép thực hiện các giao dịch lớn với ảnh hưởng giá tối thiểu, từ đó nâng cao đáng kể hiệu quả vốn giữa các tài sản cùng loại hoặc có liên quan. Mỗi bể đều có token Balancer riêng của nó (BPT), đại diện cho phần của nhà cung cấp thanh khoản trong bể, cùng với tài sản cơ bản tương ứng.

Bể này sử dụng Stable Math (mô hình StableSwap dựa trên Curve), trong đó bất biến D đại diện cho tổng giá trị ảo của bể.

Giá BPT có thể được ước tính là:

Hình ảnhTừ công thức trên có thể thấy, nếu D có thể được giảm trên sổ sách (ngay cả khi không có bất kỳ tổn thất thực tế nào về tài chính), thì giá BPT sẽ trở nên rẻ hơn.

2. batchSwap() và onSwap()

Balancer V2 cung cấp hàm batchSwap(), hàm này hỗ trợ thực hiện các giao dịch đa bước (multi-hop swaps) trong Vault. Dựa trên các tham số được truyền vào hàm này, có hai loại giao dịch:

  • GIVEN_IN(“Đầu vào được chỉ định”):Người gọi chỉ định chính xác số lượng Token đầu vào, bể tính toán số lượng đầu ra tương ứng.
  • GIVEN_OUT(“đầu ra đã cho”):Người gọi xác định số lượng đầu ra mong muốn, hồ bơi tính toán số lượng đầu vào cần thiết.

Thông thường, batchSwap() bao gồm nhiều lần trao đổi giữa các Token được thực hiện qua hàm onSwap(). Dưới đây là cái nhìn tổng quan về lộ trình thực hiện khi một SwapRequest được phân bổ là loại trao đổi GIVEN_OUT (xin lưu ý rằng ComposableStablePool kế thừa từ BaseGeneralPool):

! [hình ảnh] ()

Dưới đây hiển thị cách tính amount_in trong loại giao dịch GIVEN_OUT, điều này liên quan đến bất biến D.

// inGivenOut token x cho y - phương trình đa thức để giải // ax = số tiền cần tính toán
// bx = số dư token trong // x = bx + ax (finalBalanceIn)
// D = bất biến // A = hệ số khuếch đại // n = số lượng token // S = tổng số dư cuối cùng nhưng x // P = sản phẩm của số dư cuối cùng nhưng x

               D                     D^(n+1)  

x^2 + ( S - ---------- - D) * x - ------------- = 0
(A * n^n) A * n^2n * P

3. Thu phóng và làm tròn

Để chuẩn hóa tính toán giữa các số dư Token khác nhau, Balancer thực hiện hai thao tác sau:

  • Phóng đại (Upscaling):Trước khi thực hiện tính toán, phóng đại số dư và số tiền lên độ chính xác nội bộ thống nhất.

! [hình ảnh] ()

  • Giảm quy mô (Downscaling):Chuyển đổi kết quả về độ chính xác gốc của nó và áp dụng làm tròn định hướng (ví dụ, số tiền đầu vào thường được làm tròn lên để đảm bảo rằng hồ không bị thu phí thiếu, trong khi số tiền đầu ra thường được làm tròn xuống).

! [hình ảnh] ()

Rõ ràng, phóng to và thu nhỏ về lý thuyết là các phép toán đối xứng - lần lượt là phép nhân và phép chia. Tuy nhiên, có sự không nhất quán trong việc thực hiện hai phép toán này. Cụ thể, phép thu nhỏ có hai biến thể hoặc hướng: divUp và divDown. Trong khi đó, phép phóng to chỉ có một hướng, đó là mulDown.

Nguyên nhân của sự không nhất quán này vẫn chưa rõ ràng. Theo chú thích trong hàm _upscale(), các nhà phát triển cho rằng ảnh hưởng của việc làm tròn một chiều là rất nhỏ.

// Phóng đại (Upscale) việc làm tròn không nhất thiết lúc nào cũng theo cùng một hướng: ví dụ, trong một lần trao đổi,

// Số dư Token đầu vào nên được làm tròn lên, trong khi số dư Token đầu ra nên được làm tròn xuống. Đây là nơi duy nhất mà chúng tôi thực hiện việc làm tròn cùng hướng cho tất cả các khoản tiền,

// Bởi vì ảnh hưởng của việc làm tròn này dự kiến sẽ là tối thiểu.

// (và trừ khi _scalingFactor() bị ghi đè, thì không có lỗi làm tròn).

Phân tích lỗ hổng 0x2

Vấn đề cơ bản xuất phát từ việc thực hiện thao tác làm lớn (upscaling) trong hàm BaseGeneralPool._swapGivenOut(), nơi có thao tác làm tròn xuống. Cụ thể, _swapGivenOut() đã làm tròn sai swapRequest.amount xuống thông qua hàm _upscale(). Giá trị đã được làm tròn này sau đó được sử dụng làm amountOut, khi tính toán amountIn qua _onSwapGivenOut(). Hành vi này trái ngược với thực tiễn tiêu chuẩn “làm tròn nên được áp dụng theo cách có lợi cho giao thức.”

! [hình ảnh] ()

Do đó, đối với một bể được chỉ định (wstETH/rETH/cbETH), lượng amountIn được tính toán đã đánh giá thấp đầu vào thực tế cần thiết. Điều này cho phép người dùng trao đổi một lượng nhỏ của một tài sản cơ sở (ví dụ wstETH) lấy một tài sản khác (ví dụ cbETH), dẫn đến giảm biến không (D) do thanh khoản hiệu quả giảm. Do đó, giá của BPT tương ứng (wstETH/rETH/cbETH) trở nên bị nén (deflated) vì $\text{BPT price} = \frac{D}{\text{totalSupply}}$.

Phân Tích Tấn Công 0x3

Kẻ tấn công đã thực hiện

Tấn công hai giai đoạn, có thể nhằm giảm thiểu rủi ro bị phát hiện:

  • Ở giai đoạn đầu tiên, lõi được sử dụng để thực hiện trong một giao dịch đơn lẻ, không có lợi nhuận ngay lập tức.
  • Ở giai đoạn thứ hai, kẻ tấn công thực hiện lợi nhuận bằng cách rút tài sản trong một giao dịch khác.

Giai đoạn đầu tiên có thể được chia thành hai giai đoạn: tính toán tham số và trao đổi hàng loạt. Dưới đây, chúng tôi sử dụng một giao dịch tấn công (TX) trên Arbitrum làm ví dụ để minh họa cho những giai đoạn này.

Giai đoạn tính toán tham số

Trong giai đoạn này, kẻ tấn công sẽ kết hợp tính toán ngoại tuyến với mô phỏng trực tuyến, điều chỉnh chính xác các tham số của từng bước trong giai đoạn tiếp theo (hoán đổi hàng loạt) dựa trên trạng thái hiện tại của hồ chứa ổn định kết hợp (bao gồm hệ số thu phóng, hệ số khuếch đại, tỷ giá BPT, phí hoán đổi và các tham số khác). Thú vị là, kẻ tấn công còn triển khai một hợp đồng phụ trợ để hỗ trợ những tính toán này, có thể là để giảm thiểu rủi ro bị “đi trước” (front-running).

Đầu tiên, kẻ tấn công thu thập thông tin cơ bản của nhóm mục tiêu, bao gồm hệ số tỷ lệ của mỗi Token, tham số khuếch đại, tỷ lệ BPT và tỷ lệ phí trao đổi. Sau đó, họ tính toán một giá trị quan trọng trickAmt, đây là số lượng Token mục tiêu bị thao túng được sử dụng để gây ra tổn thất độ chính xác.

Gọi hệ số tỷ lệ (scaling factor) của Token mục tiêu là sF, tính như sau:

Hình ảnhĐể xác định các tham số được sử dụng trong bước 2 (hoán đổi hàng loạt) của giai đoạn tiếp theo, kẻ tấn công đã thực hiện cuộc gọi mô phỏng tiếp theo đến hàm 0x524c9e20 của hợp đồng phụ với calldata sau:

uint256[] balances; // Số dư của Pool Token (không bao gồm BPT) uint256[] scalingFactors; // Hệ số tỷ lệ của mỗi Token trong bể uint tokenIn; // Chỉ số Token đầu vào của lần nhảy này uint tokenOut; // Chỉ số Token đầu ra của lần nhảy này uint256 amountOut; // Số lượng Token đầu ra mong muốn uint256 amp; // Tham số mở rộng của bể uint256 fee; // Tỷ lệ phí trao đổi trong pool

Dữ liệu trả về là:

uint256[] balances; // Số dư Token của bể sau khi hoán đổi (không bao gồm BPT)

Cụ thể, số dư ban đầu và số lần lặp lại được tính toán ngoài chuỗi và được truyền dưới dạng tham số cho hợp đồng của kẻ tấn công (báo cáo lần lượt là 100,000,000,000 và 25). Mỗi lần lặp lại thực hiện ba lần hoán đổi:

  1. Hoán đổi 1: Đẩy số lượng Token mục tiêu lên trickAmt + 1, giả sử hướng hoán đổi là 0 → 1.
  2. Đổi 2: Tiếp tục sử dụng trickAmt để đổi lấy Token mục tiêu, điều này sẽ kích hoạt việc làm tròn xuống trong cuộc gọi _upscale(). 320,000.

Xin lưu ý rằng, do việc tính toán StableMath sử dụng phương pháp Newton–Raphson, bước này có thể thỉnh thoảng gặp thất bại. Để giảm thiểu tình huống này, kẻ tấn công đã thực hiện hai lần thử lại, mỗi lần sử dụng giá trị gốc là 9/10 làm giá trị dự phòng.

Hợp đồng phụ trợ của kẻ tấn công được phát sinh từ thư viện StableMath của Balancer V2, điều này có thể được chứng minh bằng thông điệp lỗi tùy chỉnh kiểu “BAL” mà nó chứa.

$d$ Giai đoạn trao đổi hàng loạt

Sau đó, thao tác batchSwap###( có thể được chia thành ba bước:

  1. Bước 1: Kẻ tấn công sẽ đổi BPT )wstETH/rETH/cbETH( thành tài sản cơ sở, nhằm điều chỉnh chính xác số dư của một Token (cbETH) đến rìa của biên độ làm tròn (số lượng = 9). Điều này tạo điều kiện cho sự mất mát độ chính xác ở bước tiếp theo.
  2. Bước 2: Sau đó, kẻ tấn công sử dụng một số lượng được thiết kế cẩn thận (= 8) để thực hiện giao dịch giữa một loại tài sản cơ bản khác (wstETH) và cbETH. Do việc làm tròn số lượng Token xuống khi mở rộng, Δx được tính toán trở nên hơi nhỏ (từ 8.918 xuống 8), dẫn đến Δy bị đánh giá thấp, làm cho bất biến (D, từ mô hình StableSwap của Curve) trở nên nhỏ hơn. Do $\text{BPT price} = \frac{D}{\text{totalSupply}}$, giá BPT bị ép thấp một cách nhân tạo.

![Hình ảnh])( 3. Bước 3: Kẻ tấn công sẽ đổi lại tài sản cơ bản thành BPT, khôi phục sự cân bằng, đồng thời thu lợi từ việc giá BPT bị làm giảm.

0x4: Tấn công và tổn thất

Chúng tôi đã tóm tắt các cuộc tấn công này cùng với tổn thất tương ứng trong bảng dưới đây, tổng tổn thất vượt quá 125 triệu USD.

![Hình ảnh])(

0x5 Kết luận

Sự kiện này liên quan đến một loạt các giao dịch tấn công nhằm vào giao thức Balancer V2 và các dự án nhánh của nó, dẫn đến tổn thất tài chính lớn. Sau cuộc tấn công ban đầu, đã quan sát thấy nhiều giao dịch tiếp theo và giả mạo trên nhiều chuỗi. Sự kiện này nhấn mạnh một số bài học quan trọng về thiết kế và an ninh của các giao thức DeFi:

  • Hành vi làm tròn và mất độ chính xác: Việc làm tròn đơn hướng (làm tròn xuống) được sử dụng trong thao tác phóng to (upscaling) khác với việc làm tròn hai chiều (làm tròn lên và xuống) được sử dụng trong thao tác thu nhỏ (downscaling). Để ngăn chặn các lỗ hổng tương tự, giao thức nên áp dụng toán học có độ chính xác cao hơn và thực hiện các kiểm tra xác minh vững chắc. Phải tuân thủ nguyên tắc tiêu chuẩn “Làm tròn luôn phải có lợi cho giao thức”.
  • Sự tiến hóa của việc khai thác lỗ hổng: Kẻ tấn công đã thực hiện một cuộc khai thác lỗ hổng phức tạp hai giai đoạn nhằm tránh bị phát hiện. Trong giai đoạn đầu, kẻ tấn công thực hiện khai thác cốt lõi trong một giao dịch mà không thu lợi ngay lập tức. Trong giai đoạn thứ hai, kẻ tấn công đã tạo ra lợi nhuận bằng cách rút tài sản trong một giao dịch khác. Điều này lại một lần nữa làm nổi bật cuộc “chạy đua vũ trang” liên tục giữa các nhà nghiên cứu an ninh và kẻ tấn công.
  • Ý thức vận hành và phản ứng với mối đe dọa: Sự kiện này nhấn mạnh tầm quan trọng của cảnh báo kịp thời về trạng thái khởi tạo và vận hành, cũng như các cơ chế phát hiện và phòng ngừa mối đe dọa chủ động, nhằm giảm thiểu tổn thất tiềm ẩn do các cuộc tấn công kéo dài hoặc bắt chước.

Trong khi duy trì hoạt động và tính liên tục của doanh nghiệp, các bên tham gia trong ngành có thể sử dụng BlockSec Phalcon như hàng rào cuối cùng để bảo vệ tài sản của họ. Đội ngũ chuyên gia của BlockSec luôn sẵn sàng thực hiện đánh giá an toàn toàn diện cho dự án của bạn.

Bài viết liên kết:

Nguồn:

BPT11.25%
Xem bản gốc
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.
  • Phần thưởng
  • Bình luận
  • Đăng lại
  • Retweed
Bình luận
0/400
Không có bình luận
  • Gate Fun hotXem thêm
  • Vốn hóa:$5.01KNgười nắm giữ:2
    3.15%
  • Vốn hóa:$4.21KNgười nắm giữ:2
    0.04%
  • Vốn hóa:$4.23KNgười nắm giữ:3
    0.14%
  • Vốn hóa:$4.14KNgười nắm giữ:1
    0.00%
  • Vốn hóa:$4.21KNgười nắm giữ:2
    0.25%
  • Ghim
Giao dịch tiền điện tử mọi lúc mọi nơi
qrCode
Quét để tải xuống ứng dụng Gate
Cộng đồng
Tiếng Việt
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)