Ist es möglich, den internen Speicher eines Smart Contracts in einen neuen Vertrag zu kopieren?

Angenommen, ich möchte meine eigene Version einer suicideVertragsfunktion mit erweiterter Funktionalität implementieren. Genauer gesagt möchte ich den internen Speicherstand des Vertrags auf eine neue Vertragsadresse kopieren, bevor ich ihn ungültig mache. Beispielsweise habe ich möglicherweise eine Zuordnung, die die Token der Benutzer speichert, und ich möchte, dass diese Informationen im neuen Vertrag verfügbar sind. Ich weiß, dass die delegatecallFunktion anderen Verträgen den Zugriff auf die Speicherung des Vertrags ermöglichen kann, aber was ist, wenn ich den ursprünglichen Vertrag beenden möchte.

Eine Möglichkeit, wie ich dachte, dies zu tun, besteht darin, dem Vertrag eine Funktion wie die folgende hinzuzufügen, in der ich explizit schreibe, welche Daten mit der Aufruffunktion kopiert werden sollen:

pragma solidity ^0.4.2;

contract Sample {
    uint public data;

    function setData(uint data_){
        data = data_;
    }

    function mySuicide(address newContract) {
        newContract.call(bytes4(sha3("setData(uint256)")), _n);
        suicide(newContract);
    }
}


contract NewContract {
    uint public data;

    function setData(uint data_){
        data = data_;
    }
}

Das obige Beispiel ist jedoch einfach, da es nur eine einfache Zahl übergibt.

Also meine Fragen sind:

  1. Kann ich eine komplexere Struktur wie eine Zuordnung (Adresse => Adresse) kopieren, ohne dass Ausnahmen aufgrund von Gaslimits ausgelöst werden?
  2. Gibt es einen anderen allgemeineren Ansatz?
  3. Ist es möglich, diese Kopie der Daten außerhalb der Kette zu erstellen?

Antworten (2)

Ja, das ist möglich, wenn Sie Ihren Vertrag upgradefähig machen.

Eine kurze Beschreibung des Ansatzes - Erstellen Sie die Vertragsdatenschicht als separaten Vertrag (DataStore) und gestalten Sie den Hauptvertrag so, dass Sie immer dann, wenn Sie Ihren Vertrag beenden, Ihren alten DataStore mit dem neuen Vertrag verknüpfen können.

Sie können diesen Blog von einem meiner Kollegen lesen , der die Aufrüstbarkeit von Smart Contracts beschreibt.

Sie können sich auch dieses Repo als Referenz ansehen , der Hauptvertrag hier ("Organization.sol") ist aktualisierbar.

Ich habe den Ansatz gesehen, die Daten vom Funktionsvertrag zu trennen. Auf diese Weise können Sie die Daten zwischen Verträgen teilen, die sie verwenden möchten.

Sie müssten Code in Ihren Vertrag und Datenvertrag schreiben, damit Sie als Eigentümer einen Vertragszugriff auf Ihre Daten genehmigen könnten.

contract MyDataContract {
    address contractOwner = msg.sender;

    mapping(address => bool) approvedAccess;   
    mapping(address => bytes) dataMap;

    function approveAccess(address _addressToApprove) {
        require(msg.sender==contractOwner);
        approvedAccess[_addressToApprove] = true;
    }

    function getData(address _userAddressData) returns(bytes data) {
        require(approvedAccess[msg.sender]);
        data = dataMap[_userAddressData];
    }

    function setData(address _userAddressData, bytes data) {
        require(approvedAccess[msg.sender]);
        dataMap[_userAddressData] = data;
    }
}

contract MyConsumerContract {
    address contractOwner;
    MyDataContract dataContract;

    function MyConsumerContract(address _dataContract) {
        contractOwner = msg.sender;
        dataContract = MyDataContract(_dataContract);
    }

    function doSomething() {
       bytes data = dataContract.getData(msg.sender);
       ...
       dataContract.setData(msg.sender, data);
    }
}

Sie können den Datenvertrag natürlich nach Belieben strukturieren und für bestimmte Daten feinere Details in Gettern und Settern angeben. Aber jetzt können Sie die Daten mit anderen Verträgen teilen, selbst nachdem Sie einen Vertrag zerstört haben, der früher darauf zugegriffen hat.

Nachdem ich dies gepostet hatte, wurde mir klar, dass Bytes ein dynamisches Array ist und daher nicht von einem aufrufenden Vertrag zu einem anderen Vertrag verbraucht werden kann. Sie können jedoch auch andere Datentypen verwenden.