Aufruf einer Funktion aus einem als Argument übergebenen Vertrag

Ich versuche, ein DAPP mit zwei Verträgen zu erstellen, die Vermögenswerte generieren. Einer fungiert als "Fabrik" für die anderen Verträge. Von letzterem versuche ich, eine Funktion in der Fabrik aufzurufen, ohne ihre Adresse noch zu kennen, daher möchte ich sie als Argument übergeben. Dies führt zu einem Fehler in Remix, da dieser Vertrag offensichtlich noch nicht existiert.

Um die Situation zu vereinfachen, stellen Sie sich dieses Szenario in Remix vor (beide Verträge werden in dieselbe Datei geschrieben):

    contract AssetFactory{

    address[] deployedAssets;

      function createAsset(string name) public {
        address newAsset = new Asset(name);
        deployedAssets.push(newAsset);
        return newAsset;
      }

    }

    contract Asset{

     string name;

     function Asset(string name) public{
       name = name;
     }

     function ModifyAssetAndCreateNew(string name, address factory){
       factory.createAsset(name);
       name = name;
     }

   }

Irgendwelche Ideen oder andere Ansätze? Mir ist klar, dass die Idee hinter dem obigen Vertrag in diesem Beispiel nicht viel Sinn macht, aber ich habe versucht, es so kurz wie möglich zu halten.

Danke schön!

Antworten (2)

Es gab eine Reihe von Kompilierungsfehlern in Ihrem Beispielcode, aber sobald ich diese behoben und address factoryin geändert habe AssetFactory factory, scheint alles in Ordnung zu sein.

(Ich habe nur erraten, was nameSie in der Zeile gemeint haben factory.createAsset(name). Wenn Sie ein einfaches Beispiel erstellen, stellen Sie sicher, dass Sie es tatsächlich getestet haben.)

pragma solidity ^0.4.23;

contract AssetFactory {
    Asset[] deployedAssets;

    function createAsset(string name) public returns (Asset) {
        Asset newAsset = new Asset(name);
        deployedAssets.push(newAsset);
        return newAsset;
    }

}

contract Asset {
    string name;

    constructor(string _name) public {
        name = _name;
    }

    function modifyAssetAndCreateNew(string _name, AssetFactory factory) public {
        factory.createAsset(_name);
        name = _name;
    }
}
Dies löste das Problem, das ich hatte. Sorry für das blöde Beispiel. Du hast Recht, ich habe es nicht getestet, sondern nur schnell etwas zusammengestellt, um meinen Standpunkt zu verdeutlichen. Danke schön!

Nebenbei sind mir einige seltsame Vorgänge aufgefallen und ich fand einige Alternativen erwähnenswert.

  1. Die Assets können die Factory-Adresse automatisch ableiten.
  2. Sie können verhindern, dass jemand ein Asset bereitstellt, ohne die Factory zu verwenden, und das kann nützlich sein, um die Integrität sicherzustellen und Annahmen darüber zu schützen, was vor sich geht.
  3. Ich fand es seltsam, eine Funktion zum Erstellen von Assets in das Asset selbst einzufügen. Das kommt mir ein bisschen so vor, als würde ich das Auto bitten, Bestellungen für mehr Autos entgegenzunehmen. Nicht undenkbar, aber warum? In den meisten Fällen wäre es konsequenter, die Fabrik eine Fabrik und den Vermögenswert ein Ergebnis der Fabrik zu lassen.
  4. Ich habe den Konstruktor von Asset wieder auf den alten Stil geändert und die Warnung ignoriert, da viele Dinge nicht auf die gleiche Weise kompiliert werden, einschließlich der Verwendung der neuen Syntax.

Pragma Solidität 0.4.23;

  contract AssetFactory {
    Asset[] public deployedAssets;

  function createAsset(string name) public returns (Asset) {
    Asset newAsset = new Asset(name);
    deployedAssets.push(newAsset);
    return newAsset;
  }

  function isFactory() public pure returns(bool isIndeed) {
    return true;
  }
}

contract Asset {
  string public name;
  AssetFactory factory;

  event LogAsset(address sender, bool isFactory);

  function Asset(string _name) public {
    name = _name;
    factory = AssetFactory(msg.sender);
  }

  // this seems like a strange thing to want. Consider removing it.

  function modifyAssetAndCreateNew(string _name) public {
    factory.createAsset(_name);
    name = _name;
  }   
}
Danke für deinen Kommentar! Ich habe versucht, eine Art Wertschöpfungskette zu entwickeln, in der Vermögenswerte (Dinge wie eine Kuh oder ein Stück Holz) registriert und später verarbeitet werden können. Ich habe noch nicht viel Zeit damit verbracht, aber die einzige Möglichkeit, wie ich sah, dass dies funktioniert, bevor ich eine intelligente Antwort erhielt, bestand darin, das "übergeordnete Asset" zu ändern und sofort ein neues "untergeordnetes Asset" innerhalb derselben Funktion zu erstellen.
Mit der Lösung, die @smarx und Sie mir gegeben haben, könnte ich das Asset wahrscheinlich auch an eine neue ProcessAsset()-Funktion des AssetFactory-Vertrags übergeben. Auf diese Weise hätte AssetFactory immer noch die Kontrolle
Sie hätten wahrscheinlich Verträge für jede Anlageklasse und eine bidirektionale Bindung. Die Kuh würde den Besitzer aufzeichnen. Es könnte auch für Eigentümer nützlich sein, ein Buch über alle im Besitz befindlichen Vermögenswerte zu führen (andere Richtung).
Können Sie angeben, was Sie mit bidirektionaler Bindung meinen? Soweit ich weiß, wären Zuordnungen die einzig mögliche Lösung dafür, aber Sie können Zuordnungen nicht iterieren, was Ihre Idee, ein Buch über alle im Besitz befindlichen Vermögenswerte zu führen, sehr schwierig macht.
Beginnen Sie hier: medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a Das löst die grundlegenden Iterations- und MGT-Probleme, hier zusammengefasst. Hier zusammengefasst. ethereum.stackexchange.com/questions/13167/… . Für die Zwei-Wege-Bindung, medium.com/@robhitchens/…