Họ vừa raise 10 triệu USD từ một quỹ top-tier. Token chưa launch, nhưng tôi đã tìm thấy lỗi ngay từ dòng code đầu tiên.
Đầu tháng này, tôi nhận được một hợp đồng audit từ một dự án DeFi mới tên YieldX — một giao thức yield farming thế hệ mới hứa hẹn giải quyết vấn đề impermanent loss bằng dynamic rebalancing. Whitepaper của họ dài 40 trang, toàn sơ đồ đẹp và thuật ngữ ‘next-gen’. Nhưng tôi không bao giờ đọc whitepaper trước. Tôi vào thẳng GitHub, clone repo, mở file YieldXOracle.sol. Mất khoảng 30 phút để phát hiện ra lỗi. Một lỗi đến từ thời ShibeCoin 2017 — validation đầu vào thiếu.
Context
YieldX sử dụng một oracle lai: lấy giá từ Chainlink feed, sau đó tính trung bình với Uniswap V3 TWAP để ‘chống flash loan’. Họ gọi nó là ‘Hybrid Price Feed v2’. Cơ chế: chainlink oracle gọi latestRoundData(), lấy giá và thời gian cập nhật; nếu thời gian quá cũ (>1 giờ), fallback sang Uniswap TWAP. Mọi thứ nghe có vẻ an toàn. Nhưng điểm mù nằm ở phép tính trung bình — họ so sánh giá chainlink và giá TWAP, nếu chênh lệch >5% thì revert. Logic có vẻ hợp lý: tránh oracle bị tấn công. Tuy nhiên, họ quên kiểm tra roundId trong chainlink feed. Khi chainlink proxy trả về giá từ round cũ, nhưng roundId không tăng lên, latestRoundData vẫn trả về giá hợp lệ nhưng timestamp cũ. Nếu timestamp cũ nhưng chưa đủ giờ, fallback không kích hoạt, và giá chainlink có thể bị lỗi thời trong khi TWAP chạy đúng. Lỗi ở dòng 47: (uint80 roundId, int256 answer, , uint256 updatedAt, uint80 answeredInRound) = priceFeed.latestRoundData(); — họ không kiểm tra answeredInRound >= roundId. Nghĩa là dữ liệu có thể đến từ round không hoàn chỉnh. Đây là lỗi kinh điển được CEX.io từng khai thác năm 2022.
Core
Tôi reproduce lỗi trên môi trường fork mainnet bằng Foundry. Tạo một kịch bản: giả lập chainlink proxy trả về giá từ round 100 với answeredInRound = 99 (giá của round trước). YieldX oracle nhận giá đó, so với TWAP thấy chênh lệch 4.9% (dưới ngưỡng 5%), cho qua. Nhưng giá thực tế đã thay đổi 15% do một sự kiện lớn. Kẻ tấn công có thể lợi dụng để thanh lý vị thế với giá sai. Tôi viết một script chứng minh: với một khoản vay flash 500 ETH, attacker có thể tạo ra một thanh lý hàng loạt, gây thiệt hại ước tính 2.3 triệu USD nếu TVL của giao thức đạt 50 triệu. Tôi gửi report lên GitHub của họ với 4 proof-of-concept. Đáp lại, CTO nói ‘chúng tôi đã test TWAP trước, không thấy vấn đề’. Họ không test chainlink edge case. Log không biết nói dối — tôi đưa ra kết quả console của Foundry, rõ ràng answeredInRound != roundId. Họ im lặng 3 ngày, sau đó merge PR fix của tôi và tặng bounty 5.000 USD. Tôi từ chối, chỉ yêu cầu họ public disclosure. Họ không đồng ý. Mã nguồn là sự thật cuối cùng — lỗi tồn tại trên mainnet chưa được công bố.
Contrarian
Điều trớ trêu: YieldX tự hào về ‘multi-layer security’ trong whitepaper, nhưng lỗi đến từ một dòng code copy-paste từ OpenZeppelin mà không hiểu. Họ dùng chainlink như ‘bảo kê’ cho vòng gọi vốn. Nhà đầu tư kiểm tra ‘có chainlink feed’, rồi OK. Họ không audit code — họ audit logo. Đây là điểm mù toàn thị trường: FOMO khiến mọi người tin vào thương hiệu oracle hơn là logic hợp đồng. Chainlink vốn đã là nghịch lý — phi tập trung qua các node tập trung, nhưng ít ai kiểm tra cách họ tích hợp. Lỗi answeredInRound đã được ghi nhận từ năm 2020 trên các diễn đàn, nhưng vẫn xuất hiện trong 3/10 dự án tôi audit gần đây. Các đội ngũ thường nghĩ ‘chainlink là an toàn tuyệt đối’, trong khi thực tế, cách hook feed vào contract mới quyết định. Tôi gọi đây là ‘security theater’ — tạo ra ảo tưởng bảo mật bằng cách liệt kê tên các đối tác.
Takeaway
Lần tới khi bạn thấy một dự án khoe ‘audited by...’, hãy hỏi: họ đã audit chainlink integration hay audit tokenomics? Câu trả lời sẽ quyết định 10 triệu USD tiếp theo của bạn có đi vào lỗ hổng hay không.