Tại sao một giao thức Layer 2 mất 500 ETH chỉ sau 48 giờ triển khai?

Tháng trước, tôi nhận được một cuộc gọi khẩn từ đồng nghiệp tại một dự án zk-Rollup mới. Họ vừa mất 500 ETH do một lỗ hổng trong cơ chế bằng chứng gian lận (fraud proof). Tôi đã mở mã nguồn ngay trong đêm. Sau 3 giờ phân tích, tôi tìm thấy nguyên nhân: một lỗi trong logic xác minh trạng thái (state verification) cho phép kẻ tấn công gửi một bằng chứng hợp lệ nhưng sai lệch. Đây không phải là lần đầu tiên.

Context: Cơ chế của zk-Rollup và điểm mù
zk-Rollup dùng bằng chứng không kiến thức (zero-knowledge proof) để xác thực hàng ngàn giao dịch ngoài chuỗi rồi gửi lên Ethereum. Khác với Optimistic Rollup chờ 7 ngày để thử thách, zk-Rollup có xác thực ngay lập tức. Cả hai đều dùng fraud proof – một cơ chế cho phép bất kỳ ai gửi bằng chứng về một giao dịch gian lận. Vấn đề nằm ở chỗ: bằng chứng này cần được xác minh bởi một hợp đồng thông minh trên Layer 1. Nếu hợp đồng có lỗi logic, kẻ tấn công có thể gửi bằng chứng 'hợp lệ' nhưng thực chất là sai.
Core: Phân tích mã nguồn và trade-off
Tôi đã audit hơn 50 hợp đồng thông minh từ 2017. Lỗi phổ biến nhất trong cơ chế zk-Rollup là thiếu kiểm tra 'state root' trước và sau khi áp dụng batch giao dịch. Trong trường hợp này, hợp đồng xác minh chỉ kiểm tra chữ ký số của sequencer mà không kiểm tra tính nhất quán của state root. Kẻ tấn công có thể gửi một batch với state root giả mạo, miễn là chữ ký đúng. Cụ thể, dòng 142-148 của contract Verifier.sol:
function verify(bytes calldata proof) external {
require(ecdsa.recover(proof, sequencer) == msg.sender, "Invalid signature");
// Thiếu: require(keccak256(stateRoot) == expectedRoot, "Invalid state");
applyBatch(proof);
}
Đây là trade-off giữa gas và bảo mật. Bỏ qua kiểm tra state root giúp giảm 30% gas cho mỗi batch, nhưng mở ra lỗ hổng nghiêm trọng. Tôi đã thấy pattern này trong ít nhất 5 dự án Layer 2 khác. Họ ưu tiên hiệu suất hơn an toàn, và kết quả là mất quỹ.

Contrarian: Điểm mù của cộng đồng
Bạn nghĩ rằng zk-Rollup là 'giải pháp scaling an toàn nhất'? Sai. Bằng chứng không kiến thức chỉ an toàn khi cả trình tạo bằng chứng (prover) và hợp đồng xác minh đều đúng. Thực tế, hầu hết các dự án đều dùng prover được tối ưu hóa từ các thư viện như snarkjs hoặc circom, nhưng hợp đồng xác minh thường được viết tay bởi đội ngũ riêng. Đây là điểm yếu. Từ kinh nghiệm audit của tôi, lỗi trong hợp đồng xác minh xảy ra thường xuyên hơn lỗi trong prover. Cộng đồng quá tập trung vào 'không cần trust' của zk, nhưng lại quên rằng trust được chuyển từ sequencer sang nhà phát triển hợp đồng.
Takeaway: Dự báo lỗ hổng
Trong 6 tháng tới, tôi dự đoán sẽ có ít nhất 3 vụ tấn công tương tự nhắm vào các zk-Rollup chưa được audit kỹ lưỡng. Nếu bạn đang đầu tư vào bất kỳ Layer 2 nào, hãy kiểm tra mã nguồn hợp đồng xác minh của họ. Nếu họ không publish mã, đó là red flag. Còn nếu họ có, hãy tìm dòng kiểm tra state root. Không có? Chuẩn bị cho rủi ro.
Câu hỏi duy nhất là: ai sẽ là nạn nhân tiếp theo?