中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用以太坊solidity實現智能合約設計模式

發布時間:2022-01-15 15:02:34 來源:億速云 閱讀:89 作者:iii 欄目:互聯網科技

這篇文章主要介紹“怎么用以太坊solidity實現智能合約設計模式”,在日常操作中,相信很多人在怎么用以太坊solidity實現智能合約設計模式問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用以太坊solidity實現智能合約設計模式”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1、自毀合約

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

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

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

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

  • 合約銷毀后,發送給該合約的交易將失敗

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

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

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修飾符來顯示該方法的調用者,即僅允許合約的擁有者銷毀合約。

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 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中的映射表只能存儲值,并不支持迭代,因此映射表迭代器模式非常有用。 需要指出的是,隨著成員數量的增加,迭代操作的復雜性會增加,存儲成本也會增加,因此請盡可能地避免迭代。

實現代碼如下:

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

到此,關于“怎么用以太坊solidity實現智能合約設計模式”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武宣县| 伊金霍洛旗| 深州市| 河津市| 扎鲁特旗| 鲁甸县| 丹棱县| 仁寿县| 仪陇县| 宜城市| 和平区| 莲花县| 高邮市| 渑池县| 鸡东县| 曲阳县| 芜湖县| 宁波市| 清镇市| 锦屏县| 始兴县| 永年县| 清新县| 马边| 安徽省| 隆昌县| 巴楚县| 浑源县| 衡阳市| 错那县| 峨边| 门头沟区| 吉林省| 肇州县| 扎兰屯市| 绥阳县| 奉化市| 碌曲县| 舟曲县| 龙川县| 庄河市|