Solidity
是否可以將智能合約的內部儲存複製到新合約中?
假設我想實現我自己的
suicide
具有擴展功能的合約函式版本。更具體地說,我想在無效之前將合約的內部儲存狀態復製到新的合約地址。例如,我可能有一個儲存使用者令牌的映射,並且我希望此資訊在新合約中可用。我知道該delegatecall
功能可以允許其他契約訪問契約的儲存,但是如果我想終止初始契約怎麼辦。我認為可以做到這一點的一種方法是在合約中添加一個如下所示的函式,在其中我使用呼叫函式明確寫入要複製的數據:
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_; } }
但是,上面的範例很簡單,因為它只傳遞了一個簡單的數字。
所以我的問題是:
- 我是否能夠複製更複雜的結構,例如映射(地址 => 地址)而不會因為氣體限製而引發異常?
- 還有其他更通用的方法嗎?
- 是否有可能使這個數據副本脫鏈?
是的,如果你讓你的契約可升級,你就可以做到這一點。
該方法的簡要說明 - 將合約的 DataLayer 創建為單獨的合約(DataStore),並以某種方式設計主合約,以便無論何時要終止合約,都可以將舊 DataStore 連結到新合約。
你可以從我的一位同事那裡閱讀這篇描述智能合約可升級性的部落格。
此外,您可以查看此repo以供參考,此處的主合約(“Organization.sol”)是可升級的。
我已經看到了將數據與功能契約分離的方法。通過這種方式,您可以在想要使用它的合約之間共享數據。
您需要在您的契約和數據契約中編寫程式碼,您作為所有者可以批准契約訪問您的數據。
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); } }
當然,您可以根據自己的喜好建構數據協定,並在特定數據的 getter 和 setter 中提供更詳細的資訊。但是現在您可以與其他合約共享數據,即使您破壞了曾經訪問它的合約。