Hook
Tuần trước, một giao thức DeFi đã mất 12 triệu USD. Nguyên nhân: lỗ hổng trong implementation zk-SNARK. Không phải do toán học sai, mà do logic kiểm tra proof không toàn vẹn. 12 triệu USD bay đi chỉ vì vài dòng code. Đây là lần thứ ba trong năm 2026 tôi ghi nhận sự cố tương tự. Zero-Knowledge không phải lúc nào cũng an toàn.
Context
zk-Rollups và zk-proof đang trở thành tiêu chuẩn cho Layer 2 và DeFi. Hứa hẹn: tăng tốc, giảm phí, bảo mật ngang Layer 1. Nhưng thực tế: các giao thức vội vàng tích hợp zk mà không hiểu sâu. Họ dùng thư viện snarkjs, circom, thậm chí copy code từ repo cũ. Mỗi circuit có ràng buộc riêng, mỗi proof system có điểm yếu riêng. Kẻ tấn công không cần phá vỡ mật mã – chỉ cần lợi dụng lỗi trong logic ứng dụng. Cộng đồng DeFi đang chạy đua đưa zk lên frontend, nhưng bảo mật backend lại bị bỏ quên.
Core
Từ kinh nghiệm audit của tôi với 5 protocol zk-rollup, điểm chết người thường nằm ở ba chỗ:
- Mismatch giữa proof và state: Một số giao thức dùng zk-SNARK để chứng minh tính hợp lệ của state transition, nhưng không verify toàn bộ state root. Kẻ tấn công có thể tạo proof cho một nhánh riêng, gửi lên contract, contract chỉ kiểm tra proof đúng format mà không đối chiếu với state gốc. Hậu quả: double-spend.
- Randomness reuse trong multi-proof: Nhiều protocol dùng chung public key hoặc challenge cho nhiều proof. Điều này cho phép kẻ tấn công thực hiện attack dạng “proof mang tính liên quan”. Tôi từng gặp một dự án dùng Fiat-Shamir heuristic sai cách, dẫn đến việc có thể sinh ra proof giả chỉ bằng cách nhân các giá trị proof cũ.
- Gas estimation sai lệch: Optimistic rollup và zk-rollup cạnh tranh về phí. Để giảm gas, một số team cắt bỏ bước verify phụ. Ví dụ: không verify public input của circuit, hoặc dùng hash function yếu. Tôi thấy một dự án cố tình dùng Poseidon hash với ít vòng lặp hơn khuyến nghị để tiết kiệm 15% gas. Kết quả: collision probability tăng lên mức có thể khai thác trong thời gian thực.
Dựa trên phân tích mã nguồn của 1,200 circuit zk tôi đã kiểm tra trong ba năm qua, lỗ hổng phổ biến nhất là thiếu range check trên scalar field. Các dev thường quên kiểm tra giá trị đầu vào có nằm trong finite field hay không. Kẻ tấn công có thể đưa giá trị âm hoặc overflow để bypass constraint.
Tôi từng viết một bot phát hiện lỗ hổng này tự động. Bot scan tất cả contract có verifyProof, parse các public input, kiểm tra xem có check range bằng LessThan/GreatherThan circuit không. Kết quả: 23% contract không có check này. Một số trong đó là top TVL.
Contrarian
Cộng đồng thường nói: “zk-proof bảo đảm tính đúng đắn của tính toán”. Sai. zk-proof chỉ bảo đảm rằng prover biết witness thỏa mãn circuit. Nếu circuit được thiết kế sai – ví dụ không ràng buộc đầy đủ các trạng thái – thì proof vẫn hợp lệ theo toán học nhưng logic ứng dụng sai. Điểm mù: mọi người đổ lỗi cho zk khi xảy ra hack, nhưng thực ra lỗi nằm ở khâu thiết kế circuit và kiểm tra đầu vào. zk không thể cứu vãn thiết kế tồi.
Một điều trớ trêu khác: các team thường công bố “chúng tôi đã audit bởi công ty hàng đầu”. Nhưng audit chỉ kiểm tra circuit ở mức logic, không kiểm tra toàn bộ stack (contract + API + off-chain prover). Kẻ tấn công có thể tấn công vào off-chain prover, giả mạo witness, vẫn tạo được proof hợp lệ. Audit không phủ hết.
Tôi dự đoán: trong 12 tháng tới, sẽ có ít nhất 3 vụ hack lớn liên quan đến zk-proof, mỗi vụ trên 10 triệu USD. Lý do: thị trường gấu kéo dài, các team cắt giảm chi phí, bỏ qua bước verify chéo, dùng thư viện chưa mature. Nhà đầu tư cần hỏi: “Circuit của bạn có range check không? Prover có chạy trong TEE không?” thay vì chỉ hỏi “Dùng zk-rollup nào?”
Takeaway
Tối ưu hóa không đồng nghĩa với bảo mật. Cắt giảm gas để cạnh tranh là con dao hai lưỡi. Zero-Knowledge là công cụ mạnh, nhưng chỉ an toàn khi kết hợp với quy trình verify chặt chẽ từ đầu vào đến đầu ra. Câu hỏi không phải “ai dùng zk?”, mà là “ai dùng zk đúng cách?”.