首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >代码审核:根据资产使用情况向受益人支付smart合同

代码审核:根据资产使用情况向受益人支付smart合同
EN

Ethereum用户
提问于 2017-07-24 16:10:15
回答 1查看 1.5K关注 0票数 1

我编写两个智能合同是为了创建一个“智能资产”。这样做的想法是,一旦资产被使用,涉及资产的受益人将支付资产的使用价格。例如,四个当事方(设计师、原材料交付者、维护人员和装配人员)创建了一台洗衣机,然后创建了一份智能合同,一旦消费者使用洗衣机,就会向受益人支付费用。(想法是从浪费经济转向使用经济,并鼓励创造可持续的产品。)

SimpleSmartAssetManager是实例化智能资产的智能契约。SimpleSmartAsset是智能资产的表示。

我这样做是为了使受益人包括一个地址和一个重量。权重是受益人在使用资产时收到的使用价格的相对权重。当资产被使用时(通过在pay()上调用SimpleSmartAsset),将从用户中扣除使用的价格,并支付所增加的受益人的相对权重(其权重占总重量的百分比)。

SimpleSmartAssetManager有一个现有智能资产的列表。当使用智能资产时,管理器检索SimpleSmartAsset的特定实例的地址,并调用pay函数。所有调用都应通过合同所有者SimpleSmartAssetManager进行。

这是UML契约图:

当函数被调用时,一些事件被记录到块链中。

MortalOwned契约(因此契约具有onlyOwner修饰符,可以删除):

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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();
  }
}

这是我写的第一份合同,我很好奇我能如何改进。

EN

回答 1

Ethereum用户

回答已采纳

发布于 2017-07-24 18:30:21

不错的合同,作为初学者,做得很好!

在阅读您的代码后,我注意到了前两个问题:

1.您正在使用一种不安全的方法对受益人进行循环:

代码语言:javascript
复制
addr.transfer(amount);

因此,如果一个用户在接受转帐时抛出,则可能会冻结其他用户的付款。考虑使用支取支付模式

2.从理论上讲,你允许无限数量的受益人:

代码语言:javascript
复制
function addBeneficiary(address addr, uint weight) onlyOwner {
    beneficiaries.push(Beneficiary({
        addr: addr,
        weight: weight
    }));
  }

出于安全考虑,我会检查有多少受益人可以在不超过汽油限额的情况下服务,我建议对受益人人数设置一个硬性上限。没有它,您将面临冻结资产的风险,因为循环可能永远不会完全执行。

票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/22951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档