Ich habe einen Vertrag, der ein Array von Strukturen deklariert, die in storage
.
Aus diesem Vertrag rufe ich eine Funktion in einem anderen Vertrag auf, der eine einzelne Struktur als Eingabe verwendet.
Um "Syntaxhindernisse" zu umgehen, übergebe ich stattdessen den Inhalt (Variablen) der Struktur.
Ich musste der Struktur ein paar weitere Variablen hinzufügen, und jetzt erhalte ich den folgenden Kompilierungsfehler:
Stapeln Sie zu tief, versuchen Sie, lokale Variablen zu entfernen.
Instinktiv glaube ich, dass die einzige Lösung darin besteht, die Struktur an die Funktion "per Adresse" zu übergeben.
Da ich das Array dieser Strukturen in zugewiesen storage
habe, denke ich, dass es machbar sein sollte.
Aber egal wie ich versuche es aufzuschreiben, ich bekomme immer wieder Fehler.
Wenn ich den Rückgabetyp als deklariere address
, erhalte ich den folgenden Kompilierungsfehler:
Rückgabeargumenttyp struct MyStruct storage ref kann nicht implizit in den erwarteten Typ address konvertiert werden.
Wenn ich den Rückgabetyp als deklariere MyStruct storage
, erhalte ich den folgenden Kompilierungsfehler:
Speicherort muss Speicher für öffentlich sichtbare Funktionen sein (entfernen Sie das Schlüsselwort „storage“).
Wenn ich den Rückgabetyp als deklariere MyStruct memory
, erhalte ich den folgenden Laufzeitfehler :
Statische Speicherauslastung von mehr als 32 Bytes angefordert.
Steht im Solidity-Standard irgendwo, dass dies nicht machbar ist?
Danke schön.
Instinktiv glaube ich, dass die einzige Lösung darin besteht, die Struktur an die Funktion "per Adresse" zu übergeben.
Sie können nicht auf die physikalischen Adressen von Speichervariablen zugreifen (wie Sie es mit C können), dies ist in Solidity nicht erlaubt. Der Adresstyp wird nur verwendet, um auf die Adressen anderer Konten (Vertrag oder extern) zu verweisen, und wird nicht verwendet, um auf Speicheradressen zu verweisen.
Eine Problemumgehung wäre die Verwendung eines intelligenten Vertrags zum Speichern Ihrer Daten anstelle einer Struktur. Auf diese Weise könnten Sie die Adresse des Smart Contracts weitergeben, anstatt die Daten weitergeben zu müssen. Ich habe unten ein Beispiel gepostet:
contract Person {
uint public age;
uint public weight;
function Person(uint _age, uint _weight) public {
age = _age;
weight = _weight;
}
}
contract PersonHolder {
address[] public people; // Could use Person[] here
function addPerson(uint age, uint weight) public {
people.push(new Person(age, weight));
}
function getPerson(uint index) public view returns (Person) {
require(people.length > index);
return Person(people[index]);
}
}
struct
durch ein contract
... Das ist interessant; Ich werde es versuchen, danke!!!struct
wurde implizit ein Konstruktor für mich "erzeugt". Muss ich es wirklich explizit deklarieren, wenn ich zu a wechsle contract
?Person person
, und ich möchte darauf zugreifen age
, dann muss ich verwenden person.age()
. Dies könnte zu einer Art Laufzeitauswirkung führen, die ich jetzt untersuchen muss. 2. Der Compiler zwingt mich, den Funktionsmodifikator von in zu pure
ändern view
. Irgendeine Idee warum?returns (Person)
- gibt sie einen Verweis auf dieses Objekt im people
Array zurück oder gibt sie eine Kopie davon zurück (was meiner Meinung nach dazu führen würde, das ursprüngliche Objekt in den Stapel zu kopieren, bevor die Funktion aufgerufen wird)? Da Ihre Lösung den Stack too deep
Fehler, den ich zuvor erhalten hatte, aufgehoben hat, glaube ich, dass ersterer richtig ist (dh das Person
Objekt wird per Referenz zurückgegeben ). Kannst du das irgendwie bestätigen? Danke schön!!!returns (Person)
ich eigentlich eine Adresse in Form einer Vertragsreferenz zurück. Sie könnten dies auch tun returns (address)
, aber Sie müssten die Adresse als Person-Vertragsreferenz umwandeln, um nativ auf ihre Methoden zugreifen zu können. Es freut mich, dass ich Ihnen helfen konnte :-)Pure functions can only be used when contract state is not read
- aber dies ist der Status eines anderen Vertrags (dh nicht des Vertrags, in dem sich die Funktion befindet). Warum kann die Funktion pure
dann nicht sein? Wird nicht pure
behauptet, dass die Funktion nur in Bezug auf den "Besitzer"-Vertrag "rein" ist?Ich kann dein Problem vielleicht nicht ganz nachvollziehen. Aber aus meiner Erfahrung und vielen Recherchen im Internet:
Zum Beispiel habe ich einen Vertrag, der einen anderen Vertrag aufruft, einige Variablentypen können auf diese Weise nicht zurückgegeben werden (aber mit einem externen Aufruf, wie einem web3js-Aufruf). Dazu gehören "tiefe" Typen wie Strukturen.
Hinweis : Dies ist keine offizielle Aussage, nur einige Dinge, die ich aus Erfahrung / Lesen habe. Wenn jemand eine offizielle Dokumentation hat, geben Sie bitte eine andere korrekte Antwort ein :)
MyStruct[10][20] private myStructLists
.Stack too deep, try removing local variables
Ihre Antwort führt mich zu dem Schluss, dass ich das ursprüngliche Problem ( ) mit einem anderen Ansatz
lösen müsste . Irgendeine Idee außer dem Offensichtlichen, die in diesem Fehler ausdrücklich erwähnt wird?uint256
akzeptiert und innere Funktionsaufrufe durchführt, was schließlich zu einer Stapelnutzung führt, die über dem zulässigen Limit liegt.
Gregor Jeanmart
gute Stimmung
Harry Wright
gute Stimmung