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方法执行后可以在这里找到打印出的变量信息:
1.001^365=1.44......life is a project
原创文章,转载请注明出处!