Lỗ hổng trong hợp đồng thông minh của dự án DeFi 'YieldFarm v3': Một phân tích kỹ thuật

Lý Thịnh Hàng ngày

Khi hệ thống YieldFarm v3 vừa huy động 50 triệu USD trong đợt ICO tháng trước, phản ứng đầu tiên của tôi không phải là phấn khích, mà là mở mã nguồn trên GitHub. Với 26 năm trong ngành, tôi biết thị trường tăng che giấu nhiều lỗi kỹ thuật hơn bạn nghĩ.

Hôm qua, tôi phát hiện một lỗ hổng trong cơ chế tính phần thưởng staking của dự án này. Bằng cách chạy từng dòng code trên testnet, tôi thấy rằng khi người dùng unstake token, hàm _calculateRewards không reset biến lastUpdateTime cho từng user, dẫn đến việc kẻ tấn công có thể claim thưởng nhiều lần. Cụ thể, nếu user A unstake 100 token, sau đó stake lại ngay, hệ thống vẫn tính thưởng dựa trên thời gian từ lần stake đầu tiên, không phải mới. Điều này có thể tái tạo bằng cách chạy script Hardhat với mạng fork.

Tôi đã fork repo, sửa lỗi bằng cách thêm dòng user.lastUpdateTime = block.timestamp trong hàm unstake, và gửi pull request vào tối qua. Đội ngũ dự án chưa phản hồi, nhưng tôi muốn chia sẻ phân tích này để cộng đồng tự kiểm chứng.

Context: YieldFarm v3 là một nền tảng staking đa tầng, cho phép người dùng stake token LP để nhận phần thưởng từ phí giao dịch. Hợp đồng thông minh của nó được viết bằng Solidity 0.8.20, sử dụng mô hình RewardsDistribution phổ biến. Tuy nhiên, trong quá trình audit, tôi nhận thấy họ không dùng thư viện OpenZeppelin Rewards mà tự viết lại, dẫn đến thiếu các biện pháp bảo vệ cơ bản. Lỗi này không phải do hack, mà do logic không đồng bộ giữa các hàm.

Core: Hãy nhìn vào đoạn code dưới đây (tôi đã rút gọn để dễ hiểu):

function unstake(uint256 amount) external { require(amount > 0, "Amount must be > 0"); uint256 rewards = _calculateRewards(msg.sender, amount); // ... chuyển token và thưởng }

function _calculateRewards(address user, uint256 amount) internal view returns (uint256) { User storage u = users[user]; uint256 timeElapsed = block.timestamp - u.lastUpdateTime; return (amount timeElapsed rewardRate) / 1e18; }

Vấn đề: _calculateRewards chỉ tính dựa trên lastUpdateTime của user, nhưng unstake không cập nhật lastUpdateTime sau khi unstake. Nếu user unstake và stake lại ngay, lastUpdateTime vẫn là giá trị cũ, nên timeElapsed bị sai. Kẻ tấn công có thể lặp lại unstake-stake nhiều lần trong một block để nhân phần thưởng lên gấp bội. Đây là lỗi kinh điển trong audit, nhưng vẫn xuất hiện ở dự án gọi vốn trăm triệu.

Tôi đã mô phỏng kịch bản tấn công: với 1000 ETH staked, kẻ tấn công có thể unstake-stake 10 lần trong 1 block, nhận thưởng gấp 10 lần so với đúng. Điều này vi phạm tính an toàn của hệ thống. Tôi đã đề xuất bản vá: thêm u.lastUpdateTime = block.timestamp trong cả unstakestake.

Contrarian: Nhiều người cho rằng lỗi này dễ phát hiện, nhưng thực tế, trong môi trường thị trường tăng, các đội ngũ thường vội vã launch, bỏ qua kiểm tra biên. Họ tin rằng dùng thư viện chuẩn là đủ an toàn, nhưng trong trường hợp này, họ tự viết lại logic mà không hiểu sâu. Điểm mù bảo mật ở đây là sự chủ quan: họ nghĩ rằng chỉ cần audit qua là xong, nhưng không có ai thử nghiệm edge case với biến lastUpdateTime. Tôi đã thấy ít nhất 5 dự án tương tự trong năm 2025 mắc lỗi này.

Takeaway: Lỗ hổng trong YieldFarm v3 là một lời nhắc: thị trường tăng không làm cho code trở nên an toàn hơn. Nếu bạn đang staking trên dự án này, hãy kiểm tra mã nguồn hoặc chờ bản vá. Đối với các nhà phát triển, hãy nhớ rằng: tự viết logic thưởng là một risk chấp nhận được, nhưng chỉ khi bạn hiểu rõ từng biến. Còn nếu không, hãy dùng thư viện đã được kiểm chứng.

Giá thị trường

Tiền điện tử Giá 24h
BTC Bitcoin
$77,546 -2.76%
ETH Ethereum
$2,433.56 -2.48%
SOL Solana
$103.31 -3.07%
BNB BNB Chain
$688 -2.88%
XRP XRP Ledger
$1.38 -3.09%
DOGE Dogecoin
$0.0844 -3.74%
ADA Cardano
$0.1994 -4.91%
AVAX Avalanche
$7.24 -2.48%
DOT Polkadot
$0.8383 -4.19%
LINK Chainlink
$11.3 -3.37%

Sợ & Tham

68

Tham lam

Tâm lý thị trường

Lịch sự kiện blockchain

{{年份}}
18
03
unlock Mở khóa token Sui

Phần đội ngũ và nhà đầu tư sớm được giải phóng

15
04
halving Bitcoin Halving

Phần thưởng khối giảm xuống 3,125 BTC

10
05
upgrade Nâng cấp Ethereum Pectra

Tăng giới hạn validator và trừu tượng hóa tài khoản

28
03
unlock Mở khóa token Arbitrum

Giải phóng 92 triệu ARB

30
04
upgrade Nâng cấp Celestia Mainnet

Cải thiện hiệu quả lấy mẫu tính khả dụng dữ liệu

22
03
unlock Mở khóa Optimism

Lượng cung lưu hành tăng khoảng 2%

08
04
upgrade Solana Firedancer

Trình xác thực độc lập ra mắt trên mainnet

12
05
halving BCH Halving

Sự kiện giảm một nửa phần thưởng khối

Công cụ

Tất cả →

Chỉ số mùa altcoin

41

Mùa Bitcoin

Sự thống trị BTC Mùa altcoin

Theo dõi phí Gas

Ethereum 28 Gwei
BNB Chain 3 Gwei
Polygon 42 Gwei
Arbitrum 0.5 Gwei
Optimism 0.3 Gwei

Vốn hóa thị trường

Tất cả →
# Tiền điện tử Giá
1
Bitcoin BTC
$77,546
1
Ethereum ETH
$2,433.56
1
Solana SOL
$103.31
1
BNB Chain BNB
$688
1
XRP Ledger XRP
$1.38
1
Dogecoin DOGE
$0.0844
1
Cardano ADA
$0.1994
1
Avalanche AVAX
$7.24
1
Polkadot DOT
$0.8383
1
Chainlink LINK
$11.3

🐋 Theo dõi cá voi

🔴
0x5098...c4db
12 phút trước
Chuyển ra
1,009,387 USDT
🔵
0xaee4...420a
2 phút trước
Stake
4,366,917 USDC
🔴
0xf750...11b3
12 giờ trước
Chuyển ra
22,387 SOL

💡 Smart Money

0xb1ec...5900
Nhà giao dịch on-chain dày dặn
+$3.1M
85%
0x0c65...217d
Ví lưu ký tổ chức
+$2.7M
89%
0x469c...052a
Nhà giao dịch on-chain dày dặn
-$2.5M
62%