900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 以太坊知识教程------智能合约的5种设计模式

以太坊知识教程------智能合约的5种设计模式

时间:2023-08-12 03:52:52

相关推荐

以太坊知识教程------智能合约的5种设计模式

1、自毁合约

合约自毁模式用于终止一个合约,这意味着将从区块链上永久删除这个合约。 一旦被销毁,就不可能调用合约的功能,也不会在账本中记录交易。

eg. 贷款合约,它应当在贷款还清后自动销毁;另一个案例是基于时间的拍卖合约,它应当在拍卖结束后 终止 —— 假设我们不需要在链上保存拍卖的历史记录。

在处理一个被销毁的合约时,有一些需要注意的问题:

合约销毁后,发送给该合约的交易将失败。任何发送给被销毁合约的资金,都将永远丢失。为避免资金损失,应当在发送资金前确保目标合约仍然存在,移除所有对已销毁合约的引用。

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

2、工厂合约

工厂合约用于创建和部署“子”合约。

工厂用于存储子合约的地址,以便在必要时提取使用。

为什么不把它们存在Web应用数据库里?将地址数据存在工厂合约里、存在区块链上,更加安全不会丢失。需要跟踪所有新 创建的子合约以便同步更新数据库。

eg. 销售资产并跟踪这些资产(例如,谁是资产的所有者)。 需要向负责部署资产的 函数添加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;}}

3、名称注册表

其实就是一个字符串map一个struct对象。使用场景: 假设一个合约依赖很多个合约,如果将所有这些合约的地址写在你的应用代码中,如果这些合约的地址随着时间的推移而变化,那该怎么办?

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

4、映射表迭代器

由于mapping迭代效率低,所以需要一个mapping迭代模式,答案就是通过一个数组来保存key。

注意:put()函数的一个常见错误“通过遍历来检查指定的键是否存在”。

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

5. 提款模式

简单来说,就是不用transfer,而是用send,因为一旦callback错误,transfer会导致异常,而send不会。

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。