Was macht msg.sender.call() in Solidity?

Hallo, ich habe Solidity-Dokumentation durchgesehen. Es gab einige Codes, die ich nicht verstehen konnte, selbst nachdem ich viel recherchiert hatte, konnte ich keine zufriedenstellende Ausgabe finden. Der Code lautet wie folgt:

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;
  }
}

Was msg.sender.call()bedeutet? ruft es f()wieder an? Wenn ja, wie dann?

Antworten (2)

Es ruft die anonyme Fallback-Funktion auf auf msg.sender.

Bei einem typischen Reentrancy-Angriff wäre es so etwas wie eine withdrawFunktion, die msg.sender.call.value(1 ether)(). Der Aufrufer (ein intelligenter Vertrag) würde die Funktion dann erneut aufrufen, daher der "Reentrancy" -Angriff. In diesem Snippet callscheint das nichts Nützliches zu tun, aber es ist nur dazu da, um zu zeigen, dass die lockedVariablen vor Wiedereintritt schützen.

Kommentare sind nicht für längere Diskussionen gedacht; diese Konversation wurde in den Chat verschoben .

msg.sender.call()ruft die auf auf msg.sender.

Hier ist ein Beispiel, das um eine canBeAttackedFunktion erweitert wird.

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;
  }
}

2 Dinge, die Sie aus dem obigen Code beachten sollten.

  1. Ein Angreifer kann einen Vertrag mit einem Fallback erstellen

von:

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

Der Vertrag kann eine andere Funktion haben, die aufruft canBeAttacked(), und diese wird immer wieder neu betreten canBeAttacked()und dem Angreifer jedes Mal 1 Ether senden. (Der Fallback benötigt mehr Code, um eine Endlosschleife und ein Auslaufen des Gases zu vermeiden.) Dies ist ein Beispiel für einen reentranten Angriff.

Stellen Sie sich nun einen Angreifervertrag vor, der einen Fallback von hat:

// attacker fallback
function() {
  Mutex(msg.sender).f();
}
  1. Wenn der Angreifer aufruft f(), schlägt der Angreifer-Fallback fehl, da , also lockedeine Ausnahme generiert und die gesamte Transaktion rückgängig macht.truerequire(!locked)

Beachten Sie auch, dass noReentrancyverhindert wird, dass ein Angreifer anruft f()und im Fallback des Angreifers canBeAttacked. (Aber sie können wie Nr. 1 oben angreifen.)

Sie haben nicht erklärt, warum überhaupt jemand die Fallback-Funktion des Absenders aufrufen möchte. Welchem ​​Zweck dient dies?
@LukeHutchison Sie haben Recht, dass man in fast allen Fällen die Fallback-Funktion nicht aufrufen möchte. Sie fragen sich vielleicht etwas Ähnliches, was ich mich gefragt habe, warum das Senden von Ether an einen Vertrag immer die Fallback-Funktion aufruft? ethereum.stackexchange.com/questions/1505/…