Schreiben in Vertragsstruktur über Funktionsparameter, Speicher vs. Speicher, "Speicher außerhalb des Speichers"

Dies ist mein erster Vertrag überhaupt (aufbauend auf einem eigenen Beispiel-Lernfall, den ich mir ausgedacht habe).

Angesichts dieses Vertrages (vereinfacht):

unit gEval = 0;

contract Group {
  struct Grp {
    string    name;
    uint      orgId;
    Contrib[] contribs;
  }

  struct Contrib {
     uint id;
     uint grpId;
     Evals[] evals;  
  }

  struct Eval {
    uint id;
    address evaluator;
    uint result;

  }


  function  evalContrib(Contrib c, uint res) public {
    require(msg.sender != c.contributor);

    Eval eval = Eval(gEval++,msg.sender, res);

    c.evals.push(eval);
  }
}

Ich bekomme :

Fehler: Member „push“ ist in struct Group.Eval memory[] memory außerhalb des Speichers nicht verfügbar. c.evals.push(eval); ^----------------^

Folgendes verstehe ich: Der Contrib cParam in der evalContribFunktion ist ein Speicherparameter, da es sich um einen Funktionsparameter handelt, während ich versuche, das aufzurufen, c.evals.push(eval)was storageich denke.

Ich habe mehrere Kombinationen von Zuweisungen storageoder memoryZeigern ausprobiert, konnte dies jedoch nicht lösen.

Wie kann ich so etwas umsetzen? Kann ich vielleicht nur eine Referenz nach Id bekommen, zB contribs[id].evals.push(eval)?

Hinweis: Mein Design ist möglicherweise völlig ineffizient für die Solidität (viele Strukturen mit Arrays), daher freue ich mich über jeden Vorschlag.

Ich habe nur Zeit für einen kurzen Kommentar. Es sieht so aus, als ob Sie auf diesem Weg sind. Die Strukturen sehen angemessen aus, aber es beginnt auseinanderzufallen, wenn auf die Daten in den Strukturen zugegriffen wird. „Kaninchenloch“-Warnung: Es ist eine ziemlich vollständige Beschreibung eines Musters, von dem ich denke, dass Sie es verwenden können: medium.com/@robhitchens/…
danke @RobHitchens, das sieht nach einem Weg für diesen Fall aus!

Antworten (1)

Sie sollten auf jeden Fall Rob Hitchens Empfehlung folgen.

Nun, um die Warnung zu beheben, sind ein paar Dinge zu beachten:

  • Sie können struct nicht in öffentlichen Funktionen verwenden, es ist eine Einschränkung in der ABI-Spezifikation (vielleicht wird es in einer zukünftigen Version unterstützt).
  • Sie können Push nur für Arrays im Speicher verwenden.

Wenn die Funktion nicht von außerhalb des Vertrags verwendet werden soll, können Sie sie als intern deklarieren, sodass Sie Strukturen übergeben können

Struct werden als Speicherreferenzen übergeben, aber Sie können den Speicherort mit Arbeitsspeicher oder Speicherung angeben.

function  evalContrib(Contrib storage c, uint res) internal {
    require(msg.sender != c.contributor);

    Eval memory eval = Eval(gEval++, msg.sender, res);

    c.evals.push(eval);
}