Wie kann die Bibliothek den Status ändern?

Ich habe sehr interessante Fälle über Bibliotheken.

FALL 1:

Ich habe in den offiziellen Solidity-Dokumenten Folgendes gelesen:

Bibliotheksfunktionen können nur dann direkt (dh ohne Verwendung von DELEGATECALL) aufgerufen werden, wenn sie den Zustand nicht verändern (dh wenn sie Ansichts- oder reine Funktionen sind), weil Bibliotheken als zustandslos angenommen werden

Ich bin sicher, sie meinen, Bibliotheken mit der Verwendung von auf der Adresse aufzurufen, .callund sie sagen, dass dies nur möglich wäre, wenn die Funktion der Bibliotheken wäre pure/view. Lassen Sie mich das wiederholen, a), b), c)was ich nicht verstehe.

a) Im kopierten Satz heißt es: if they do not modify the state. Ich bin mir nicht sicher, wie die Bibliothek den Status überhaupt ändert. es hat kein eigenes und alles, was es tun kann, ist den Wert der übergebenen Variablen zu ändern.

b) Ich habe versucht, es mit zu verwenden addr.call, aber ich habe keine Funktionen als angegeben, pure/viewund es ließ mich dies trotzdem tun. Es ist interessant, warum es mich gelassen hat, da in den Dokumenten steht, dass es zurückgesetzt werden sollte.

c) Warum sollte ich jemals Bibliotheken mit dem aufrufen wollen .call? Dies macht nur den ganzen Zweck von Bibliotheken zunichte.

**D) ** Wenn ich internalFunktionen für Bibliotheken verwende, scheint der Bibliothekscode in der kompilierten Version des Vertrags zu landen. Irgendein Grund, warum das gut ist? Wenn dem so wäre, hätte ich einen anderen Vertrag anstelle von Bibliothek verwendet.

Fall 2:

In der Dokumentation ist es wirklich ein schlechtes Beispiel, wie es den Referenztyp übergibt. Nehmen wir an, ich habe eine Bibliothek:

// Let's say this was written by third-party and it's put on github.

library libraryContract {
   
   function libraryTest(){

   }

}

// I can import the above here.

// import "libraryContract.sol";

contract myContract {
   
   function contractTest(){
      // I call it. This will work. Now, let's say in this contract, I
      // have a variable called `uint x = 0;`. and what libraryContract 
      // should be doing is change the value of the passed argument. 
      // If I pass `x` here directly, and change the argument in 
      //`libraryTest`, It still doesn't work since it's not passed by 
      //reference or something. Another case is What If I want my library 
      //to be changing the struct's properties, but library doesn't see 
      //the definiton of struct. 
      libraryContract.test(); 
   }

}

Einmal bereitgestellte Bibliotheken sind wie jeder andere Vertrag. AFAIK gibt es nichts, was jeden Benutzer daran hindert, die Funktionen aufzurufen. Die internen Funktionen sollen innerhalb desselben Vertrags aufgerufen werden, sodass sie von einem anderen Vertrag aufgerufen werden können, was den Zweck, intern zu sein, zunichte macht. Bibliotheken eignen sich gut zum Organisieren des Codes, weisen jedoch einige Einschränkungen auf. Wenn die Solidity-Dokumentation nicht klar ist, würde ich vorschlagen, Solidity-Entwickler zu fragen.

Antworten (3)

a) Im kopierten Satz heißt es: wenn sie den Zustand nicht ändern. Ich bin mir nicht sicher, wie die Bibliothek den Status überhaupt ändert. es hat kein eigenes und alles, was es tun kann, ist den Wert der übergebenen Variablen zu ändern.

Eine Bibliothek kann den Status eines Aufrufvertrags durch einen Delegiertenaufruf ändern. In diesem Fall wird die Funktion so ausgeführt, als ob sie direkt im aufrufenden Vertrag geschrieben wäre. Dies bedeutet, dass es theoretisch jeden Teil des Zustands des aufrufenden Vertrags ändern kann, solange die entsprechenden Variablen in der Bibliothek deklariert wurden (aber nicht initialisiert wurden, da die Bibliothek keinen eigenen Zustand hat). Was die Dokumente sagen, ist, dass, wenn Sie versuchen, eine solche Funktion direkt aufzurufen, sie fehlschlagen wird, da sie nicht dazu bestimmt ist, ihren eigenen Speicher zu ändern/zu modifizieren (weil kein solcher Speicher vorhanden ist), sondern den entsprechenden Speicher in einem aufrufenden Vertrag .

b) I tried using it with addr.call, but I didn't specify functions as pure/view and it still let me do this. It's interesting why it let me since in the docs, it says it should revert.

Das Markieren einer Funktion als pure/ viewist nicht obligatorisch. Solange die Funktion also nicht tatsächlich versucht, den Status zu ändern, wird die Transaktion nicht zurückgesetzt.

c) Why would I ever want to call libraries with the .call ? This just defeats the whole purpose of libraries.

Eine Bibliothek kann verwendet werden, um den Status eines aufrufenden Vertrags zu ändern (über delegatecall), aber sie kann sich auch wie eine Klasse mit statischen Methoden verhalten. Nehmen wir zum Beispiel an, Sie benötigen immer wieder vertraute Konstanten oder Methoden in Ihren Verträgen ( uint pi, uint days_in_year function n_squared(uint n), usw.). Sie können sie in eine Bibliothek auslagern, um sie nicht in jeden Vertrag aufnehmen zu müssen, den Sie schreiben. Dann werden sie nur einmal auf der Blockchain gespeichert und die anderen Verträge nur calldann, wenn sie sie brauchen.

Danke Simon. Auch hier habe ich ein paar Punkte.
1). Du sagst: not initialised. Das bedeutet, dass das Einzige, was ich in die Bibliothek einfügen kann, struct ist, denn wenn ich ints oder array oder irgendetwas anderes einfüge, bedeutet dies, dass sie standardmäßig initialisiert werden. 3). Es scheint so zu sein, dass das Beispiel, das Sie hervorgebracht haben, n_squaredauch einfach durch Hochladen eines Vertrags anstelle einer Bibliothek und dann durch Verwenden seiner Funktionen erreicht werden kann. Außerdem könnte ich die Methode des Vertrags mit meiner eigenen aufrufen delegatecall. Also, ich sehe vielleicht immer noch kein großes Bild

Es scheint, als würde der Bibliothekscode in der kompilierten Version des Vertrags landen, wenn ich interne Funktionen für Bibliotheken verwende

Eine Anwendung dafür ist wiederverwendbarer Code. Beispielsweise verwendet SafeMath interne Funktionen. Auf diese Weise a.add(b)führt es die Berechnung durch, wenn Sie dies tun, ohne eine delegatecall. Wenn a delegatecallverwendet werden sollte, werden die Berechnungen am Ende ziemlich teuer.

In Zukunft wird diese Verwendung von Bibliotheken jedoch aufgrund kostenloser Funktionen wahrscheinlich weniger verbreitet sein.


Ein einfaches Beispiel für die „Zustandsfrage“ wäre:

library L {
    function f() external {
        assembly {
            sstore(0, 1)
        }
    }
}

Wenn es also keinen Aufrufschutz gäbe, würden Sie in den Zustand der Bibliothek schreiben.

Bibliotheken sind zustandslos, sie können nur „konstante“ Werte speichern. Selbst wenn also ein Delegierter Anruf in der Bibliothek verwendet wird, kann der Status des Anrufervertrags nicht geändert werden.

Als ich zum Beispiel versuchte, die folgende Bibliothek zu erstellen, gab es diesen Fehler:

von solidity: TypeError: Bibliothek kann keine nicht konstanten Zustandsvariablen haben

library LibraryContract {

  uint storedTime;  

  function setTime(uint _time) public {
    storedTime = _time;
  }
}

Update: Es stellt sich heraus, dass diese Einschränkung aufgehoben wird, wenn sie wie in diesem Artikel erwähnt verwendet wird: https://dev.to/mudgen/solidity-libraries-can-t-have-state-variables-oh-yes-they-can-3ke9