我最近在重新学以太坊opcodes,也写一个“WTF EVM Opcodes极简入门”,供小白们使用。
所有代码和教程开源在github: github.com/WTFAcademy/WTF-Opcodes
上一讲我们介绍了CREATE
指令,使合约有能力创建其他合约。这一讲,我们将进一步探讨CREATE2
指令,它提供了一种新的方式来确定新合约的地址。
CREATE vs CREATE2
传统的CREATE
指令通过调用者的地址和nonce来确定新合约的地址,而CREATE2
则提供了一种新的计算方法,使我们可以在合约部署之前预知它的地址。
与CREATE
不同,CREATE2
使用调用者地址、盐(一个自定义的256位的值)以及initcode
的哈希来确定新合约的地址,计算方法如下:
这样的好处是,只要你知道initcode
,盐值和发送者的地址,就可以预先知道新合约的地址,而不需要现在部署它。而CREATE
计算的地址取决于部署账户的nonce
,也就是说,在nonce
不确定的情况下(合约还未部署,nonce可能会增加),没法确定新合约的地址。
对CREATE2
的更多介绍可以参考WTF Solidity教程第25讲。
CREATE2
在EVM中,CREATE2
指令的简化流程如下:
- 从堆栈中弹出
value
(向新合约发送的ETH)、mem_offset
、length
(新合约的initcode
在内存中的初始位置和长度)以及salt
。 - 使用上面的公式计算新合约的地址。
- 之后的步骤同
CREATE
指令:初始化新的EVM上下文、执行initcode
、更新创建的账户状态、返回新合约地址或0
(如果失败)。
下面,我们在极简EVM中实现CREATE2
指令:
测试
-
使用
CREATE2
指令部署一个新合约,发送9
wei,但不部署任何代码: -
使用
CREATE2
指令部署一个新合约,并将代码设置为ffffffff
:
总结
这一讲,我们介绍了EVM
中创建合约的另一个指令,CREATE2
,通过它,合约不仅可以创造其他合约,而且可以预知新合约的地址。Uniswap v2
中的LP地址就是用这个方法计算的。现在,我们已经学习了144个操作码中的142个(98.6%)!