Übergeben der Adresse einer Struktur, die in einem Vertrag im Speicher zugewiesen ist, an eine Funktion in einem anderen Vertrag

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 storagehabe, 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.

Hi. Ein Codebeispiel wäre großartig, um es leicht zu verstehen und Ihnen zu helfen
@GregJeanmart: Ich müsste etwa 2 oder 3 Verträge minimieren und sie dann hier einfügen.
Sie können einen Link zu einer Zusammenfassung posten, anstatt sie direkt hier einzufügen.
@HarryWright: Danke, aber ich habe die Chance aufgegeben, das ursprüngliche Problem (Stack-Usage) zu lösen, indem ich eine Speicherstruktur als Referenz übergebe, da es in Solidity nicht unterstützt zu werden scheint (na ja, nur für interne Funktionen von what Ich habe bisher gesammelt, aber ich mache hier Funktionsaufrufe zwischen Verträgen).

Antworten (2)

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]);
    }
}
Hmmm... Ersetze das structdurch ein contract... Das ist interessant; Ich werde es versuchen, danke!!!
PS: Für eine structwurde implizit ein Konstruktor für mich "erzeugt". Muss ich es wirklich explizit deklarieren, wenn ich zu a wechsle contract?
Ja, das ist richtig, Sie müssen einen Konstruktor für einen Vertrag schreiben.
OK, ein paar Anmerkungen zu Ihrer (funktionierenden) Lösung: 1. Wenn ich tatsächlich die Vertragsinstanz verwende, die an eine bestimmte Funktion übergeben wird, muss ich eine 'Getter'-Funktion für die Variable verwenden, auf die ich zugreifen möchte. Angenommen, eine Funktion nimmt 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?
Eine letzte Frage: In Bezug auf eine Funktion, die returns (Person)- gibt sie einen Verweis auf dieses Objekt im peopleArray 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 deepFehler, den ich zuvor erhalten hatte, aufgehoben hat, glaube ich, dass ersterer richtig ist (dh das PersonObjekt wird per Referenz zurückgegeben ). Kannst du das irgendwie bestätigen? Danke schön!!!
In Bezug auf die Auswirkungen auf die Laufzeit kostet der Getter für Personeneigenschaften, z. B. das Alter, kein Gas, da es sich um einen Aufruf und nicht um eine Transaktion handelt. Reine Funktionen können nur verwendet werden, wenn der Vertragsstatus nicht gelesen wird, Ansichtsfunktionen ermöglichen das Lesen des Vertragsstatus. Dabei gebe 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 :-)
Sehr hilfreich, danke!!! Eine "klebrige" Frage jedoch - 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 puredann nicht sein? Wird nicht purebehauptet, dass die Funktion nur in Bezug auf den "Besitzer"-Vertrag "rein" ist?
Die Dokumentation besagt, dass eine reine Funktion keine nicht reine Funktion aufrufen kann. Die generierte Getter-Funktion für den anderen Vertrag ist nicht rein, ich denke, das ist der Grund, warum Sie diese Operation nicht durchführen können.
Die Dokumentation besagt, dass eine reine Funktion keine nicht reine Funktion aufrufen kann. Die generierte Getter-Funktion für den anderen Vertrag ist nicht rein, ich denke, das ist der Grund, warum Sie diese Operation nicht durchführen können.
Ich habe festgestellt, dass Ihre Lösung im Grunde bedeutet, dass ich viele Verträge erstellen und bereitstellen werde. In meinem speziellen Fall - um 1100. In Bezug auf "Speicher" verbraucht es genau das gleiche wie die Verwendung eines Arrays von Strukturen. Aber werde ich für die Verwendung von Verträgen anstelle von Strukturen eine enorme „Strafe“ zahlen? Danke schön.

Ich kann dein Problem vielleicht nicht ganz nachvollziehen. Aber aus meiner Erfahrung und vielen Recherchen im Internet:

  1. 1: Solidity handhabt (für Entwickler) Objekte mit dynamischer Größe (wie Arrays, Strings) nicht sehr gut
  2. 2: Einige Typen können nicht von einem Vertragsaufruf zurückgegeben werden

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 :)

Mein Array von Strukturen ist nicht dynamisch: MyStruct[10][20] private myStructLists.
Ja, aber Ihre Strukturen sind zu "tief" (außerdem befinden sie sich in einem Array, also ist es noch tiefer :/ )
Stack too deep, try removing local variablesIhre 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?
Nicht wirklich. Ich versuche zu vereinfachen und mit den „grundlegendsten“ Typen zu arbeiten, wenn ich in Solidität codiere, also vermeide ich Strukturen, Arrays und so weiter.
Ändert nichts am Endergebnis des Problems, mit dem ich konfrontiert bin. Ich kann diese Strukturen und Arrays beliebig reduzieren, aber im Endeffekt habe ich eine Funktion, die ungefähr 9 Variablen vom Typ uint256akzeptiert und innere Funktionsaufrufe durchführt, was schließlich zu einer Stapelnutzung führt, die über dem zulässigen Limit liegt.
Mehr kann ich dir da nicht helfen, sorry. Mein Wissen ist nicht stark. Versuche es einfach selbst herauszufinden oder warte darauf, dass jemand Besseres als ich dir etwas vorschlägt :)