Wie schränke ich eine Funktion in einem Vertrag so ein, dass sie nur von einem bestimmten Vertrag aufgerufen werden kann?

Erstens ist mir eine ähnliche Frage bekannt , aber diese Antwort ist nicht ausreichend.

Angenommen, ich habe einen Vertrag A bereitgestellt, dann stelle ich einige Zeit später einen weiteren Vertrag B bereit. Ich möchte sicherstellen, dass eine Funktion A.f1()in A nur von Vertrag B aufgerufen werden kann. Dazu implementiere ich eine Funktion register(address trusted_contract), um B bei A zu registrieren, die im Grunde die Adresse von B in einem Array in A speichert. Da ich A besitze, I Bin der einzige, der es anrufen kann, um eine Adresse zu registrieren.

Wenn B jetzt anruft , überprüfe ich A.f1()innerhalb von , ob es im Array enthalten ist, und entscheide, ob der Anruf bedient werden soll.f1()msg.sender

Ist dies der richtige Weg?

Wenn ja, habe ich noch eine Frage. Was hindert einen anderen Vertrag C daran, eine Nachricht zu senden und behauptet, dass es B ist? Mein Verständnis ist, dass ein Vertrag im Gegensatz zu einem externen Konto keinen privaten Schlüssel hat und daher keine Nachricht signieren kann. Wenn ja, wie verifiziert Empfänger A, dass der Anrufer Vertragspartner B ist und nicht ein schlechter Schauspieler C?

Antworten (2)

Ist dies der richtige Weg?

Ja, außer dass Sie anstelle eines Arrays eine Karte für eine effiziente Suche verwenden sollten.

Wenn ja, wie verifiziert Empfänger A, dass der Anrufer Vertragspartner B ist und nicht ein schlechter Schauspieler C?

Es gibt zwei Möglichkeiten, wie ein "Angreifer" handeln kann:

  1. Senden Sie eine Transaktion direkt an Ihren Vertrag A.
  2. Senden Sie eine Transaktion an einen Vertrag X (anders als Vertrag B), dann wird innerhalb des Vertrags X eine Nachricht an Ihren Kontakt A gesendet.

Innerhalb des Vertrags A sind zwei Eigenschaften verfügbar:

  • tx.origin- die externe Kontoadresse.
  • msg.sender- die externe Kontoadresse für Fall 1; Vertragsanschrift X für Fall 2.

msg.senderist das, was Sie überprüfen werden, um sicherzustellen, dass der Anruf von Vertrag B erfolgt.

In beiden Fällen kann sich der „Angreifer“ nicht als Vertrag B ausgeben:

  • für den 1. Fall müsste er die Transaktion mit dem privaten Schlüssel von Vertrag B signieren, der nicht existiert;
  • Für den zweiten Fall hat er keine Kontrolle, msg.senderweil er von der EVM gehandhabt wird : Wenn ein Nachrichtenanruf von Vertrag X erfolgt, muss die EVM msg.senderdie Adresse von Vertrag X festlegen.

Wenn also der „Angreifer“ die Transaktion nicht an Vertrag B sendet, kann er sich nicht als Vertrag B ausgeben.

Danke dir! Was in meinen Augen Angriff 2 war, und was Sie gesagt haben, hat meine Zweifel ausgeräumt. "er hat keine Kontrolle über msg.sender, weil es von der EVM gehandhabt wird"!

Ja, das ist richtig. Was ein Konto daran hindert, eine Transaktion als Vertrag B zu senden, ist, dass das Konto das private/öffentliche Schlüsselpaar benötigen würde, um die Transaktion unter der Identität des Vertrags zu signieren.