Sind monolithische Smart Contracts besser als solche, die entkoppelt sind?

Die Smart-Contract-App, die ich schreibe, folgt dem, was ich für bewährte Verfahren halte – sie ist entkoppelt, sodass ein Controller-Vertrag einen Logikvertrag aufruft, der einen Speichervertrag aufruft. Also Contract AAnrufe Contract BAnrufe Contract C.

Ich frage mich jedoch, ob eine solche Entkopplung aus Sicherheitsgründen eine gute Idee für Smart Contracts ist. Das liegt daran, dass ich den onlyOwnerModifikator benötige, um festzulegen, wer meine Funktionen aufruft (wie hier beschrieben: https://github.com/ethereum/wiki/wiki/Solidity-Features ). Meiner Meinung nach wäre es toll, wenn ich so etwas machen könnte:

import "Owned.sol";

contract A is Owned {

   B private b;

   function A(address B) {
       b = B(b);
   }

   function myInterface() public onlyOwner {
       a.doStuff({from: msg.sender});
   }
}

contract B is Owned {

   C private c;

   function B(address c) {
       c = C(c);
   }

   function doStuff() public onlyOwner {
       c.store(42,{from: msg.sender});
   }
}

contract C is Owned {

   int private theAnswer;

   function store(int value) public onlyOwner {
       theAnswer = value
   }
}

Ich glaube jedoch, dass ich so nicht senden msg.senderkann. Wäre ich daher besser zu bündeln und Contract Ain einem einzigen monolithischen Vertrag, wo gültig ist ?Contract BContract Cmsg.sender

Warum machen Sie nicht einfach A zum Eigentümer von B und B zum Eigentümer von C?
@TjadenHess. Ich wollte gerade schreiben: "Ja, aber wie?" Aber eigentlich kann ich im Konstruktor die Adresse von A an B und von B an C übergeben und so den Besitzer zuweisen. Doh! Äh, ja - du hast Recht. Manchmal müssen diese Dinge nur gelüftet werden, um gelöst zu werden ;) Danke!
Eigentlich würde ich B im Konstruktor von A erstellen, anstatt die Adresse zu übergeben, und dann msg.senderim Konstruktor von B verwenden, um den Eigentümer festzulegen. Machen Sie dann dasselbe und erstellen Sie C aus dem Konstruktor von B heraus
@TjadenHess - schön - liegt das daran, dass B dann seine Instanz von C (zum Beispiel) ordnungsgemäß besitzt, anstatt ein bereits bereitgestelltes C zu besitzen (dessen Eigentümer möglicherweise inzwischen geändert wurde)?
Exakt. In einigen Fällen ist das vielleicht nicht das, was Sie wollen, aber es ist im Allgemeinen einfacher, über den Vertrag zu argumentieren, wenn er nicht mit einem willkürlichen Vertrag interagiert
Ich erinnere mich jetzt - ich habe es so gemacht, aber der Grund, warum ich das jetzt nicht tue, ist, dass mir die Gasbereitstellungsverträge ausgingen, die viele news machten. Aber ich weiß jetzt ein bisschen mehr, also werde ich nochmal nachforschen.
Wenn Ihnen das Benzin ausgeht, funktioniert auch die Übergabe der Adressen an den Konstruktor
@TjadenHess Also habe ich versucht , mich zu newnähern, und tatsächlich ist mir das Gas beim Ausbringen ausgegangen. Es braucht etwa 7M Gas. Daher muss ich Adressen weitergeben. Was ich oben leider nicht erkannt habe, ist, dass ich die Adresse von B nicht an C weitergeben kann, damit C B zu seinem Besitzer machen kann, da B zuerst die Adresse von C benötigt. Es gibt Möglichkeiten, das Eigentum an B zurückzuübertragen, aber sie sind alle ziemlich chaotisch. Das bringt mich zurück zum Titel meines ursprünglichen Beitrags: Bin ich besser dran, diese ganze Komplikation zu vermeiden, indem ich einfach alle meine erforderlichen Funktionen in einem einzigen Vertrag bündele? Ich hoffe nicht, dass es bessere Wege geben muss ...

Antworten (1)

In den Kommentaren zu Ihrem ursprünglichen Beitrag haben Sie festgestellt, dass die Bereitstellung eines großen monolithischen Vertrags aufgrund des Erreichens des Blockgaslimits scheitern kann. Eine DApp, die nicht bereitgestellt werden kann, kann nicht besser sein. :)


Zu den Lösungen: vielleicht verlängern Ownedauf Authablemit:

  • mapping (address => bool) public authorised
  • modifier onlyAuthed {...}
  • function authAdd (address _addr) public onlyOwner {...}
  • function authRem (address _addr) public onlyOwner {...}

... und dann Authed+ onlyAuthedanstelle von Owned+ onlyOwnerin abgeleiteten Dapps verwenden? ..

Sie könnten die Teile dann unabhängig voneinander bereitstellen. Sobald eine "vollständige Kette" vorhanden ist, die verknüpft werden kann (z. B. ), können Sie von Ihrem Konto aus A->B->C[several]anrufen .C.authAdd(<address-of-B>)owner

Das ist etwas mühsam, aber relativ einfach zu automatisieren. Darüber hinaus müssen Sie sich keine Gedanken über die Reihenfolge der Bereitstellung machen oder darüber, ob einige DApps nicht bereitgestellt werden können.

Das Schema kann an spezielle Bedürfnisse angepasst werden.


Alternativ könntest du Zeppelins Ownable und seine transfer()Funktion verwenden.

Dies würde gut funktionieren, wenn:

  • die "Eigentumskette" ist linear, dh kein Fall, in dem ein Dapp von mehreren anderen aufgerufen werden könnte; und
  • Das Beibehalten des ursprünglichen Eigentums (durch das bereitstellende Konto) ist nicht erforderlich (z. B. für Nuking-Zwecke).

BEARBEITEN:

Andererseits könnten Sie b = B(b)aus dem Konstruktor heraus zu einer separaten Funktion wechseln (wie function createChildren(...) public onlyOwner onlyOnce {...}) und eine Möglichkeit hinzufügen, die Anfrage an bereits erstellte Kinder weiterzugeben (wie function nagForGrandChildren(...) public onlyOwner {...}). Aber das Problem bleibt: Wenn nFGC()das Blockgaslimit erreicht wird, muss der Funktionsaufruf wiederholt werden – ausgelöst vom ursprünglichen externen ownerKonto von A.

Auf die eine oder andere Weise müssen Sie vorhersehen, dass ein Teil Ihrer Kette nicht bereitgestellt werden kann. Hier haben Sie die Wahl zwischen „etwas auf der Strecke“ oder „irgendwas dazwischen“.