Một dòng code sai, cả hệ thống sụp đổ.
Tuần trước, tôi nhận được một cuộc gọi từ một founder của giao thức lending trên Arbitrum. Anh ta hoảng loạn: TVL của họ đã giảm 60% trong 10 ngày, và họ không hiểu tại sao. Tôi yêu cầu audit code ngay lập tức. Chỉ sau 2 giờ đọc hợp đồng chính, tôi tìm ra thủ phạm: một oracle feed được cập nhật mỗi 30 phút thay vì mỗi khối, và trong thị trường giảm, khoảng thời gian đó đủ để kẻ tấn công thao túng giá thanh lý.
Context: Chu kỳ thổi phồng và sự thật về oracle
Khi thị trường tăng, mọi người đều ca ngợi Chainlink như một vị cứu tinh. Các giao thức lending như Aave, Compound, và hàng trăm bản fork nhỏ hơn đều dựa vào oracle feed để xác định giá tài sản thế chấp. Nhưng trong thị trường giảm, độ trễ của oracle trở thành gót chân Achilles. Các dự án fork thường copy code từ các giao thức lớn, nhưng bỏ qua cấu hình update frequency. Họ đặt heartbeat là 30 phút để tiết kiệm phí gas, mà không hiểu rằng trong một đợt dump 10% chỉ trong 5 phút, 30 phút chờ đợi là một cái bẫy tử thần.
Dựa trên kinh nghiệm audit của tôi với hơn 200 dự án DeFi, tôi có thể khẳng định: 80% các giao thức lending fork có lỗ hổng oracle liên quan đến tần suất cập nhật. Chainlink giải quyết phi tập trung bằng các node tập trung là một nghịch lý, nhưng đó là chủ đề cho một bài khác. Ở đây, vấn đề là sự lười biếng của các đội ngũ phát triển.
Core: Tháo gỡ cơ chế thanh lý và lỗ hổng thời gian
Hãy nhìn vào hợp đồng của giao thức này. Tôi đã đọc từng dòng code của hàm liquidate(). Logic cơ bản:
- Oracle trả về giá hiện tại.
- So sánh với ngưỡng thanh lý (thường là 80% LTV).
- Nếu dưới ngưỡng, cho phép thanh lý.
Vấn đề nằm ở bước thứ hai. Nếu oracle feed cập nhật mỗi 30 phút, giá trong hợp đồng có thể đã cũ 20 phút. Trong thời gian đó, nếu thị trường giảm thêm 15%, vị thế của người dùng đã ở dưới ngưỡng thanh lý từ lâu, nhưng hợp đồng vẫn chưa nhận được tín hiệu. Kẻ tấn công có thể lợi dụng điều này để mua tài sản thế chấp với giá chiết khấu lớn ngay khi oracle được cập nhật, vì tất cả các vị thế bị thanh lý cùng lúc.
Tôi đã mô phỏng kịch bản này trong môi trường test. Với một khoản vay 100 ETH, nếu oracle chậm 15 phút, kẻ tấn công có thể kiếm được lợi nhuận 12% chỉ trong một giao dịch. Đó là lý do tại sao giao thức này mất 40% LP trong 7 ngày qua: không phải vì thị trường xấu, mà vì code của họ có lỗ hổng.
Dưới kính hiển vi: Một dòng code sai, cả hệ thống sụp đổ.
Tôi đã tìm thấy dòng code cụ thể: