Create & Create2
源文章:https://www.immunebytes.com/blog/explained-create2-opcode-in-solidity/
本文对其进行部分删改。Contract Address nonce 部分内容来自:
https://ethereum.stackexchange.com/questions/764/do-contracts-also-have-a-nonce
https://ethereum.stackexchange.com/questions/185/where-is-the-private-key-for-a-contract-stored
CREATE2 操作码是 Solidity 语言中一个强大的功能,使开发人员能够在具有确定性的预定地址创建合约。它诞生于以太坊网络的拜占庭硬分叉期间,因其多功能性和成本效益而受到开发人员的欢迎。
Create2 的优势
使用 Create 部署合约 时,地址由 Factory 合约的 nonce 确定。每次在工厂合约中调用 CREATE 时,其 nonce 都会加 1,而 CREATE2 则通过任意的 salt
值和init_code
来确定地址。
换句话说:使用 CREATE2 时,生成的合约地址不依赖调用时 factory contract 的确切状态(即 nonce)
Contract Address nonce
合同也有 nonces。EIP 161 使合约 nonce 从 1 开始,而在 EIP 161 之前,nonce 将从 0 开始。只有当该合约创建另一个 Contract 时,该 Contract 的 nonce 才会递增。当一个合约调用另一个合约上的函数时,即所谓的“内部交易”,nonce 不会递增。
可以使用 web3.eth.getTransactionCount
获取 nonce。合约没有内置方法来访问账户的 nonce,包括它自己的 nonce。(Contract 可以使用其存储来跟踪自己的 nonce.)
需要明确的是,以太坊中只有 2 种类型的账户,它们都具有相同的 4 个“物理”属性:nonce、balance(以 wei 为单位)、storage trie root 的哈希值、Code。唯一的 “物理” 区别是 Contract 具有非零代码。
在行为方面,合约和普通账户之间还有一些差异。nonce 的增加是一种行为差异,另一个主要的是合约的私钥存储在哪里
合约不像 EOA 那样拥有私钥。相反,它们具有以 Ethereum 虚拟机的语言编写的编程代码。
为了确定合约的“作用”,以太坊网络的所有成员只需在每次交易或其他合约使用合约的功能时运行相关部分的代码。因为代码和 EVM 是仔细定义的,所以每个人都会对操作的结果达成一致。这包括合约是否向任何其他合约发送交易。由于每个人都可以就消息的来源达成一致,因此不需要进一步程度的验证(例如签名提供的验证)。
为了澄清“普通账户的随机数会随着每次交易而增加”,非合约账户的 nonce 仅在该账户发起交易时(当它是账户的发送者时)才会增加。当帐户是接收者(to 帐户)时,其 nonce 不会增加。
CREATE2 Opcode
CREATE2 具有一个显著的特性,可以提高其在特定上下文中的适用性:它独立于部署地址的当前状态运行。因此,可以确定今天计算的合约地址将与一年后计算的地址保持一致。
此功能非常重要,因为它允许与地址进行交互,并有助于在智能合约部署到该地址之前将 ETH 转移到该地址。简单来说,CREATE2 操作码无需实际部署即可预测合约的部署地址,并提供了许多增强用户入职和可扩展性的机会,而无需预先执行部署。
使用 CREATE 部署合约和 CREATE2 部署合约的区别
部署智能合约有两种主要方法:使用 CREATE 和 CREATE2 流。在这个简短的概述中,我们将探讨每种方法的工作原理并强调它们的基本区别。
使用 CREATE
智能合约可以通过合约或标准账户(EOA)生成。在这两种情况下,新创建的合约的地址遵循相同的计算方法:
由 **msg.sender**
和 **nonce**
决定
new_address = hash(sender, nonce)
每个账户都有一个相应的 nonce,对于 EOA 账户,随着每笔交易和合约账户的每次合约创建而增加。nonce 是不可重用的,且必须按照顺序。
虽然可以预测下一个部署合约的地址,但这种预测仅在没有干预交易的情况下才成立——对于反事实系统来说,这是一个不太理想的特征。
使用 CREATE2
CREATE2 通过确保生成的地址不受未来事件的影响来有效地解决问题。无论区块链上发生什么事件,在预先计算的地址部署合约将始终保持可行。
new_address = hash(0xFF, sender, salt, bytecode)
新地址的计算涉及以下元素:
- 0xFF:用于避免与 CREATE 冲突的常量
- sender:部署者的地址
- salt:一个 32 字节,由 sender 提供的任意值
- bytecode:要部署的合约的字节码
执行时,CREATE2 操作码会生成一个智能合约,其地址由 salt 值和合约创建代码的组合确定。
当使用相同的 salt 值和合约创建代码时,无论使用何种部署节点,生成的合约都将始终显示相同的地址。
CREATE2 有什么用?
事实证明,CREATE2 操作码固有的可预测性在各种情况下都是有益的。例如,它简化了需要与特定合约交互的不同智能合约或去中心化应用程序 (dApp) 之间的协调,因为可以提前预测合约的地址。
以太坊中的 CREATE2 操作码提供了几个好处:
改进的互操作性:地址的确定性简化了不同智能合约或去中心化应用程序之间的协调和交互。这可以在复杂的去中心化系统中实现更高效、更无缝的互操作性。
高效的状态通道和第 2 层扩容解决方案:在状态通道和第 2 层扩容解决方案中,协调链下交易,CREATE2 地址的确定性可以简化合约地址的管理并提高这些扩容解决方案的效率。
增强的安全性:确定性地计算合约地址的能力可以通过允许各方在与合约交互之前验证和确认地址来增强安全性。这降低了地址生成过程中出现意外错误的风险。
成本效益:可预测的合约地址可能会节省 gas 费用。去中心化系统中的参与者可以规划和优化他们的交互,从而可能减少计算开销和相关成本。
促进可升级性:确定性地址在可升级的合约场景中可能是有利的。开发人员能够在相同的确定性地址部署合约的更新版本,从而通过无缝升级的版本简化用户和其他合约的交互。
在去中心化金融 (DeFi) 中有用:在部署各种需要精确寻址以实现 DeFi 生态系统内无缝集成的金融工具和智能合约时,DeFi 协议通常受益于 CREATE2 的确定性。
Create2 OpCode 的陷阱
利用“Create2”技术,黑客预先计算合约地址,使他们能够生成与受害者经常使用的地址非常相似的欺诈地址。这导致毫无戒心的受害者在不知不觉中批准了促进非法资金转移的交易。这种诈骗技术被称为地址中毒。
这种方法在 Wallet Drainers 在六个月内从近 100,000 名受害者那里窃取了约 6000 万美元的过程中发挥了重要作用。