返回介绍

使用 Library

发布于 2024-06-02 01:00:06 字数 6484 浏览 0 评论 0 收藏 0

使用Library

如果现在新增一个需求:计算商品卖出花了多长时间。开动脑筋想想可以怎么办?

显而易见的思路是:发布时记录时间戳(我们已经做了),买家确认收货的时候再记录时间戳然后减 发布时间戳。

按此思路,进行改写:

function confirmFinish(address seller) commodityExist(seller){
    require(warehouse[seller].buyer == msg.sender);

    // 计算时间间隔
    warehouse[seller].timeInterval = now - warehouse[seller].time;
    warehouse[seller].isFinish = true;
    seller.transfer(warehouse[seller].price);
}

要注意:solidity 的加减乘除四则运算很容易出现上溢下溢问题,比如

contract C {
    // (2**256 - 1) + 1 = 0
    function overflow() returns (uint256 _overflow) {
        uint256 max = 2**256 - 1;
        return max + 1;
    }

    // 0 - 1 = 2**256 - 1
    function underflow() returns (uint256 _underflow) {
        uint256 min = 0;
        return min - 1;
    }
}

最简单的0-1的值不会是-1,而是 2的 256次方 的值为-1,为了避免像这些错误我们可以用现成的library,并增强程序的健壮性。

以zeppelin 的 SafeMath.sol 为例:

pragma solidity ^0.4.18;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

这个library 提供了四则运算的基本检查,如果溢出assert 就会被触发进而结束操作。

下面在remix中新增一个合约,命名为SafeMath.sol ,把这些代码复制粘贴进去就好,千万注意和Market.sol在同一目录下哦。

在程序头部添加import:

import './SafeMath.sol';

然后在struct Commodity声明之前添加引用:

using SafeMath for uint;

修改刚才的confirmFinish方法:

function confirmFinish(address seller) commodityExist(seller){
    require(warehouse[seller].buyer == msg.sender);

    // 使用SafeMath 计算时间间隔
    warehouse[seller].timeInterval = now.sub(warehouse[seller].time);
    warehouse[seller].isFinish = true;
    seller.transfer(warehouse[seller].price);
}

修改之后的完整代码:

pragma solidity ^0.4.14;
import './SafeMath.sol';

contract Market{
    using SafeMath for uint;

    struct Commodity{
        string name;
        string url;
        uint price;
        address seller;
        address buyer;
        uint time;
        bool isFinish;
        uint timeInterval;
    }

    mapping(address => Commodity) warehouse;

    modifier commodityExist(address seller){
        var commodity =  warehouse[seller];
        assert(commodity.seller != 0x0);
        _;
    }

    function buy(address seller) commodityExist(seller) payable returns (uint) {
        warehouse[seller].buyer = msg.sender;
        return this.balance;
    }

    function addCommodity(string name, string url, uint price){
        require(bytes(name).length > 0);
        require(bytes(url).length > 0);

        warehouse[msg.sender] = Commodity(name, url, price.mul(1 ether), msg.sender, 0x0, now, false, 0);
    }

    function removeCommodity() commodityExist(msg.sender){
        delete warehouse[msg.sender];
    }

    function updateCommodity(string name, uint price) commodityExist(msg.sender){
        warehouse[msg.sender].name = name;
        warehouse[msg.sender].price = price.mul(1 ether);
        warehouse[msg.sender].time = now;
    }

    function confirmFinish(address seller) commodityExist(seller){
        require(warehouse[seller].buyer == msg.sender);

        warehouse[seller].timeInterval = now.sub(warehouse[seller].time);
        warehouse[seller].isFinish = true;
        seller.transfer(warehouse[seller].price);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文