我最近在重新学以太坊opcodes,也写一个“WTF EVM Opcodes极简入门”,供小白们使用。
所有代码和教程开源在github: github.com/WTFAcademy/WTF-Opcodes
在这一讲,我们将介绍EVM中用于查询区块信息的9个指令,包括BLOCKHASH
,COINBASE
,PREVRANDAO
等。我们将在用Python写的极简版EVM中添加对这些操作的支持。
区块信息
我们在写智能合约时经常会用到区块链信息,比如生成伪随机数时我们会使用blockhash
,block.number
,和block.timestamp
:
EVM提供了一系列指令让智能合约访问当前或历史区块的信息,包括区块哈希、时间戳、coinbase等。
这些信息一般保存在区块头(Header
)中,但我们可以为在极简EVM中添加current_block
属性来模拟这些区块信息:
区块信息指令
下面,我们介绍这些区块信息指令:
-
BLOCKHASH
: 查询特定区块(最近的256个区块,不包括当前区块)的hash,它的操作码为0x40
,gas消耗为20。。它从堆栈中弹出一个值作为区块高度(block number),然后将该区块的hash压入堆栈,如果它不属于最近的256个区块,则返回0(你可以使用NUMBER
指令查询当前区块高度)。但是为了简化,我们在这里只考虑当前块。 -
COINBASE
: 将当前区块的coinbase(矿工/受益人)地址压入堆栈,它的操作码为0x41
,gas消耗为2。 -
TIMESTAMP
: 将当前区块的时间戳压入堆栈,它的操作码为0x42
,gas消耗为2。 -
NUMBER
: 将当前区块高度压入堆栈,它的操作码为0x43
,gas消耗为2。 -
PREVRANDAO
: 替代了原先的DIFFICULTY
(0x44) 操作码,其返回值是beacon链随机性信标的输出。此变更允许智能合约在以太坊转向权益证明(PoS)后继续从原本的DIFFICULTY
操作码处获得随机性。它的操作码为0x44
,gas消耗为2。 -
GASLIMIT
: 将当前区块的gas限制压入堆栈,它的操作码为0x45
,gas消耗为2。 -
CHAINID
: 将当前的链ID压入堆栈,它的操作码为0x46
,gas消耗为2。 -
SELFBALANCE
: 将合约的当前余额压入堆栈,它的操作码为0x47
,gas消耗为5。 -
BASEFEE
: 将当前区块的基础费(base fee)压入堆栈,它的操作码0x48
,gas消耗为2。
下面,我们在极简EVM中添加对这些操作码的支持:
总结
这一讲,我们介绍了EVM中与区块链信息相关的指令,这些指令允许智能合约访问与其所在区块链相关的信息。这些信息有很多用途,比如判断交易是否超时,或者检查合约的余额。
课后习题: 请尝试写出一段字节码,该字节码会先压入当前区块链的高度,然后获取它的区块哈希。