我编写两个智能合同是为了创建一个“智能资产”。这样做的想法是,一旦资产被使用,涉及资产的受益人将支付资产的使用价格。例如,四个当事方(设计师、原材料交付者、维护人员和装配人员)创建了一台洗衣机,然后创建了一份智能合同,一旦消费者使用洗衣机,就会向受益人支付费用。(想法是从浪费经济转向使用经济,并鼓励创造可持续的产品。)
SimpleSmartAssetManager是实例化智能资产的智能契约。SimpleSmartAsset是智能资产的表示。
我这样做是为了使受益人包括一个地址和一个重量。权重是受益人在使用资产时收到的使用价格的相对权重。当资产被使用时(通过在pay()上调用SimpleSmartAsset),将从用户中扣除使用的价格,并支付所增加的受益人的相对权重(其权重占总重量的百分比)。
SimpleSmartAssetManager有一个现有智能资产的列表。当使用智能资产时,管理器检索SimpleSmartAsset的特定实例的地址,并调用pay函数。所有调用都应通过合同所有者SimpleSmartAssetManager进行。
这是UML契约图:

当函数被调用时,一些事件被记录到块链中。
Mortal和Owned契约(因此契约具有onlyOwner修饰符,可以删除):
pragma solidity ^0.4.10;
contract Owned {
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
contract Mortal is Owned {
function remove() onlyOwner {
selfdestruct(owner);
}
}SimpleSmartAsset:
contract SimpleSmartAsset is Mortal {
uint usagePrice;
Beneficiary[] beneficiaries;
uint totalWeight; // to calculate percentage the beneficiaries receive
event AssetCreated(uint _usagePrice,
address[] addresses,
uint[] weights);
function SimpleSmartAsset(uint _usagePrice,
address[] addresses,
uint[] weights) {
owner = msg.sender;
usagePrice = _usagePrice;
uint beneficiaryCount = addresses.length;
for (uint i = 0; i < beneficiaryCount; i++) {
uint weight = weights[i];
addBeneficiary(addresses[i], weight);
totalWeight += weight;
}
AssetCreated(_usagePrice, addresses, weights);
}
function getUsagePrice() constant returns (uint) {
return usagePrice;
}
event BeneficiaryPaid(address addr, uint amount);
function pay() payable onlyOwner {
require(msg.value >= usagePrice);
uint beneficiaryCount = beneficiaries.length;
for (uint i = 0; i < beneficiaryCount; i++) {
Beneficiary memory beneficiary = beneficiaries[i];
uint weight = beneficiary.weight;
address addr = beneficiary.addr;
uint amount = (weight * usagePrice) / totalWeight;
addr.transfer(amount);
BeneficiaryPaid(addr, amount);
}
}
struct Beneficiary {
address addr;
uint weight;
}
function addBeneficiary(address addr, uint weight) onlyOwner {
beneficiaries.push(Beneficiary({
addr: addr,
weight: weight
}));
}
}SimpleSmartAssetManager:
contract SimpleSmartAssetManager is Mortal {
mapping(string => address) smartAssets;
function SimpleSmartAssetManager() {
owner = msg.sender;
}
function createSmartAsset(string name,
uint usagePrice,
address[] addresses,
uint[] weights) {
require(addresses.length == weights.length);
require(smartAssets[name] == address(0x0));
address assetAddress = new SimpleSmartAsset(usagePrice,
addresses,
weights);
smartAssets[name] = assetAddress;
}
function getUsagePrice(string assetName)
constant returns (uint) {
address assetAddress = smartAssets[assetName];
uint price = getUsagePrice(assetAddress);
return price;
}
function getUsagePrice(address assetAddress)
constant returns (uint) {
uint price = SimpleSmartAsset(assetAddress).getUsagePrice();
return price;
}
event AssetUsed(string name, uint usagePrice);
function useAsset(string name) payable {
address assetAddress = smartAssets[name];
uint price = getUsagePrice(assetAddress);
require (msg.value >= price);
SimpleSmartAsset(assetAddress).pay.value(msg.value)();
AssetUsed(name, price);
}
function removeAsset(string name) onlyOwner {
address assetAddress = smartAssets[name];
SimpleSmartAsset(assetAddress).remove();
}
}这是我写的第一份合同,我很好奇我能如何改进。
发布于 2017-07-24 18:30:21
不错的合同,作为初学者,做得很好!
在阅读您的代码后,我注意到了前两个问题:
1.您正在使用一种不安全的方法对受益人进行循环:
addr.transfer(amount);因此,如果一个用户在接受转帐时抛出,则可能会冻结其他用户的付款。考虑使用支取支付模式。
2.从理论上讲,你允许无限数量的受益人:
function addBeneficiary(address addr, uint weight) onlyOwner {
beneficiaries.push(Beneficiary({
addr: addr,
weight: weight
}));
}出于安全考虑,我会检查有多少受益人可以在不超过汽油限额的情况下服务,我建议对受益人人数设置一个硬性上限。没有它,您将面临冻结资产的风险,因为循环可能永远不会完全执行。
https://ethereum.stackexchange.com/questions/22951
复制相似问题