¿Es posible copiar el almacenamiento interno de un contrato inteligente a un nuevo contrato?

Supongamos que quiero implementar mi propia versión de una función de suicidecontrato con funcionalidad extendida. Más específicamente, quiero copiar el estado de almacenamiento interno del contrato a una nueva dirección de contrato antes de invalidarlo. Por ejemplo, puedo tener un mapeo que almacene los tokens de los usuarios y me gustaría que esta información esté disponible en el nuevo contrato. Sé que la delegatecallfunción puede permitir el acceso al almacenamiento del contrato a otro contrato, pero ¿qué pasa si quiero eliminar el contrato inicial?

Una forma en que pensé que esto se puede hacer es agregando una función en el contrato como la siguiente, donde escribo explícitamente qué datos quiero que se copien usando la función de llamada:

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_;
    }
}

Sin embargo, el ejemplo anterior es simple ya que solo pasa un número simple.

Entonces mis preguntas son:

  1. ¿Podré copiar una estructura más compleja, como un mapeo (dirección => dirección) sin que se generen excepciones debido al límite de gas?
  2. ¿Hay algún otro enfoque más general?
  3. ¿Es posible hacer esta copia de datos fuera de la cadena?

Respuestas (2)

Sí, puede hacerlo si hace que su contrato sea actualizable.

Una breve descripción del enfoque: cree DataLayer de contrato como un contrato separado (DataStore) y diseñe el contrato principal de tal manera que cada vez que vaya a eliminar su contrato, pueda vincular su antiguo DataStore al nuevo contrato.

Puede leer este blog de uno de mis colegas que describe la capacidad de actualización del contrato inteligente.

Además, puede echar un vistazo a este repositorio como referencia, el contrato principal aquí ("Organización.sol") es actualizable.

He visto el enfoque de separar los datos del contrato funcional. De esta forma puedes compartir los datos entre los contratos que quieran utilizarlos.

Deberá escribir un código en su contrato y contrato de datos para que usted, como propietario, pueda aprobar un contrato de acceso a sus datos.

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);
    }
}

Por supuesto, puede estructurar el contrato de datos como desee y proporcionar detalles más precisos en captadores y definidores para datos particulares. Pero ahora puede compartir los datos con otros contratos, incluso después de destruir un contrato que solía acceder a ellos.

Después de publicar esto, me di cuenta de que los bytes son una matriz dinámica y, por lo tanto, no pueden ser consumidos por un contrato de llamada a otro contrato. Sin embargo, puede utilizar otros tipos de datos.