22 giây. Đó là khoảng thời gian kẻ tấn công xoáy sạch pool thanh khoản NovaSwap trên Arbitrum. Không phải do oracle giá – lỗi nằm ở hợp đồng staking, nơi hàm withdraw() quên cập nhật số dư trước khi gọi lại bên ngoài. Tôi đã đọc dòng code đó ba lần, và vẫn không thể tin nổi một dự án có audit từ hai công ty lớn lại để sót reentranry cơ bản như vậy.
Thị trường đang tăng. Mọi người đổ xô vào yield farming với hy vọng kiếm lời nhanh. Nhưng chính những lúc này, lỗ hổng kỹ thuật thường bị che giấu bởi sự phấn khích. NovaSwap là một DEX mới, TVL đạt 12 triệu USD chỉ sau 3 tuần ra mắt nhờ chiến dịch airdrop hấp dẫn. Giao thức hứa hẹn cơ chế thanh khoản tập trung kiểu Uniswap v3, kết hợp với staking tự động sinh lời. Nhưng khi tôi đi sâu vào mã nguồn, một điều kỳ lạ xuất hiện: hàm emergencyWithdraw thừa kế từ contract base không được kiểm tra bởi auditor? Thực ra, auditor đã kiểm tra. Chỉ là họ bỏ qua một nhánh – khi người dùng unstake toàn bộ số dư, hợp đồng gửi token trước, sau đó mới đặt balance về 0. Kẻ tấn công đã tận dụng callback từ token ERC-777 để gọi lại unstake trước khi balance được cập nhật, tạo ra vòng lặp vô tận.
Core insight nằm ở dòng lệnh thứ 312: _transferTokens(msg.sender, amount); đứng trước balance[msg.sender] -= amount;. Checks-Effects-Interactions pattern bị vi phạm. Điều này quá quen thuộc với bất kỳ ai từng đọc DAO hack năm 2016. Nhưng tại sao NovaSwap vẫn mắc lỗi? Bởi vì đội ngũ phát triển vội vàng, và auditor có thể đã bỏ qua do contract staking vay mượn từ một repo cũ. Tôi đã kiểm tra repo gốc: nó từng được patch sau một bài báo cáo lỗi vào tháng 3/2024, nhưng NovaSwap lại fork phiên bản chưa patch. Một sai lầm sơ đẳng.
Nhưng điều contrarian ở đây là: lỗi reentrancy không phải nguyên nhân chính gây mất thanh khoản. Thực tế, kẻ tấn công chỉ lấy được 200 ETH (~$400k) từ pool staking. 600 nghìn USD còn lại bị mất do... chính cộng đồng. Khi tin tức hack lan ra, người dùng hoảng loạn rút thanh khoản khỏi pool AMM, gây ra trượt giá nghiêm trọng. Một bot MEV đã lợi dụng chênh lệch giá để sandwich attack, cuỗm thêm 200 ETH. Vậy thiệt hại thực sự đến từ lỗi kỹ thuật hay từ hành vi bầy đàn? Theo dữ liệu on-chain, 60% tổn thất xảy ra trong 10 phút đầu sau khi hack được công bố, trước khi bất kỳ ai có thể phản ứng. Thị trường tăng càng khiến tâm lý FOMO dễ vỡ – mọi người đã stake số tiền lớn hơn nhiều so với bình thường, và không có kịch bản fallback.
Takeaway: Dù bot copy trading của tôi luôn cắt lỗ tự động dựa trên thanh khoản on-chain, nhưng với những dự án mới có TVL tăng nhanh, tôi dành ít nhất một ngày để đọc toàn bộ mã nguồn staking. Lỗi reentrancy sẽ luôn tồn tại ở những nơi bạn ít ngờ nhất – như một hàm withdraw tưởng chừng vô hại. Hãy tự hỏi: Khi thị trường sôi động, bạn có đủ tỉnh táo để kiểm tra dòng balance[msg.sender] -= amount; trước hay sau khi gửi token? Câu trả lời quyết định số tiền bạn giữ được.