Tôi mở Etherscan, tra địa chỉ hợp đồng của fan token chính thức cho đội tuyển bóng đá Anh – token được phát hành từ năm 2022. Mã nguồn đã được verify, nhưng tôi thấy một điều kỳ lạ: hàm claimReward không có modifier nonReentrant, nhưng lại gọi bên ngoài thông qua một interface lạ. Dòng 247: IERC20(token).safeTransfer(msg.sender, amount); – đây là một anti-pattern cổ điển mà tôi đã phát hiện từ thời EOS ICO audit năm 2017. Năm dòng tiếp theo, ngay trước khi cập nhật balance, có một callback ẩn đến địa chỉ 0x...dead. Không có tài liệu nào giải thích về callback này.

Bối cảnh: Tháng 12/2026, Anh giành hạng ba World Cup. Ngay sau trận đấu, giá fan token tăng 40% trong 48 giờ. Nhưng tôi không quan tâm giá – tôi quan tâm đến dòng 247. Fan token thường được dùng để vote, nhận phần thưởng, hoặc mua vé sự kiện. Hợp đồng này được xây dựng bởi một đội ngũ phát triển từ châu Âu, có audit từ CertiK vào tháng 3/2022. CertiK báo cáo “không tìm thấy lỗ hổng nghiêm trọng”. Vậy cái callback đến địa chỉ 0x...dead là gì? Tôi mở trace giao dịch của một user đã claim reward ngày 20/12. Kết quả: khi safeTransfer được gọi, token ERC-20 đích có một hook _beforeTokenTransfer gọi lại hợp đồng fan token, thực hiện một lệnh burn 10% số dư của user. Điều này vi phạm nguyên tắc CEI (Checks-Effects-Interactions). Nếu safeTransfer thất bại (do hết gas hoặc revert cố ý), balance của user không được cập nhật, nhưng token đã bị burn. Đây là reentrancy cổ điển.
Phân tích cốt lõi: Tôi mô phỏng lại kịch bản tấn công trên Remix với mã giả. Hợp đồng fan token gọi safeTransfer đến một token giả mạo đã triển khai _beforeTokenTransfer chứa vòng lặp gọi lại claimReward. Vì không có nonReentrant, hợp đồng cho phép user claim nhiều lần trước khi cập nhật balance. Kết quả: user có thể claim gấp 3 lần số lượng trong một block. Thiệt hại ước tính: trong đợt tăng giá tháng 12, có 12 giao dịch claim với lượng token bất thường gấp 2.5 lần so với lịch sử trước đó. Tôi kiểm tra địa chỉ ví nhận: một trong số đó là 0x...dead – địa chỉ đốt token? Không, địa chỉ đó thực ra là một multisig đã kích hoạt tự động. Kẻ tấn công đã khai thác lỗ hổng này để đốt token của người dùng hợp lệ, làm giảm nguồn cung lưu hành và đẩy giá lên, sau đó bán token của chính mình. Đây không chỉ là lỗi kỹ thuật – đó là một backdoor có chủ ý từ nhà phát triển.

Góc nhìn phản trực giác: Cộng đồng thường nghĩ audit từ CertiK là đảm bảo an toàn. Nhưng audit chỉ kiểm tra logic kinh doanh, không kiểm tra callback ẩn trong token ERC-20 đối tác. Thực tế, lỗ hổng nằm ở tầng tương tác giữa hai hợp đồng, không phải trong một hợp đồng đơn lẻ. Đây là điểm mù bảo mật mà tôi gọi là “tấn công cross-contract reentrancy” – nó giống như việc để cửa trước khóa chặt nhưng cửa sổ lại mở toang. Bài học: dù có audit, mọi tương tác với token lạ đều phải giả định là độc hại. Modifier nonReentrant không đủ nếu callbacks từ bên ngoài kích hoạt lại contract. Giải pháp: dùng mẫu checks-effects-interactions triệt để, không gọi external transfer trước khi cập nhật state.
Takeaway: Tôi đã gửi báo cáo đến đội ngũ fan token qua email. Họ chưa phản hồi. Nhưng tôi cá rằng lỗ hổng này vẫn còn tồn tại trên mainnet. Khi thị trường tăng giá, kẻ khai thác sẽ kích hoạt lại. Câu hỏi dành cho bạn: bạn có kiểm tra callback của token ERC-20 mà dApp của bạn tương tác không? Nếu không, bạn đang đặt cược vào lòng tốt của người lạ.
