Verschachtelte Strukturen mit Mappings im Inneren

Ich habe folgenden Code:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2; 

contract VenueRegistry{
    struct Queue{
        uint head;
        uint tail;
        mapping(uint => address) queue;
    }

    struct Venue{
        uint id;
        Queue queue;
    }

    mapping (uint => Venue) public venues;

}

Ich bekomme folgenden Fehler:

TypeError: Interner oder rekursiver Typ ist für öffentliche Zustandsvariablen nicht zulässig. Mapping (uint => Venue) öffentlicher Veranstaltungsorte;

Also habe ich das venuesPrivate gemacht und einen Getter geschrieben:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2; 

contract VenueRegistry{
    struct Queue{
        uint head;
        uint tail;
        mapping(uint => address) queue;
    }

    struct Venue{
        uint id;
        Queue queue;
    }

    mapping (uint => Venue) venues;

    function getVenue(uint _index) public view returns(Venue memory){
        return venues[_index];
    }
}

Dann bekomme ich folgenden Fehler:

Nur Bibliotheken dürfen den Zuordnungstyp in öffentlichen oder externen Funktionen verwenden.

Das Problem scheint bei der Zuordnung innerhalb von zu liegen struct Queue. Wenn ich das Mapping entferne, funktioniert es. Gibt es eine Möglichkeit, verschachtelte Strukturen mit Zuordnungen darin zu haben?

Antworten (1)

Das Problem ist Ihre Verwendung von publicmit inkompatiblen Datenstrukturen an zwei Stellen.

Zuerst diese Zeile:

pragma solidity >=0.4.22 <0.7.0;

Es macht es unmöglich, Ihre Ergebnisse zu replizieren, da niemand sicher ist, welchen Compiler Sie verwenden. Aus diesem Grund ist es gut, in einem Hauptvertrag konkret zu sein, um eine bestimmte Version zu erzwingen. Es ist in Ordnung, wenn geerbte Verträge, Bibliotheken usw. mehr Flexibilität haben, da der Hauptvertrag das Problem immer noch erzwingt.

Ich habe Solc 6.6 verwendet.

In Zeile 16:

publicmacht mehrere Dinge mit einer Zustandsvariablen. Es ist alles oder nichts – sehr praktisch, wenn Sie sie alle wollen, aber Sie können Dinge manuell codieren, wenn Sie nicht alles wollen. Eines dieser Dinge ist ein "freier" Getter, der wie folgt aussieht function variable(args) public returns(....

Es funktioniert mit skalaren Variablen, Arrays und Mappings, uint public x;ist also in Ordnung und uint[] public x;ist in Ordnung, aber myComplexStructWithMoreIndexedStuff[] public x;nicht kompatibel. Zusammenfassend liegt dies daran, dass der Compiler nicht sicher ist, wie er den Getter für Sie erstellen soll.

Kein Problem. Machen Sie es einfach privat oder intern und codieren Sie Ihre eigene Getter-Funktion, um nach den Argumenten zu fragen, die Elemente abzurufen und eine Antwort zurückzugeben.

So:

mapping (uint => Venue) private venues;

In Zeile 18:

Auch hier publicversuchen Sie, eine Struktur mit einer darin enthaltenen Zuordnung zurückzugeben. Eine Struktur allein würde ausreichen, um in Verbindung mit ein Problem zu verursachen public.

Bei Strukturen, Arrays und Zuordnungen sind Funktionsargumente Speicherzeiger, d. h. eine 32-Byte-Referenz auf einen Speicherort, nicht die eigentlichen Daten. Dies funktioniert gut für interne und private Kontexte, in denen der Vertrag sich selbst vertraut. Speicherzeiger können jedoch nicht ein- oder ausgegeben werden.

Beachten Sie, dass das System nicht über die Daten iteriert, um eine langatmige Antwort über die Werte der Variablen zu erzeugen, und dies wahrscheinlich auch nie tun wird, da dies O(n)-Komplexität wäre – hohe CPU- und E/A-Aktivität in der Kette, was du willst nicht. Da es nicht alle Elemente eines Arrays und keinen einfachen Zeiger auf den Speicher zurückgeben kann, kann es nichts tun.

Sie könnten es umschreiben, um ein Element und alles, was dieses Element enthält, wie folgt zurückzugeben:

function getVenueQueueElement(uint id, uint row) public view returns(address) {
  return venues[id].queue[row];
}

Sie könnten eine bessere Datenstruktur in Betracht ziehen, um das Aufzählen der vorhandenen Veranstaltungsorte und Warteschlangenmitglieder zu erleichtern, damit Kunden keinen Unsinn und die Vertragsgegenstände anfordern sollten, wenn dies der Fall ist.

Werfen Sie einen Blick auf diese aktualisierte Erklärung und lesen Sie unbedingt Teil 1 und 2, um wirklich zu verstehen, was vor sich geht und welche Probleme behandelt werden: https://medium.com/robhitchens/solidity-crud-epilogue-e563e794fde

Es verwendet intern Speicherzeiger . Sie sind mysteriöse Dinge, also könnte dies helfen: https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

Ich hoffe es hilft.