Was ist der Unterschied zwischen „msg.sender“ und „tx.origin“?

Wenn beide im Hauptteil einer Solidity-Funktion verwendet werden, die den Status eines Vertrags ändern kann (Schreibaufruf), was ist der Hauptunterschied und / oder Vorteil der Verwendung einer Funktion gegenüber der anderen? Zum Beispiel:

   function setOwner() {
      owner = msg.sender;
   }

vs.

   function setOwner() {
      owner = tx.origin;
   }

Was ist der Unterschied?

Antworten (2)

Mit msg.senderdem Eigentümer kann ein Vertrag geschlossen werden.

Mit tx.origindem Eigentümer kann niemals ein Vertrag zustande kommen.

In einer einfachen Anrufkette A->B->C->D wird innerhalb von D msg.senderC und tx.originA sein.

msg.senderwegen der gebotenen Flexibilität bevorzugt. Darüber hinaus empfiehlt Vitalik für Serenity, auch wenn es eine Weile her ist, Folgendes zu vermeiden tx.origin: Wie mache ich mein DAPP „Serenity-Proof“?

Überlegen Sie sorgfältig, ob Sie wirklich jemals verwenden müssen tx.origin. Denken Sie daran, dass Sie möglicherweise nicht der einzige Nutzer Ihres Vertrags sind. Andere Personen möchten möglicherweise Ihren Vertrag verwenden und über einen von ihnen geschriebenen Vertrag damit interagieren.

Wenn der Ursprung in D wirklich erwünscht ist, dann könnte jede der Funktionen in den Verträgen B, C, D einen zusätzlichen Parameter annehmen, um den Ursprung weiterzugeben: A würde seine Adresse ( this) an B weitergeben, B würde den Wert an C weitergeben, und C würde es an D weitergeben.

BEARBEITEN: Um den Kommentar von @WBT unten hervorzuheben, muss ein Vertrag, der einen übergebenen Wert für den Ursprung verwendet, sehr vorsichtig sein, wie er den Ursprung verwendet: Jeder kann einen Wert übergeben, der nicht der wahre Ursprung ist.

Wenn Sie eine Brieftasche wie die Mist-Brieftasche verwenden, werden Sie tx.origin nicht verwenden wollen, wenn ich diese Erklärung richtig verstehe. Ich würde niemals nennenswerten Ether halten, es sei denn, es wäre in einer Multi-Sig-Wallet wie der Mist-Wallet.
Zustimmen! Code, der tx.origin verwendet, kann von einer Vertrags-Multi-Sig-Brieftasche wie Mist nicht „besessen“ werden.
Der Beispielcode von OpenZeppelin hat „address public owner“, was bedeutet, dass jeder die Adresse des Vertragseigentümers abrufen kann. Kann ein Wallet (Hacker) jemals msg.sender fälschen, um sich als Eigentümer auszugeben?
@Curt Der praktikable Weg, sich als msg.sender auszugeben, besteht darin, ihren privaten Schlüssel zu haben. ohne den privaten Schlüssel ist es rechnerisch nicht durchführbar.
Die Übergabe der Ursprungsadresse als Parameter sollte niemals aus Sicherheitsgründen verwendet werden (z. B. "diese Aktion nur zulassen, wenn die übergebene Adresse der Vertragsinhaber ist / bestimmte Rechte hat"), da dies leicht zu spoofen ist: Ein Angreifer kann es einfach herausfinden die richtige Adresse zum Übergeben (z. B. Aufrufen von owner()) und übergeben Sie diese als Parameterwert. Sie möchten nicht, dass Sie dem Aufrufer Berechtigungen erteilen, die den Nachweis erfordern sollten, dass der Akteur den mit der Adresse verknüpften privaten Schlüssel besitzt (wie beim direkten Lesen von msg.sender, nicht über einen übergebenen Parameter).

msg.sendergibt den direkten Absender der Nachricht an, also zum Beispiel einen Vertrag, der sie weitergegeben hat.

tx.origingibt die Herkunft der Transaktionen an, also die Benutzeradresse, von der sie ursprünglich gesendet wurden. In der Praxis wird dies immer ein Benutzer sein, daher gilt die Antwort von eth.