智能合約設計模式

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

設計模式是許多開發場景中的首選解決方案,本文將介紹五種經典的智能合約設計模式并給出以太坊solidity實現代碼:自毀合約、工廠合約、名稱注冊表、映射表迭代器和提款模式。

1、自毀合約

合約自毀模式用于終止一個合約,這意味著將從區塊鏈上永久刪除這個合約。 一旦被銷毀,就不可能調用合約的功能,也不會在賬本中記錄交易。

現在的問題是:“為什么我要銷毀合約?”。

有很多原因,比如某些定時合約,或者那些一旦達到里程碑就必須終止的合約。 一個典型的案例是貸款合約,它應當在貸款還清后自動銷毀;另一個案例是基于時間的拍賣合約,它應當在拍賣結束后終止 —— 假設我們不需要在鏈上保存拍賣的歷史記錄。

在處理一個被銷毀的合約時,有一些需要注意的問題:

  • 合約銷毀后,發送給該合約的交易將失敗
  • 任何發送給被銷毀合約的資金,都將永遠丟失

為避免資金損失,應當在發送資金前確保目標合約仍然存在,移除所有對已銷毀合約的引用。 現在我們來看看代碼:

contract SelfDesctructionContract {public address owner;public string someValue;modifier ownerRestricted {require(owner == msg.sender);_;} // constructorfunction SelfDesctructionContract() {owner = msg.sender;}// a simple setter functionfunction setSomeValue(string value){someValue = value;} // you can call it anything you wantfunction destroyContract() ownerRestricted {suicide(owner);}
}

正如你所看到的, destroyContract()方法負責銷毀合約。

請注意,我們使用自定義的ownerRestricted修飾符來顯示該方法的調用者,即僅允許合約的擁有者銷毀合約。

2、工廠合約

工廠合約用于創建和部署“子”合約。 這些子合約可以被稱為“資產”,可以表示現實生活中的房子或汽車。

工廠用于存儲子合約的地址,以便在必要時提取使用。 你可能會問,為什么不把它們存在Web應用數據庫? 這是因為將這些地址數據存在工廠合約里,就意味著是存在區塊鏈上,因此更加安全,而數據庫的損壞可能會造成資產地址的丟失,從而導致丟失對這些資產合約的引用。 除此之外,你還需要跟蹤所有新創建的子合約以便同步更新數據庫。

工廠合約的一個常見用例是銷售資產并跟蹤這些資產(例如,誰是資產的所有者)。 需要向負責部署資產的 函數添加payable修飾符以便銷售資產。 代碼如下:

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(...)將觸發一個交易來部署子合約并返回該合約的地址。 由于工廠合約和資產合約之間唯一的聯系是變量address[] carAssets,所以一定要正確保存子合約的地址。

3、名稱注冊表

假設你正在構建一個依賴與多個合約的DApp,例如一個基于區塊鏈的在線商城,這個DApp使用了ClothesFactoryContract、GamesFactoryContract、BooksFactoryContract等多個合約。

現在想象一下,將所有這些合約的地址寫在你的應用代碼中。 如果這些合約的地址隨著時間的推移而變化,那該怎么辦?

這就是名稱注冊表的作用,這個模式允許你只在代碼中固定一個合約的地址,而不是數十、數百甚至數千個 地址。它的原理是使用一個合約名稱 => 合約地址的映射表,因此可以通過調用getAddress("ClothesFactory") 從DApp內查找每個合約的地址。 使用名稱注冊表的好處是,即使更新那些合約,DApp也不會受到任何影響,因為我們只需要修改映射表中合約的地址。

代碼如下:

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 1require(ver >= 1);ContractDetails memory info = registry[name];require(info.owner == msg.sender);// create info if it doesn't exist in the registryif (info.contractAddress == address(0)) {info = ContractDetails({owner: msg.sender,contractAddress: addr,version: ver});} else {info.version = ver;info.contractAddress = addr;}// update record in the registryregistry[name] = info;return true;}function getContractDetails(string name) constant returns(address, uint16) {return (registry[name].contractAddress, registry[name].version);}
}

你的DApp將使用getContractDetails(name)來獲取指定合約的地址和版本。

4、映射表迭代器

很多時候我們需要對一個映射表進行迭代操作 ,但由于Solidity中的映射表只能存儲值,并不支持迭代,因此映射表迭代器模式非常有用。 需要指出的是,隨著成員數量的增加,迭代操作的復雜性會增加,存儲成本也會增加,因此請盡可能地避免迭代。

實現代碼如下:

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

實現put()函數的一個常見錯誤,是通過遍歷來檢查指定的鍵是否存在。正確的做法是elements[key] == address(0)。雖然遍歷檢查的做法不完全是一個錯誤,但它并不可取,因為隨著keys數組的增長,迭代成本越來越高,因此應該盡可能避免迭代。

5、提款模式

假設你銷售汽車輪胎,不幸的是賣出的所有輪胎出問題了,于是你決定向所有的買家退款。

假設你跟蹤記錄了合約中的所有買家,并且合約有一個refund()函數,該函數會遍歷所有買家并將錢一一返還。

你可以選擇 - 使用buyerAddress.transfer()或buyerAddress.send() 。 這兩個函數的區別在于,在交易異常時,send()不會拋出異常,而只是返回布爾值false ,而transfer()則會拋出異常。

為什么這一點很重要?

假設大多數買家是外部賬戶(即個人),但一些買家是其他合約(也許是商業)。 假設在這些買方合約中,有一個合約,其開發者在其fallback函數中犯了一個錯誤,并且在被調用時拋出一個異常,fallback()函數是合約中的默認函數,如果將交易發送到合同但沒有指定任何方法,將調用合約的fallback()函數。 現在,只要我們在refund函數中調用contractWithError.transfer() ,就會拋出異常并停止迭代遍歷。 因此,任何一個買家合約的fallback()異常都將導致整個退款交易被回滾,導致沒有一個買家可以得到退款。

雖然在一次調用中退款所有買家可以使用send()來實現,但是更好的方式是提供withdrawFunds()方法,它 將單獨按需要退款給調用者。 因此,錯誤的合約不會應用其他買家拿到退款。

實現代碼如下:

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

轉載于:https://my.oschina.net/u/3837977/blog/1808827

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390484.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何使用1Password,Authy和Privacy.com外包您的在線安全性

Take some work off your plate while beefing up security with three changes you can make today.通過今天可以進行的三項更改來增強安全性,同時省下一些工作。 Unstable times are insecure times, and we’ve already got enough going on to deal with. When…

「CodePlus 2017 12 月賽」火鍋盛宴

n<100000種食物&#xff0c;給每個食物煮熟時間&#xff0c;有q<500000個操作&#xff1a;在某時刻插入某個食物&#xff1b;查詢熟食中編號最小的并刪除之&#xff1b;查詢是否有編號為id的食物&#xff0c;如果有查詢是否有編號為id的熟食&#xff0c;如果有熟食刪除之…

5815. 扣分后的最大得分

給你一個 m x n 的整數矩陣 points &#xff08;下標從 0 開始&#xff09;。一開始你的得分為 0 &#xff0c;你想最大化從矩陣中得到的分數。 你的得分方式為&#xff1a;每一行 中選取一個格子&#xff0c;選中坐標為 (r, c) 的格子會給你的總得分 增加 points[r][c] 。 然…

您有一個上云錦囊尚未領取!

前期&#xff0c;我們通過文章《確認過眼神&#xff1f;上云之路需要遇上對的人&#xff01;》向大家詳細介紹了阿里云咨詢與設計場景下的五款專家服務產品&#xff0c;企業可以通過這些專家服務產品解決了上云前的痛點。那么&#xff0c;當完成上云前的可行性評估與方案設計后…

怎么從運營轉到前端開發_我如何在16個月內從銷售人員轉到前端開發人員

怎么從運營轉到前端開發On August 18, 2015, I was on a one-way flight headed to Copenhagen from Toronto Pearson Airport. I was starting my two semester exchange at the Copenhagen Business school. 2015年8月18日&#xff0c;我乘坐單程飛機從多倫多皮爾遜機場前往哥…

Python os.chdir() 方法

概述 os.chdir() 方法用于改變當前工作目錄到指定的路徑。 語法 chdir()方法語法格式如下&#xff1a; os.chdir(path) 參數 path -- 要切換到的新路徑。 返回值 如果允許訪問返回 True , 否則返回False。 實例 以下實例演示了 chdir() 方法的使用&#xff1a; #!/usr/bin/pyth…

oracle認證考試_Oracle云認證–通過此3小時免費課程通過考試

oracle認證考試This Oracle Cloud Certification exam will take – on average – about one week of study to prepare for. Most people who seriously commit to their studies are ready to pass the exam within about four days.這項Oracle Cloud認證考試平均需要大約一…

git 修改遠程倉庫源

自己已經寫好了一個項目&#xff0c;想上傳到 github github 創建新項目 新建 README.md &#xff0c; LICENSE 本地項目添加 github 遠程倉庫源 不是git項目git remote add origin https://USERNAME:PASSWORDgithub.com/USERNAME/pro.git已是git項目&#xff0c;先刪除再添加 …

Docker 常用命令備忘錄

build鏡像docker build -t"name" . 復制代碼后臺運行docker run -d -i -t 14a21c118315 /bin/bash 復制代碼刪除鏡像docker image rmi -f 300de37c15f9 復制代碼停止運行的鏡像docker ps docker kill (id) 復制代碼進入鏡像docker attach 29f2ab8e517c(ps id) 復制…

mvp最小可行產品_最低可行產品–如何為您的項目建立MVP以及為什么要這樣做

mvp最小可行產品具有足夠功能的產品可以收集全面的定性反饋 (A product with just enough features to gather comprehensive qualitative feedback) Proof of concept, prototypes, wireframes, mockups… what actually constitutes a Minimum Viable Product (MVP)?概念驗證…

composer 更改為中國鏡像

composer 更改為中國鏡像 $ composer config -g repo.packagist composer https://packagist.phpcomposer.com 轉載于:https://www.cnblogs.com/love-snow/articles/8111410.html

人人都能學會的python編程教程(基礎篇)完整版

人人都能學會的python編程教程1&#xff1a;第一行代碼 人人都能學會的python編程教程2&#xff1a;數據類型和變量 人人都能學會的python編程教程3&#xff1a;字符串和編碼 人人都能學會的python編程教程4&#xff1a;關系運算符與循環 人人都能學會的python編程教程5&#x…

劍指 Offer 56 - I. 數組中數字出現的次數

一個整型數組 nums 里除兩個數字之外&#xff0c;其他數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間復雜度是O(n)&#xff0c;空間復雜度是O(1)。 示例 1&#xff1a; 輸入&#xff1a;nums [4,1,4,6] 輸出&#xff1a;[1,6] 或 [6,1] 示例 2&#xff1a…

表達愛意的程序_如何像程序員一樣表達愛意??

表達愛意的程序Today is Valentines Day! &#x1f60d; 今天是情人節&#xff01; &#x1f60d; How nice would it be if you sent a Romantic Message every hour to your loved one? But even better... 如果您每小時向您所愛的人發送一封浪漫的短信&#xff0c;那將有多…

工作中的小問題

1、a標簽的選擇問題 需要修改帶class的a標簽的hover的文字顏色&#xff0c;方式如下 <style>a.egHyperlink:hover{color:red;} </style> <a href"#" class"egHyperlink">smile</a> 復制代碼2、hr分割線 需要一條粉紅色的分割線&am…

More DETAILS! PBR的下一個發展在哪里?

最近幾年圖形學社區對PBR的關注非常高&#xff0c;也許是由于Disney以及一些游戲引擎大廠的助推&#xff0c;也許是因為它可以被輕松集成進實時渲染的游戲引擎當中&#xff0c;也許是因為許多人發現現在只需要調幾個參數就能實現具有非常精細細節的表面著色了。反正現在網絡上隨…

sql server 2008 身份驗證失敗 18456

雙擊打開后加上 ;-m 然后以管理員方式 打開 SQLSERVER 2008 就可以已window身份登錄 不過還沒有完 右鍵 屬性 》安全性 更改為 sql server 和 window身份驗證模式 沒有sql server登陸賬號的話創建一個 然后把-m去掉就可以用帳號登錄了 轉載于:https://www.cnblogs.com/R…

js 兩個方法

//js in_array方法function in_array(all,one) { for(i0;i<all.length;i) { if(all[i] one) return true; } return false; } //js in_array方法/*** 一維數組去重方法** param arr 需要去重數組* returns {Array} 返回已經去重數組*/function unique(arr) {var ret [];va…

敏捷數據科學pdf_如何將敏捷框架應用于數據科學項目

敏捷數據科學pdfIn this article, well discuss how agile principles and values can be applied to the way you approach data science projects.在本文中&#xff0c;我們將討論如何將敏捷性原則和價值觀應用于您處理數據科學項目的方式。 Project management methodologi…

劍指 Offer 56 - II. 數組中數字出現的次數 II

在一個數組 nums 中除一個數字只出現一次之外&#xff0c;其他數字都出現了三次。請找出那個只出現一次的數字。 示例 1&#xff1a; 輸入&#xff1a;nums [3,4,3,3] 輸出&#xff1a;4 示例 2&#xff1a; 輸入&#xff1a;nums [9,1,7,9,7,9,7] 輸出&#xff1a;1 限制…