区块链学习打卡-20180706

BUG 描述

在调试第五课程序时的遇到了一个奇怪的BUG,我随手添加了一个地址为 0x0000000000000000000000000000000000000001 的雇员,在进行删除操作时,系统提示『资金不足』。然而在salary参数相同的条件下,其他地址(比如:0x2d4f946fc3c540342421f2c80a0f1f1058eb0cdb)的雇员信息却可以正常删除。很显然,我遇到了一个『钉子户』雇员 😂

无法删除地址为 0x0000000000000000000000000000000000000001 的雇员

BUG 假设

遇到这个问题时,脑海里首先闪过以下几种可能

1. 合约账户ETH余额不足

2. 合约中 PAY_DURATION 时间设置过短

3. 合约存在类似于『短地址攻击』的漏洞,导致 0x0000000000000000000000000000000000000001 这样的特殊地址在执行 _partialPaid 函数时,实际发放金额为被计算成了1  * 1000000000000000000000000000000000000000 ether,从而执行失败

前两点假设很容易进行验证,在确认合约余额,延长 PAY_DURATION 时间后,很快就被我排除掉了。而第三个假设,通过检查代码,使用类似 0x0000000000000000000000000000000000000002 地址进行试验,最终也被否定了。

BUG 追踪

由于之前的假设一一被否定,我意识到这个BUG可能并没有想象中那么简单,需要收集更多信息进行调试。在 ganache-cli 的日志中可以发现,交易之前的失败交易触发了revert操作

交易日志

利用remix debug 功能,单步调试,发现问题出在 employeeId.transfer(payment); 这个函数上。

revert 触发前的最后一行代码

然而,光有这些信息仍然无法解释为什么偏偏只有0x0000000000000000000000000000000000000001(后续简称『0x1地址』)这个地址会触发transfer异常,因此,需要继续深入查看实际执行transfer的evm指令。为了方便测试构造一个简化版的函数,分别传入常规地址和0x1地址,同样常规地址执行成功,而0x1地址执行失败。

简化版验证函数

通过对比成功交易的call stack,最终将问题锁定这个CALL指令的调用上


出现问题的CALL指令

官方文档中call函数的函数说明如下

call(g, a, v, in, insize, out, outsize) 

call contract at address a with input mem[in..(in+insize)) providing g gas and v wei and output area mem[out..(out+outsize)) returning 0 on error (eg. out of gas) and 1 on success

可以看出,call返回值为0,也就是调用失败了。由于tansfer传输的金额为v = 0,所以可以排除账户余额不足的情况,最大的可能性是gas不足,也就是目前传入给call的 g = 0x8fc (十进制:2300) gas 不足以支付调用费用。下图是正常的call调用消耗 了700 gas

正常调用 call 费用为 700 gas

而transfer到0x1地址消耗了2300+700 gas,也就是说,传入的gas全部被耗尽后仍然无法完成 call 调用,导致调用失败

异常调用消耗了2300+700 gas

暂且不考虑为什么0x1地址会消耗更多的gas,假设增加传入call操作的gas数量是否能成功调用该函数呢?为了验证这个猜想,构造如下函数


验证gas

该CALL调用参数与之前的函数一致,唯一不同的是call传入的gas数量变为了0xffff 也就是 65535,,传入0x1地址,执行成功!实际call调用消耗gas为700+3000


执行成功

由此可以得知,之前无法删除员工的原因便是:0x1地址调用call操作时消耗的gas超出了预分配的量,导致transfer失败,触发了revert()

GAS消耗之谜

尽管弄明白了调用失败的原因,但目前有一个问题仍旧没能解决,那就是为什么call在调用0x1地址时会消耗更多的gas。为此我查阅了EIP150的中相关gas消耗细节,其中大部分的opcode都规定了明确gas消耗数量,唯独call这一类型需要单独查看黄皮书


EIP150部分细节

在翻阅了黄皮书附录后,我终于找到了call的计费细节


call gas消耗细节-1


call gas消耗细节-2

根据黄皮书中细节描述,call调用的初始消耗是700 gas,触发revert的条件是堆栈深度超过1024或者预分配gas消耗殆尽,而预分配的gas只会在调用(或创建)其他合约时才会被使用,也就是说,对于非合约账户地址(也就是普通钱包地址),在不传入传出额外数据的情况下,不会产生额外的gas消耗,call调用的总gas消耗为700,这也和之前观测到的正常调用消耗一致。黄皮书似乎也没有解答这个问题。

由于之前的一直是在remix的javascript vm环境测试,会不会是这个仿真环境的bug呢?为此我也在ropsten网络进行了测试,结果依然不变,0x1地址会额外消耗3000点gas。主网环境下也依然如此,正常的eth转账需要消耗21000 gas,而如果给0x1地址转账的话,需要消耗24000gas。如果用metamask尝试给0x1地址转账的话,gaslimit 会默认是21000 gas,不出意外的话,这笔转账会fail掉。


给0x1地址转账,需要消耗24000gas


因此,要回答这个问题还是需要去看evm的具体代码实现。这也许是个bug,也许是个feature,也可能是我之前的分析还存在着一些漏洞,如有任何问题,欢迎各位大佬指正,也希望对此问题感兴趣的小伙伴们能做进一步研究。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容