文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
使用 Library
使用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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论