什麼是重入攻擊?
當合約正在執行某函數時,攻擊者可以通過各種方式反復調用該函數。由於合約狀態存在依賴,反復調用會破壞預期邏輯。例如合約在轉賬前,減少用戶餘額;在轉賬後,增加接收者餘額。攻擊者在餘額減少時反復調用合約,就可以多次減少餘額。
防止重入攻擊的方法:
在函數執行前設置狀態變量防重入。
避免外部合約調用。可通過介面定義安全的調用方式。
使用互斥鎖 (Mutex) 防止同時調用衝突函數。
避免代幣 approve 後直接調用 transferFrom,應在兩步之間檢查 approve 額度。
代碼示例:
// 使用互斥鎖來防止重入
Mutex mutex;
function withdraw(uint amount) external {
require(!mutex.locked());
mutex.lock();
msg.sender.call.value(amount)();
mutex.release();
}
// 使用狀態變量來防止重入
uint256 protecting;
function withdraw() external {
require(protecting == 0);
protecting = 1;
msg.sender.transfer(balance[msg.sender]);
protecting = 0;
}