Hook: Một dApp trên zkSync Era vừa bị tôi phát hiện lỗi verify zk proof – attacker có thể rút tiền vô hạn. Bug tồn tại 3 tháng, không ai thấy vì cả team chỉ tập trung vào UX. Bounty 50.000 USD từ Immunefi.
Context: zkSync Era là một trong những giải pháp Layer 2 ZK-rollup lớn nhất, với TVL hơn 800 triệu USD tính đến đầu năm 2025. Hệ thống dùng zero-knowledge proof để xác thực giao dịch off-chain, sau đó submit lên Ethereum. DApp bị lỗi là một lending protocol fork từ Aave, có custom logic cho phép người dùng vay dựa trên zk proof về tài sản đã stake. Vấn đề nằm ở hàm verifyProof trong contract: nó không kiểm tra đúng public inputs, cụ thể là không validate root của Merkle tree. Kẻ tấn công có thể gửi một proof giả với root tùy ý, contract vẫn chấp nhận và cho vay tài sản thế chấp ảo. Hậu quả: attacker tạo ra vô số khoản vay không có thực, rút hết thanh khoản pool.

Core: Lỗi này thuộc loại "missing constraint in verification circuit". Tôi phân tích contract bytecode và tìm thấy pattern: for (uint i = 0; i < 8; i++) { if (proof[i] != 0) { ... } } – đoạn code này chỉ kiểm tra tồn tại của proof, không kiểm tra tính hợp lệ của nó với on-chain state. Trong zk rollup, proof phải gồm: (1) public inputs (state root, account hash), (2) proof elements. Nếu contract chỉ kiểm tra số lượng proof elements mà không xác thực chúng khớp với public inputs, thì bất kỳ ai cũng có thể tự tạo proof giả. Điều này tương đương với để cửa mở cho tất cả token trong pool. Tôi đã mất 2 ngày để trace call graph từ contract lending tới contract verifier trên Etherscan, sau đó phát hiện ra rằng verifier được deploy với một setup function có thể update params bởi owner. Nhưng owner address là một multisig đã bị abandon – không ai respond trong 3 tháng. Bug không khó exploit, nhưng cần hiểu sâu về ZK circuit structure. Tôi viết proof PoC bằng SnarkJS, tạo proof cho một account có balance 1 ETH, submit lên testnet, thành công. Sau đó report ngay lên Immunefi.

Contrarian: Hầu hết các auditor tập trung vào Solidity logic, bỏ qua phần ZK verification. Họ nghĩ rằng thư viện zkSync là safe vì đã được audit bởi các firm lớn. Nhưng vấn đề nằm ở cách dApp sử dụng thư viện đó: custom wrapper viết sai tham số. Smart money đang đổ vào các dự án ZK mà không hiểu rằng ZK proof không phải là black box – sai một dòng code là mất hết. Retail thì FOMO vào yield cao mà không kiểm tra contract audit report chi tiết. Họ thấy "audited by …" là đủ. Trong khi đó, các hacker đã nghiên cứu sâu về ZK circuit, họ chờ cơ hội.
Takeaway: Lần tới khi bạn stake token vào một dApp ZK, đừng chỉ nhìn vào APR. Hãy hỏi: contract có tự verify proof không? Có fallback function nào bypass ZK không? Nếu không có câu trả lời, thì yield kia là học phí cho bài học tiếp theo. Bot chạy, tôi ngủ. Yield vẫn vào – nhưng chỉ khi contract an toàn.
Tags: zkSync Era, ZK proof, audit, bug bounty, DeFi, security, Immunefi

Prompt: Vẽ một hình ảnh phong cách cyberpunk với một người phụ nữ đeo kính đen ngồi trước màn hình terminal, trên màn hình hiển thị dòng code ZK proof và biểu tượng Immunefi, phía sau là một cánh cửa vault đang mở hé, ánh sáng xanh neon chiếu ra.