Solidity调试 - 实现变量打印

Solidity没有print或console.log方法可以用来打印变量,这会给我们调试程序增加难度。

 

Solidity有event功能,可以在event中记录变量信息,通过调用event方法也可以实现打印功能,但不可能处处写event方法,麻烦。

 

以下代码实现了可重用的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);
    }
}

 

我尝试过用var替代变量类型,但是编译不通过,应该是var不能做函数参数类型。

以下是编译不过的:

pragma solidity ^0.4.21;

contract Console {
    event LogUint(string, var);
    function log(string s , var x) internal {
    emit LogUint(s, x);
    }
}

 

使用时只需要将Console.sol import进程序且继承Console就好(注意第3行和第41行):

  1 pragma solidity ^0.4.21;
  2 
  3 import "browser/Console.sol";
  4 
  5 contract SimpleAuction is Console {
  6     // Parameters of the auction. Times are either
  7     // absolute unix timestamps (seconds since 1970-01-01)
  8     // or time periods in seconds.
  9     address public beneficiary;  //受益人
 10     uint public auctionEnd; //竞拍终止时间
 11 
 12     // Current state of the auction.
 13     address public highestBidder; //最高竞拍者
 14     uint public highestBid; //最高竞拍
 15 
 16     // Allowed withdrawals of previous bids
 17     mapping(address => uint) pendingReturns;  //待退回的竞拍(不是最高出价都退回)
 18 
 19     // Set to true at the end, disallows any change
 20     bool ended; //一旦设置不允许再投标
 21 
 22     // Events that will be fired on changes.
 23     event HighestBidIncreased(address bidder, uint amount); //最高出价变动时调用事件
 24     event AuctionEnded(address winner, uint amount); // 拍卖结束时调用事件
 25 
 26     // The following is a so-called natspec comment,
 27     // recognizable by the three slashes.
 28     // It will be shown when the user is asked to
 29     // confirm a transaction.
 30 
 31     /// Create a simple auction with `_biddingTime`
 32     /// seconds bidding time on behalf of the
 33     /// beneficiary address `_beneficiary`.
 34     /// 初始化拍卖对象:受益人地址、拍卖持续时间
 35     function SimpleAuction(
 36         uint _biddingTime,
 37         address _beneficiary
 38     ) public {
 39         beneficiary = _beneficiary;
 40         auctionEnd = now + _biddingTime;
 41         log("time now", now);
 42     }
 43 
 44     /// Bid on the auction with the value sent
 45     /// together with this transaction.
 46     /// The value will only be refunded if the
 47     /// auction is not won.
 48     ///对竞拍投标,payable代表该交易可以获取ether,只有没有竞拍成功的交易款才会退回
 49     function bid() public payable {
 50         // No arguments are necessary, all
 51         // information is already part of
 52         // the transaction. The keyword payable
 53         // is required for the function to
 54         // be able to receive Ether.
 55 
 56         // Revert the call if the bidding
 57         // period is over.
 58         //输入检查,竞拍如果结束则终止
 59         require(now <= auctionEnd);
 60 
 61         // If the bid is not higher, send the
 62         // money back.
 63         //如果投标金额未超过当前最高金额,则终止
 64         require(msg.value > highestBid);
 65 
 66         if (highestBid != 0) {
 67             // Sending back the money by simply using
 68             // highestBidder.send(highestBid) is a security risk
 69             // because it could execute an untrusted contract.
 70             // It is always safer to let the recipients
 71             // withdraw their money themselves.
 72             pendingReturns[highestBidder] += highestBid; //原来的最高变次高出价,次高出价要退回
 73         }
 74         highestBidder = msg.sender; //新的最高出价者
 75         highestBid = msg.value; //新的最高出价
 76         emit HighestBidIncreased(msg.sender, msg.value); //触发最高出价增加事件
 77     }
 78 
 79     /// Withdraw a bid that was overbid.
 80     /// 取回被淘汰的竞拍
 81     function withdraw() public returns (bool) {
 82         uint amount = pendingReturns[msg.sender];
 83         if (amount > 0) {
 84             // It is important to set this to zero because the recipient
 85             // can call this function again as part of the receiving call
 86             // before `send` returns.
 87             pendingReturns[msg.sender] = 0; //在send方法被执行之前,将待退还的钱置为0 *这个很重要* 因为如果不置为0的话,可以重复发起withdraw交易,send需要时间,在交易没确认之前,重复发起可能就要退N倍的钱
 88 
 89             if (!msg.sender.send(amount)) { //用户自己取回退回的款项时,如果出错不用调用throw方法,而是将被置0的待退款金额恢复
 90                 // No need to call throw here, just reset the amount owing
 91                 pendingReturns[msg.sender] = amount;
 92                 return false;
 93             }
 94         }
 95         return true;
 96     }
 97 
 98     /// End the auction and send the highest bid
 99     /// to the beneficiary.
100     function auctionEnd() public {
101         // It is a good guideline to structure functions that interact
102         // with other contracts (i.e. they call functions or send Ether)
103         // into three phases:
104         // 1. checking conditions
105         // 2. performing actions (potentially changing conditions)
106         // 3. interacting with other contracts
107         // If these phases are mixed up, the other contract could call
108         // back into the current contract and modify the state or cause
109         // effects (ether payout) to be performed multiple times.
110         // If functions called internally include interaction with external
111         // contracts, they also have to be considered interaction with
112         // external contracts.
113 
114         // 1. Conditions
115         require(now >= auctionEnd); // auction did not yet end
116         require(!ended); // this function has already been called
117 
118         // 2. Effects
119         ended = true;
120         emit AuctionEnded(highestBidder, highestBid);
121 
122         // 3. Interaction
123         beneficiary.transfer(highestBid);
124     }
125 }

 

log方法执行后可以在这里找到打印出的变量信息:

 

posted @ 2018-03-18 00:00 huahuayu 阅读(...) 评论(...) 编辑 收藏