Solidity

msg.sender.call() 在 Solidity 中做了什麼?

  • October 23, 2018

您好正在瀏覽solidity文件。有一些我無法理解的程式碼,即使經過大量研究,我也無法找到一些令人滿意的輸出。程式碼如下:

contract Mutex {
 bool locked;
modifier noReentrancy() {
   require(!locked);
   locked = true;
   _;
   locked = false;
}

/// This function is protected by a mutex, which means that
/// reentrant calls from within `msg.sender.call` cannot call `f` again.
/// The `return 7` statement assigns 7 to the return value but still
/// executes the statement `locked = false` in the modifier.
 function f() public noReentrancy returns (uint) {
   require(msg.sender.call());
  return 7;
 }
}

有什麼msg.sender.call()作用?又來電f()了?如果是,那怎麼辦?

它呼叫匿名回退函式msg.sender

在典型的重入攻擊中,它就像一個withdraw函式在做msg.sender.call.value(1 ether)(). 然後呼叫者(智能合約)將再次呼叫該函式,因此是“重入”攻擊。在這個片段中,call似乎沒有做任何有用的事情,但它只是為了表明locked變數可以防止重入。

msg.sender.call()在上呼叫回退函式msg.sender

這是一個使用canBeAttacked函式擴展的範例。

contract Mutex {
 bool locked;
modifier noReentrancy() {
   require(!locked);
   locked = true;
   _;
   locked = false;
}

 function canBeAttacked() public returns (uint) {
   require(msg.sender.call.value(1 ether)());
  return 7;
 }

/// This function is protected by a mutex
 function f() public noReentrancy returns (uint) {
   require(msg.sender.call());
  return 7;
 }
}

從上面的程式碼中需要注意的兩件事。

  1. 攻擊者可以創建具有回退的合約

的:

// attacker fallback
function() {
 Mutex(msg.sender).canBeAttacked();
}

合約可以有另一個呼叫 的函式,canBeAttacked()這將不斷重新進入canBeAttacked()並每次向攻擊者發送 1 個乙太幣。(回退需要更多程式碼來避免無限循環和耗盡gas。)這是一個可重入攻擊的例子。

現在想像一個攻擊者合約有一個備份:

// attacker fallback
function() {
 Mutex(msg.sender).f();
}
  1. 當攻擊者呼叫f()時,攻擊者回退將失敗,因為lockedis true,所以require(!locked)會產生異常並恢復整個事務。

另請注意,這noReentrancy可以防止攻擊者呼叫f()並在攻擊者的備份中呼叫canBeAttacked. (但他們可以像上面的#1一樣攻擊。)

引用自:https://ethereum.stackexchange.com/questions/42521