什麼是重入攻擊?
當合約正在執行某函數時,攻擊者可以通過各種方式反復調用該函數。由於合約狀態存在依賴,反復調用會破壞預期邏輯。例如合約在轉賬前,減少用戶餘額;在轉賬後,增加接收者餘額。攻擊者在餘額減少時反復調用合約,就可以多次減少餘額。
防止重入攻擊的方法:
在函數執行前設置狀態變量防重入。
避免外部合約調用。可通過介面定義安全的調用方式。
使用互斥鎖 (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;
}
