我最近在重新学以太坊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指令部署一个新合约,发送9wei,但不部署任何代码:
- 
使用 CREATE2指令部署一个新合约,并将代码设置为ffffffff:
总结
这一讲,我们介绍了EVM中创建合约的另一个指令,CREATE2,通过它,合约不仅可以创造其他合约,而且可以预知新合约的地址。Uniswap v2中的LP地址就是用这个方法计算的。现在,我们已经学习了144个操作码中的142个(98.6%)!