BTC 6 4
Đếm sai một, mất cả kho.
Ngày hôm qua, dự án DeFi "Mekong Finance" – một fork của Compound được quảng cáo là "đội ngũ Việt 100%, có audit bởi công ty bảo mật danh tiếng" – bị rút sạch 400 ETH (~15 tỷ VND) sau 6 giờ hoạt động chính thức.
400 ETH. Đối với một dự án huy động được 12.000 ETH từ ICO, con số này tưởng như chẳng là bao. Nhưng tôi đọc txhash. Tôi đọc contract. Và tôi thấy một điều quen thuộc: lỗi reentrancy cổ điển trong hàm withdraw, kết hợp với việc tính toán lãi suất dựa trên block.timestamp không được kiểm tra kỹ.
ICO ảo – kỹ thuật thật.
Context
Mekong Finance ra mắt vào tháng 4/2025, huy động 12,000 ETH qua một chiến dịch ICO rầm rộ. Họ fork Compound v2, sửa đổi logic farm LP token, thêm tính năng "Dynamic Fee" nhằm hút thanh khoản người dùng Việt. Họ công bố audit bởi một công ty tôi biết – họ gửi cho tôi báo cáo dài 120 trang, nhưng tôi chỉ xem phần code diff. Vì tôi biết: fork từ code đã audit không có nghĩa là dự án được audit.
Khi chạy thử local testnet, tôi thấy ngay vấn đề: họ không khởi tạo lại nonce cho checkpoint trong contract quản lý pool. Mỗi lần gọi withdraw, nonce vẫn giữ nguyên – tạo cơ hội cho reentrancy attack. Tôi đã gửi báo cáo 5 trang cho người dùng trong cộng đồng, nhưng ai đó chỉ comment: "Kẻ FUD". Sáu ngày sau, hacker khai thác.
Core: Tháo Rã Từng Dòng Code
Metadata lỗi – niềm tin sập.
Hãy mở Etherscan. Contract của Mekong Finance: 0x4b4e... (không tiết lộ để tránh copy). Xem hàm withdraw():
function withdraw(uint256 _pid, uint256 _amount) external nonReentrant {
UserInfo storage user = userInfo[_pid][msg.sender];
require(_amount <= user.amount, "insufficient balance");
updatePool(_pid);
uint256 pending = user.rewardDebt.sub(user.amount.mul(accPercShare[_pid]));
// ...
user.amount = user.amount.sub(_amount);
// Gọi external call trước khi cập nhật số dư
safeTokenTransfer(msg.sender, _amount);
// Cập nhật rewardDebt sau
user.rewardDebt = user.amount.mul(accPercShare[_pid]);
}
Đây là lỗi reentrancy kinh điển: external call (safeTokenTransfer) được thực hiện trước khi cập nhật biến trạng thái user.rewardDebt. Kẻ tấn công deploy contract, gọi withdraw trong fallback function, lặp lại cho đến khi hết ETH trong pool. Kết quả: 400 ETH bị rút trong 12 block.
Nhưng không chỉ vậy. Họ dùng block.timestamp để tính accPercShare, nhưng không lock mức thời gian. Kẻ tấn công có thể gọi deposit và withdraw trong cùng một block, khiến accPercShare = 0, nhưng lỗi reentrancy vẫn có hiệu lực.
Thực ra, tôi đã tìm thấy lỗi này trong file diff của contract MekongFinance.sol (phiên bản trước audit). Tôi chạy test với 100 ETH giả, exploit hoạt động hoàn hảo. Đây là lỗi mà bất kỳ auditor nào cũng phải thấy – nếu họ tự tay chạy test, không chỉ đọc báo cáo của Compound.
Contrarian: Phần Phe Bò Đúng, Nhưng Sai Cách
Có người bảo: "Mekong Finance chỉ là scam ngay từ đầu, không phải lỗi code." Tôi nói: sai.
Dự án thực sự deploy code, có source verified trên Etherscan, có audit report (dù audit report che giấu phần chính). Kẻ làm giàu từ ICO không có ý định cho người dùng rút gốc – họ muốn giữ thanh khoản càng lâu càng tốt. Nhưng lỗi reentrancy quá cơ bản đến mức nó không thể là cố tình. Nếu là cố tình, họ đã dùng một backdoor tinh vi hơn. Lỗi này giống như ai đó vội vã copy code Compound, sửa vài dòng, rồi quên không sửa dòng quan trọng nhất: thứ tự gọi hàm.
Bài học: Kể cả một dự án chi 120.000 USD cho audit, kể cả khi đội ngũ có 3 năm kinh nghiệm DeFi, một dòng lệnh sai vị trí cũng có thể lấy đi 400 ETH. Đếm sai một, mất cả kho.
Takeaway: Ai Sẽ Chịu Trách Nhiệm?
400 ETH đã biến mất. Nhà đầu tư ICO nắm giữ token chưa bao giờ có quyền rút gốc – họ chỉ nhận lãi từ phí giao dịch. Nhưng thanh khoản trong pool farm thì dựa trên ETH thật. Những ai deposit gốc để farm đã mất trắng.
Câu hỏi duy nhất tôi muốn đặt ra: liệu có ai trong số những người ký contract, những người duyệt audit, hay những KOL đã quảng bá dự án này từng tự mình chạy một test exploit trên local testnet trước khi launch? Hay tất cả chỉ dựa vào báo cáo 120 trang đóng gói đẹp đẽ?
Điều đó không thay đổi kết quả. Nhưng tôi hy vọng lần tới, khi gặp một dự án "DeFi Việt có audit", bạn sẽ dành 10 phút để đọc code, không phải 10 phút để buy token.