我一直在寻找有关以太坊如何处理跳转和跳转目的地的信息。从各种博客和黄皮书中我发现如下:
JUMP 所采用的操作数和 JUMPI 所采用的两个操作数中的第一个是 PC
设置的值(假设在 JUMPI
的情况下,第一个堆栈值 != 0)。
但是,看看 this合约的创建代码(作为操作码)前几个操作码/值是:
PUSH1 0x60
推1 0x40
微商城
调用数据大小
伊泽罗
推2 0x00f8
JUMPI
据我了解,这意味着如果 ISZERO
插入堆栈的值!= 0,则 PC
将更改为 0x00f8
,如下所示JUMPI
从堆栈中取出两个,检查第二个是否为 0,如果不是,则将 PC
设置为其第一个操作数的值。
我遇到的问题是十进制的0x00f8
是248
。合约中的第 248 个位置似乎是 MSTORE
而不是 JUMPDEST
,这会导致合约执行失败,因为 JUMP*
可以仅指向有效的 JUMPDEST
。
大概合约不会故意跳转到无效目的地?
如果有人能解释如何解决跳转和跳转目的地,我将非常感激。
最佳答案
如果它对其他人有帮助:
困惑是由 EVM 逐字节读取而不是逐字读取引起的。
从问题中的示例来看,0x00f8
将是第 248 个字节,而不是第 248 个字。
由于每个操作码都是 1 字节长 PC
读取操作码时通常加 1。
但是在 PUSH
的情况下指令中,还包括以下字节数作为其操作数的信息。
例如PUSH2
取其后的 2 个字节,PUSH6
占用其后的 6 个字节,依此类推。这里PC
对于 PUSH
将增加 1然后对于 PUSH
使用的数据的每个字节分别为 2 或 6 .
关于bytecode - 以太坊字节码 JUMP 和 JUMPDEST 是如何解决的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47520515/