Cái bug hôm qua, bài học hôm nay. #DeFi

Tuần trước, tôi nhận audit một hợp đồng yield farming mới ra mắt trên Arbitrum, tên mã 'GreenField V2'. Dự án huy động 12 triệu USD trong vòng private, TVL đạt 45 triệu chỉ sau 3 ngày. Mọi thứ có vẻ ổn: whitepaper dài 30 trang, team doxxed, audit từ một công ty nhỏ. Nhưng khi tôi đọc line-by-line, một dòng code trong hàm withdraw() khiến tôi dừng lại.

Context
Hợp đồng này sử dụng mô hình 'pull payment' thay vì 'push'. Người dùng gửi LP token, farming để nhận reward token. Hàm withdraw() cho phép rút cả LP và reward. Điểm đáng chú ý: team sử dụng thư viện OpenZeppelin phiên bản 4.8, nhưng custom lại một phần để tối ưu gas. Cụ thể, họ viết lại hàm _updateReward() bằng inline assembly, bỏ qua modifier nonReentrant. Lý do? Họ muốn giảm 2000 gas mỗi lần gọi.
Core – Phân tích kỹ thuật
Dòng code nguy hiểm: