Hook
Một dự án vừa huy động 120 triệu USD từ các quỹ đầu tư hàng đầu, với whitepaper đầy hứa hẹn về cross-chain lending và yield farming tích hợp AI. Nhưng khi tôi mở bytecode của hợp đồng thông minh chính, một điều bất thường xuất hiện: hàm withdraw() thiếu kiểm tra msg.sender so với owner trong một nhánh cụ thể. Từ lỗ hổng nhỏ nhất, một hệ thống có thể sụp đổ. Đây không phải là một lỗi đơn giản – nó là dấu hiệu của cả một triết lý phát triển cẩu thả đang ẩn sau lớp vỏ marketing hoành tráng.
Context
Dự án có tên mã ‘NexusFi’, hướng đến việc kết nối thanh khoản giữa Ethereum, Arbitrum và Solana. Họ tuyên bố đã audit bởi một công ty bảo mật có tiếng, nhưng tôi nghi ngờ. Từ kinh nghiệm audit 8 năm, tôi biết rằng audit chỉ có giá trị nếu auditor thực sự đào sâu. NexusFi sử dụng kiến trúc ‘pool riêng lẻ’ cho mỗi cặp tài sản, với một hợp đồng router trung tâm. Whitepaper mô tả cơ chế ‘claimRewards’ an toàn nhờ multi-signature, nhưng trong mã nguồn tôi thấy một onlyOwner modifier được dùng không nhất quán. Bear market là mùa của những kẻ kiên nhẫn đào sâu. Trong thị trường tăng này, ai cũng vội vã FOMO, ít ai dừng lại để kiểm tra code.
Core
Tôi dành hai tuần để phân tích mã nguồn NexusFi (phiên bản đã deploy trên testnet). Điểm mấu chốt nằm ở hàm emergencyWithdraw – một tính năng cho phép người dùng rút tài sản khi pool bị tấn công. Hàm này gọi _transferTokens mà không kiểm tra trạng thái ‘pause’. Trong một kịch bản bình thường, nếu pool bị pause, emergencyWithdraw vẫn hoạt động – đó là ý đồ. Nhưng vấn đề ở chỗ: biến pause được cập nhật trong cùng một transaction với cuộc gọi emergencyWithdraw? Không. Hợp đồng không có cơ chế chống reentrancy ở cấp độ này. Dựa trên kinh nghiệm audit của tôi, đây là một lỗ hổng nghiêm trọng: kẻ tấn công có thể gọi pause() (nếu chiếm được quyền owner) và ngay lập tức gọi emergencyWithdraw để rút toàn bộ tài sản của pool trước khi bất kỳ ai kịp phản ứng. Thậm chí, nếu owner là multisig, một thành viên độc hại có thể lợi dụng khoảng thời gian giữa các lần xác nhận. Hợp đồng là luật, nhưng lỗ hổng là ngoại lệ.
Tôi kiểm tra thêm modifier onlyOwner – nó chỉ kiểm tra msg.sender == owner, nhưng owner được đặt trong constructor dưới dạng địa chỉ cứng. Nếu private key của owner bị lộ, toàn bộ hệ thống sụp đổ. Họ không dùng multisig thực sự, chỉ là một ví đơn. Trong báo cáo audit công khai, họ tự hào về việc “kiểm tra toàn diện”, nhưng tôi không thấy đề cập đến lỗ hổng này. Sự tĩnh lặng của dữ liệu thường che giấu bão tố. Một lỗi nữa: trong hàm addLiquidity, họ tính phí bằng cách nhân amount với feeBasisPoints rồi chia cho 10000, nhưng không kiểm tra overflow – dù Solidity 0.8+ đã tự động kiểm tra, nhưng nếu dùng unchecked block thì sao? Họ dùng unchecked trong một số phép tính để tiết kiệm gas, nhưng quên không kiểm tra điều kiện biên. Kết quả: nếu feeBasisPoints được set quá lớn (do lỗi admin), phí có thể bị sai lệch, dẫn đến mất tài sản cho người dùng.
Tôi tìm thấy tổng cộng 5 lỗi nghiêm trọng và 7 lỗi trung bình. Điều đáng nói: đội ngũ NexusFi đã bỏ qua những lỗi này vì họ tập trung vào tính năng AI, không phải bảo mật nền tảng. Tôi không tin vào lời nói, tôi tin vào bytecode.
Contrarian
Nhiều người cho rằng audit bởi công ty lớn là đủ tin cậy. Nhưng thực tế, auditor thường chỉ kiểm tra các lỗi phổ biến, bỏ qua logic nghiệp vụ phức tạp. NexusFi đã trả 500.000 USD cho một audit ‘cấp tốc’ trong 2 tuần – không đủ để phân tích toàn bộ kiến trúc. Điểm mù bảo mật ở đây không phải là kỹ thuật, mà là kinh tế: ngành audit đang bị thương mại hóa, công ty audit có động cơ bỏ qua lỗi để giữ khách hàng. Theo quan điểm của tôi, thị trường tăng đang che đậy sự yếu kém của quy trình audit. Nếu NexusFi sụp đổ vì lỗi, đó sẽ là hồi chuông cảnh tỉnh, nhưng hiện tại mọi người chỉ thấy con số huy động vốn.
Takeaway
Khi FOMO lên cao, hãy nhìn vào bytecode thay vì whitepaper. Sự kiện NexusFi chỉ là một ví dụ – còn hàng trăm dự án khác đang ẩn chứa lỗ hổng tương tự. Liệu chúng ta có đang xây dựng một hệ sinh thái trên nền cát? Câu trả lời nằm ở những dòng code mà ít ai đọc.