modifier 把function执行前的检查逻辑抽出来,在程序执行前执行一次检查。 包含 1,2,3
require 在0.4.10 solidity加入,用在function参数检查,确认input或合约state V满足条件,用来验证用户的输入。 require(false)不会扣除全部gas,仅扣除已经发生的部分。
throw 用在function逻辑判断,business logic (已弃用!)。
assert 在0.4.10 solidity加入,不检查不变量,发生回滚revert时会把全部gas扣除。
revert 标记错误并混滚当前调用。
operator
event 是和外部通信的方式,可以用来记录变量信息,实现打印。
-- 1 pre-conditions 2 post-conditions 3 state changes
以下代码实现了可重用的log方法,只要调用log()方法就可以打印不同类型的变量值。
使用方法为:log(string name, var value)
pragma solidity ^0.4.21;
//通过log函数重载,对不同类型的变量trigger不同的event,实现solidity打印效果,使用方法为:log(string name, var value)
contract Console {
event LogUint(string, uint);
function log(string s , uint x) internal {
emit LogUint(s, x);
}
event LogInt(string, int);
function log(string s , int x) internal {
emit LogInt(s, x);
}
event LogBytes(string, bytes);
function log(string s , bytes x) internal {
emit LogBytes(s, x);
}
event LogBytes32(string, bytes32);
function log(string s , bytes32 x) internal {
emit LogBytes32(s, x);
}
event LogAddress(string, address);
function log(string s , address x) internal {
emit LogAddress(s, x);
}
event LogBool(string, bool);
function log(string s , bool x) internal {
emit LogBool(s, x);
}
}
使用时只需要将Console.sol import进程序且继承Console就好(注意第3行和第41行
pragma solidity ^0.4.21;
import "browser/Console.sol";
contract SimpleAuction is Console {
// Parameters of the auction. Times are either
// absolute unix timestamps (seconds since 1970-01-01)
// or time periods in seconds.
address public beneficiary; //受益人
uint public auctionEnd; //竞拍终止时间
// Current state of the auction.
address public highestBidder; //最高竞拍者
uint public highestBid; //最高竞拍
// Allowed withdrawals of previous bids
mapping(address => uint) pendingReturns; //待退回的竞拍(不是最高出价都退回)
// Set to true at the end, disallows any change
bool ended; //一旦设置不允许再投标
// Events that will be fired on changes.
event HighestBidIncreased(address bidder, uint amount); //最高出价变动时调用事件
event AuctionEnded(address winner, uint amount); // 拍卖结束时调用事件
// The following is a so-called natspec comment,
// recognizable by the three slashes.
// It will be shown when the user is asked to
// confirm a transaction.
/// Create a simple auction with `_biddingTime`
/// seconds bidding time on behalf of the
/// beneficiary address `_beneficiary`.
/// 初始化拍卖对象:受益人地址、拍卖持续时间
function SimpleAuction(
uint _biddingTime,
address _beneficiary
) public {
beneficiary = _beneficiary;
auctionEnd = now + _biddingTime;
log("time now", now);
}
/// Bid on the auction with the value sent
/// together with this transaction.
/// The value will only be refunded if the
/// auction is not won.
///对竞拍投标,payable代表该交易可以获取ether,只有没有竞拍成功的交易款才会退回
function bid() public payable {
// No arguments are necessary, all
// information is already part of
// the transaction. The keyword payable
// is required for the function to
// be able to receive Ether.
// Revert the call if the bidding
// period is over.
//输入检查,竞拍如果结束则终止
require(now <= auctionEnd);
// If the bid is not higher, send the
// money back.
//如果投标金额未超过当前最高金额,则终止
require(msg.value > highestBid);
if (highestBid != 0) {
// Sending back the money by simply using
// highestBidder.send(highestBid) is a security risk
// because it could execute an untrusted contract.
// It is always safer to let the recipients
// withdraw their money themselves.
pendingReturns[highestBidder] += highestBid; //原来的最高变次高出价,次高出价要退回
}
highestBidder = msg.sender; //新的最高出价者
highestBid = msg.value; //新的最高出价
emit HighestBidIncreased(msg.sender, msg.value); //触发最高出价增加事件
}
/// Withdraw a bid that was overbid.
/// 取回被淘汰的竞拍
function withdraw() public returns (bool) {
uint amount = pendingReturns[msg.sender];
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
// before `send` returns.
pendingReturns[msg.sender] = 0; //在send方法被执行之前,将待退还的钱置为0 *这个很重要* 因为如果不置为0的话,可以重复发起withdraw交易,send需要时间,在交易没确认之前,重复发起可能就要退N倍的钱
if (!msg.sender.send(amount)) { //用户自己取回退回的款项时,如果出错不用调用throw方法,而是将被置0的待退款金额恢复
// No need to call throw here, just reset the amount owing
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
/// End the auction and send the highest bid
/// to the beneficiary.
function auctionEnd() public {
// It is a good guideline to structure functions that interact
// with other contracts (i.e. they call functions or send Ether)
// into three phases:
// 1. checking conditions
// 2. performing actions (potentially changing conditions)
// 3. interacting with other contracts
// If these phases are mixed up, the other contract could call
// back into the current contract and modify the state or cause
// effects (ether payout) to be performed multiple times.
// If functions called internally include interaction with external
// contracts, they also have to be considered interaction with
// external contracts.
// 1. Conditions
require(now >= auctionEnd); // auction did not yet end
require(!ended); // this function has already been called
// 2. Effects
ended = true;
emit AuctionEnded(highestBidder, highestBid);
// 3. Interaction
beneficiary.transfer(highestBid);
}
}
log方法执行后可以在这里找到打印出的变量信息
Comments