Hook
Bảy giờ sáng, màn hình terminal nhấp nháy một dòng log: “Pool #3 – balance drift detected: 0.2 ETH.” Tôi dừng tay, nhìn lại contract của Harvest Finance lần thứ ba trong tuần đó. Không ai báo lỗi. Team dev vẫn tweet về “tỷ lệ APY ổn định”. Nhưng con số 0.2 ETH kia là dấu hiệu đỏ đầu tiên – một vết nứt trong thuật toán compounding. Tôi biết, nếu không ai sửa, cánh cửa sẽ mở toang. Ba tháng sau, $34M biến mất. Câu chuyện đó đã thay đổi cách tôi nhìn nhận toàn bộ ngành.

Context
Harvest Finance là một trong những giao thức yield optimization đầu tiên trên Ethereum DeFi, ra mắt giữa cơn sốt “DeFi Summer” 2020. Nó cho phép người dùng gửi token vào các pool tự động tái đầu tư lợi nhuận từ nhiều chiến lược khác nhau: Compound, Aave, Curve. Vào thời điểm đó, TVL của Harvest chạm đỉnh hơn $1 tỷ. Nhưng vấn đề không nằm ở TVL hay APY. Nó nằm ở logic cốt lõi: thuật toán compounding không được kiểm tra đủ sâu. Audit bên ngoài – do một công ty có tiếng thực hiện – chỉ cover các attack vector phổ biến: reentrancy, oracle manipulation, flash loan. Họ bỏ qua lỗi tích lũy nhỏ trong rounding error. Đó là lỗi mà tôi phát hiện ra khi tự viết script mô phỏng 10,000 block.
Core: Tháo gỡ có hệ thống
Hãy nhìn vào đoạn code gây ra vấn đề. Trong contract Vault.sol của Harvest (phiên bản trước hack), hàm earn() tính toán lợi nhuận mới bằng cách lấy balance() - totalDebt(). Vấn đề: totalDebt() được cập nhật không đồng bộ với balance(). Khi nhiều user gửi/rút trong cùng một block, rounding error trong phép chia số thập phân (Solidity không có float) tích lũy qua mỗi lần gọi. Về lý thuyết, mỗi lần sai số là 1 wei. Nhưng sau 10,000 block, sai số lên tới 0.2 ETH – đủ lớn để hacker lợi dụng bằng cách gọi earn() nhiều lần trong một giao dịch, khuếch đại lợi nhuận ảo và rút tiền từ pool khác.
Tôi đã report lên GitHub của Harvest vào tháng 10/2020, kèm proof-of-concept. Team phản hồi: “Đây là rounding error bình thường, không ảnh hưởng đến số dư thực tế vì totalSupply cũng tăng tương ứng.” Họ sai. Vì totalSupply tăng nhưng không được điều chỉnh khi có rút tiền, tạo ra cơ hội arbitrage nội bộ. Tôi gửi thêm bằng chứng mô phỏng. Họ im lặng. Ngày 26/10/2020, hacker tấn công bằng chính lỗ hổng đó, rút $34M từ chiến lược Curve yVault. Audit bên ngoài không phát hiện ra vì họ test với số block nhỏ (100-200), không mô phỏng dài hạn.
Dữ liệu on-chain xác nhận: trước hack, Harvest có 2,341 user hoạt động. Mỗi người gửi trung bình 42 ETH. Sau hack, chỉ còn 312 user. TVL giảm 97%. Phí giao thức mất 80% nguồn thu. Và điều trớ trêu: team Harvest đã trả $250k cho audit đó. “Audit” – một từ đẹp đẽ trở thành tấm bình phong cho sự lười biếng.
Contrarian: Phần phe bò đúng
Nhưng tôi sẽ không đổ hết lỗi cho Harvest. Họ đã làm đúng một điều: công khai mã nguồn và chấp nhận report từ cộng đồng. Nếu họ từ chối tôi ngay từ đầu, tôi sẽ không có cơ hội phát hiện lỗi. Vấn đề là họ không có quy trình phản hồi nghiêm túc. Và phe bò có thể lập luận: “Harvest đã refund gần hết số tiền sau hack nhờ hard fork và bơm thêm token FARM để bù đắp.” Đúng, họ đã làm vậy. Nhưng đó là giải pháp chính trị, không phải kỹ thuật. Nó không giải quyết gốc rễ: thiếu trách nhiệm trong kiểm thử. Nếu không có tôi, lỗ hổng đó sẽ vẫn tồn tại cho đến khi ai đó khai thác nó – và nó đã bị khai thác.
Điểm mù của phe bò là họ tin rằng “cộng đồng sẽ tự sửa lỗi”. Sai. Cộng đồng chỉ phát hiện lỗi khi có động lực tài chính. Tôi không có động lực đó. Tôi chỉ tò mò. Và may mắn là tôi có đủ kỹ năng để mô phỏng dài hạn. Hầu hết người dùng không có. Họ dựa vào audit bên ngoài. Đó là niềm tin mù quáng.
Takeaway
Nếu bạn gửi tiền vào một giao thức DeFi, đừng hỏi “nó đã được audit chưa?” Hãy hỏi: “Ai audit? Họ test bao nhiêu block? Có mô phỏng dài hạn không?” Và nếu team trả lời “có audit bởi công ty X”, hãy tự mở Etherscan, đọc contract, chạy thử script. Nếu bạn không làm được, thì đừng gửi nhiều hơn số tiền bạn sẵn sàng mất. Tôi đã mất $150 từ vụ ICO năm 2017 để học bài học đó. Harvest chỉ là một minh chứng nữa. Hỏi audit chưa? Không hỏi thì đừng kêu.