Solidity
DApp 開發 - 如何更新 dapp 並保留現有數據
與分離應用程序和數據庫的 Web 應用程序相比,我們可以更新應用程序並保留現有數據。
你能建議我如何更新 dapp 並保留現有數據嗎?
DApp 唯一的數據源通常是智能合約程式碼和區塊鏈數據,沒有(集中式)數據庫或源。整個流程完全發生在客戶端和區塊鏈之間。升級你的 Dapp(前端)並不一定意味著你必須更新你的數據(智能合約)。根據 DApp 的託管位置,您可以重新部署它並仍然引用相同的智能合約。另一方面,智能合約一旦部署,就是不可變的。無法更新或刪除部署到網路的任何智能合約或交易。
有些模式可以幫助您將數據與業務邏輯分離,或幫助升級(替換)您的智能合約。在部署您的第一個契約之前,您需要預先為此進行設計。
永恆的儲存
一種常見的模式是使用永恆儲存。這是一個智能合約,僅包含數據、某種鍵/值儲存,沒有其他業務邏輯。這類似於更傳統的 Web 應用程序中的數據庫。
一個基本的例子
contract EternalStorage { mapping(bytes32 => uint) uIntStorage; function getUint(bytes32 _key) external view returns(uint) { return uIntStorage[_key]; } function setUint(bytes32 _key, uint _value) external { uIntStorage[_key] = _value; } function deleteUint(bytes32 _key) external { delete uIntStorage[_key]; } }
將儲存合約與業務邏輯分開可以讓您保留數據,同時仍然可以靈活地更改邏輯。
代理契約
另一種常見的方法是使用代理架構模式,它允許您使用新部署的合約,就好像您的主邏輯已升級一樣。所有消息呼叫都通過代理合約,該合約會將它們重定向到最新部署的合約邏輯。要升級,需要部署新版本的合約,並更新代理以引用新的合約地址。
一個基本的例子
contract Proxy { address delegate; address owner = msg.sender; function upgradeDelegate(address newDelegateAddress) public { require(msg.sender == owner); delegate = newDelegateAddress; } function() external payable { assembly { let _target := sload(0) calldatacopy(0x0, 0x0, calldatasize) let result := delegatecall(gas, _target, 0x0, calldatasize, 0x0, 0) returndatacopy(0x0, 0x0, returndatasize) switch result case 0 {revert(0, 0)} default {return (0, returndatasize)} } } }
這兩種模式通常結合起來,將業務邏輯與數據儲存分開,並允許通過代理合約升級業務邏輯。