Solidity调试 - 实现变量打印
Solidity没有print或console.log方法可以用来打印变量,这会给我们调试程序增加难度。
Solidity有event功能,可以在event中记录变量信息,通过调用event方法也可以实现打印功能,但不可能处处写event方法,麻烦。
以下代码实现了可重用的log方法,只要调用log()方法就可以打印不同类型的变量值。
使用方法为:log(string name, var value)
pragma solidity ^0.4.; //通过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.; contract Console {
event LogUint(string, var);
function log(string s , var x) internal {
emit LogUint(s, x);
}
}
使用时只需要将Console.sol import进程序且继承Console就好(注意第3行和第41行):
pragma solidity ^0.4.; 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 != ) {
// 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 > ) {
// 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] = ; //在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方法执行后可以在这里找到打印出的变量信息:
Solidity调试 - 实现变量打印的更多相关文章
- Lua中如何实现类似gdb的断点调试--02通用变量打印
在前一篇01最小实现中,我们实现了Lua断点调试的的一个最小实现.我们编写了一个模块,提供了两个基本的接口:设置断点和删除断点. 虽然我们已经支持在断点进行变量的打印,但是需要自己指定层数以及变量索引 ...
- Android Studio中JNI程序的单步调试和日志打印
近日有个算法(检测碰撞)需要用C++实现,目的是IOS和ANDROID中共享同一段程序. 下面说说android调用这段程序过程中遇到的一些事情.(过程中网上搜索了一些相关文章,大部分说的是eclip ...
- 脚本编程中的test、bash调试、变量计算、参数
脚本编程中的test.bash调试.变量计算.参数 1.文件测试 -e FILE:测试文件是否存在 -f FILE:测试文件是否为普通文件 -d FILE:测试路径是否为目录 -r FILE:测试当前 ...
- 冒泡排序 and 选择排序 变量打印斐波拉契数列 and 数组打印斐波拉契数列
1 排序 1.1 冒泡排序 #include <stdio.h> int main() { ]; printf("input six int numbers:\n"); ...
- 使用whIle循环语句和变量打印九九乘法表
-设置i变量declare @i int --设置j变量declare @j int --设置乘法表变量declare @chengfabiao varchar(1000)--给i,j,@chengf ...
- C#.Net集成Bartender条码打印,VS调试运行可以打印,发布到IIS运行打印报错
C#.Net集成Bartender条码打印,VS调试运行可以打印,发布到IIS运行打印报错 问题原因: 问题出现在iis账户权限. 解决方法: iis默认是用network service这个账户去执 ...
- Tensorflow之调试(Debug)及打印变量
参考资料:https://wookayin.github.io/tensorflow-talk-debugging 几种常用方法: 1.通过Session.run()获取变量的值 2.利用Tensor ...
- 增加p()函数,方便开发中对变量打印调试
在开发的过程中,我们经常要输出一下变量看看得到的结果是什么,我们就要根据变量的类型选择使用echo,print_r或者var_dump,brophp框架中的p()函数会自动根据变量类型选择用什么方法为 ...
- GDB调试指南-变量查看
前言 在启动调试以及设置断点之后,就到了我们非常关键的一步-查看变量.GDB调试最大的目的之一就是走查代码,查看运行结果是否符合预期.既然如此,我们就不得不了解一些查看各种类型变量的方法,以帮助我们进 ...
随机推荐
- 基于Java SE集合的充值管理系统
1.功能分析 ①管理员管理 注册.登录.退出 ②注册一卡通:记录相应信息. ③充值管理:对一卡通账户进行充值,查询,修改. 2.技术要求 ①Java 基础知识 + 集合类(模拟数据库). ②数据用对象 ...
- C语言队列(数组内核)
#include <stdio.h>#include <stdbool.h>#include <stdlib.h>struct Queue{ int *pBase; ...
- PHP opcache扩展安装
下面是我在PHP 5.4下的安装方法: https://pecl.php.net/get/zendopcache-7.0.5.tgz tar xzf zendopcache-7.0.5.tgz cd ...
- windows 下 Symfony的下载与安装
初始化项目 本篇教程我尽量按照Windows/*nix都可以运行的方式来讲解. 得益于Symfony installer,我们目前可以很方便的初始化一个Symfony2项目.不过首先,你得有一个Sym ...
- Egret学习笔记 (Egret打飞机-1.大致思路)
大致看了一遍Egret的官方文档,就开始打算使用Egret来开发一个打飞机游戏. 首先来捋一捋思路,先来看一看一个打飞机游戏的图片 基本上一个打飞机游戏分为 开始游戏 ----------进入游戏 ...
- UVA1601 状态搜索
很有意思的一道题,就是迷宫问题的增强版.但是细节很多,有一个技巧就是把每个可以走的位置编号方便状态判重. AC代码: #include<cstdio> #include<cstrin ...
- shell脚本中 杀死可能成为僵尸进程的方法
交互式 Bash Shell 获取进程 pid 在已知进程名(name)的前提下,交互式 Shell 获取进程 pid 有很多种方法,典型的通过 grep 获取 pid 的方法为(这里添加 -v gr ...
- 1000多个项目中的十大JavaScript错误以及如何避免
通过统计数据库中的1000多个项目,我们发现在 JavaScript 中最常出现的错误有10个.下面会向大家介绍这些错误发生的原因以及如何防止. 对于这些错误发生的次数,我们是通过收集的数据统计得出的 ...
- 用Node.JS+MongoDB搭建个人博客(model目录)(三)
model目录主要是封装一些经常使用的方法,便于使用. setting.js文件: 很简单,就单单封装了一个url作为公用,以后改就方便改了. md5.js(不推荐用): db.js文件: db.js ...
- vxWorks 命令
1.4.1 任务管理 sp( ) 用缺省参数创建一个任务(priority="100" 返回值为任务ID,或错误)(taskSpawn) sps( ) ...