Supongamos que quiero implementar mi propia versión de una función de suicide
contrato 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 delegatecall
funció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:
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.
Ian Pilipski