?
?蘇澤
大家好 這里是蘇澤 一個鐘愛區(qū)塊鏈技術(shù)的后端開發(fā)者
本篇專欄?←持續(xù)記錄本人自學兩年走過無數(shù)彎路的智能合約學習筆記和經(jīng)驗總結(jié) 如果喜歡拜托三連支持~
總而言之,智能合約實現(xiàn)上要達到的目標是:完備的業(yè)務(wù)功能、精悍的代碼邏輯、良好的模塊抽象、清晰的合約結(jié)構(gòu)、合理的安全檢查、完備的升級方案。?
經(jīng)典的5種設(shè)計模式
1、自毀合約
1、自毀合約:
合約自毀模式用于終止一個合約,從區(qū)塊鏈中永久刪除該合約,無法調(diào)用合約功能或記錄交易。常見用例包括定時合約或必須在達到里程碑時終止的合約。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
contract SelfDesctructionContract { public address owner; public string someValue; modifier ownerRestricted { require(owner == msg.sender); _; } // constructor function SelfDesctructionContract() { owner = msg.sender; } // a simple setter function function setSomeValue(string value){ someValue = value; } // you can call it anything you want function destroyContract() ownerRestricted { suicide(owner); } } |
正如你所看到的,?destroyContract()
方法負責銷毀合約。
請注意,我們使用自定義的ownerRestricted
修飾符來顯示該方法的調(diào)用者,即僅允許合約的擁有者 銷毀合約。
2、工廠合約
工廠合約用于創(chuàng)建和部署子合約(資產(chǎn)),存儲子合約地址以確保安全性和防止數(shù)據(jù)丟失。常用于銷售資產(chǎn)并跟蹤資產(chǎn)所有者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
contract CarShop { address[] carAssets; function createChildContract(string brand, string model) public payable { // insert check if the sent ether is enough to cover the car asset ... address newCarAsset = new CarAsset(brand, model, msg.sender); carAssets.push(newCarAsset); } function getDeployedChildContracts() public view returns (address[]) { return carAssets; } } contract CarAsset { string public brand; string public model; address public owner; function CarAsset(string _brand, string _model, address _owner) public { brand = _brand; model = _model; owner = _owner; } } |
代碼address newCarAsset = new CarAsset(...)
將觸發(fā)一個交易來部署子合約并返回該合約的地址。 由于工廠合約和資產(chǎn)合約之間唯一的聯(lián)系是變量address[] carAssets
,所以一定要正確保存子合約的地址。
3、名稱注冊表
名稱注冊表模式通過合約名稱到地址的映射表,簡化了依賴多個合約的DApp的開發(fā)。通過固定一個合約地址,可以輕松查找合約地址,更新合約時不影響DApp的代碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
contract NameRegistry { struct ContractDetails { address owner; address contractAddress; uint16 version; } mapping(string => ContractDetails) registry; function registerName(string name, address addr, uint16 ver) returns (bool) { // versions should start from 1 require(ver >= 1); ContractDetails memory info = registry[name]; require(info.owner == msg.sender); // create info if it doesn't exist in the registry if (info.contractAddress == address(0)) { info = ContractDetails({ owner: msg.sender, contractAddress: addr, version: ver }); } else { info.version = ver; info.contractAddress = addr; } // update record in the registry registry[name] = info; return true; } function getContractDetails(string name) constant returns(address, uint16) { return (registry[name].contractAddress, registry[name].version); } } |
你的DApp將使用getContractDetails(name)
來獲取指定合約的地址和版本。
4、映射表迭代器
映射表迭代器模式解決了Solidity中映射表無法迭代的問題,通過將鍵值對存儲在數(shù)組中實現(xiàn)迭代操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
contract MappingIterator { mapping(string => address) elements; string[] keys; function put(string key, address addr) returns (bool) { bool exists = elements[key] == address(0) if (!exists) { keys.push(key); } elements[key] = addr; return true; } function getKeyCount() constant returns (uint) { return keys.length; } function getElementAtIndex(uint index) returns (address) { return elements[keys[index]]; } function getElement(string name) returns (address) { return elements[name]; } } |
實現(xiàn)put()
函數(shù)的一個常見錯誤,是通過遍歷來檢查指定的鍵是否存在。正確的做法是?elements[key] == address(0)
。雖然遍歷檢查的做法不完全是一個錯誤,但它并不可取, 因為隨著keys數(shù)組的增長,迭代成本越來越高,因此應(yīng)該盡可能避免迭代。
5、提款模式
提款模式用于退款操作,避免在退款過程中出現(xiàn)異常導致整個交易被回滾。建議使用withdrawFunds()方法單獨按需退款給調(diào)用者,而不是一次性退款給所有買家。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
contract WithdrawalContract { mapping(address => uint) buyers; function buy() payable { require(msg.value > 0); buyers[msg.sender] = msg.value; } function withdraw() { uint amount = buyers[msg.sender]; require(amount > 0); buyers[msg.sender] = 0; require(msg.sender.send(amount)); } } |
五種模式優(yōu)劣性解析: ?
自毀合約:自毀合約模式用于終止一個合約并從區(qū)塊鏈中永久刪除。這種模式常用于一次性合約或需要在特定條件下終止的合約。通過調(diào)用自毀函數(shù)(selfdestruct)并指定一個地址,合約的余額將被轉(zhuǎn)移到該地址,并且合約的代碼和存儲將被刪除。
工廠合約:工廠合約模式用于創(chuàng)建和部署子合約。工廠合約負責管理子合約的創(chuàng)建過程,并存儲子合約的地址以確保安全性和方便訪問。這種模式常用于創(chuàng)建多個相似的合約實例,例如創(chuàng)建代幣合約或其他可復(fù)制的資產(chǎn)。
名稱注冊表:名稱注冊表模式通過將合約名稱映射到地址的表來簡化依賴多個合約的去中心化應(yīng)用(DApp)的開發(fā)。通過使用注冊表合約,可以通過固定的合約地址輕松查找和更新合約,而不需要在DApp的代碼中硬編碼合約地址,從而提高了靈活性和可維護性。
映射表迭代器:Solidity中的映射表無法直接迭代,但通過映射表迭代器模式可以解決這個問題。該模式通過將鍵值對存儲在數(shù)組中,以特定的順序記錄映射表中的鍵,并提供函數(shù)來遍歷數(shù)組并返回鍵值對的詳細信息,從而實現(xiàn)對映射表的迭代操作。文章來源:http://www.zghlxwxcb.cn/news/detail-848839.html
提款模式:提款模式用于在合約中進行退款操作,以防止在退款過程中出現(xiàn)異常導致整個交易被回滾。通常建議使用提款模式時,將退款金額存儲在合約中,然后通過調(diào)用合約的withdrawFunds()方法,單獨按需退款給調(diào)用者,而不是一次性退款給所有的買家。這樣可以確保退款操作的可靠性,并避免因異常而導致整個退款過程失敗。文章來源地址http://www.zghlxwxcb.cn/news/detail-848839.html
到了這里,關(guān)于設(shè)計模式:智能合約的經(jīng)典設(shè)計模式及解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!