- A+
基本概念:
CREATE2 是 Solidity 中的一个操作码,用于创建新的智能合约。它是在以太坊的君士坦丁堡硬分叉中引入的。
主要特性:
1、确定性地址: 与标准 CREATE 操作码不同,CREATE2 允许您在实际部署新合约之前计算新合约的地址。
2、基于“加盐”操作: 它使用“盐”(随机值)作为地址计算的一部分,使开发人员可以更好地控制结果地址。
3、可预测的部署: 相同的初始化代码和盐将始终产生相同的地址,无论何时何地部署。
工作原理:
使用 CREATE2 部署的合约的地址计算如下:
address = keccak256(0xff ++ senderAddress ++ salt ++ keccak256(initCode))[12:]
其中:
0xff
: 是常量字节,如果表示成10进制就是255。senderAddress
:是创建新合约的合约地址。salt
:创建者选择的32字节的值initCode
:是待创建合约的初始化代码
在solidity中如何使用:
我们看如下代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleContract {
uint256 public value;
constructor(uint256 _value) {
value = _value;
}
}
contract Factory {
event Deployed(address addr);
function deploy(bytes32 salt, uint256 _value) public returns (address) {
// 合约的字节码
bytes memory bytecode = abi.encodePacked(
type(SimpleContract).creationCode,
abi.encode(_value)
);
address addr;
assembly {
// 使用 CREATE2 操作码部署合约
addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
// 检查合约是否部署成功
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(addr);
return addr;
}
function computeAddress(bytes32 salt, bytes32 bytecodeHash) public view returns (address) {
return address(uint160(uint256(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
salt,
bytecodeHash
)))));
}
function getBytecodeHash(uint256 _value) public pure returns (bytes32) {
bytes memory bytecode = abi.encodePacked(
type(SimpleContract).creationCode,
abi.encode(_value)
);
return keccak256(bytecode);
}
}
代码解释:
SimpleContract
: 一个简单的合约,带有一个状态变量 value
和一个构造函数用于初始化这个变量。
Factory
: 工厂合约,包含以下几个函数:
deploy
: 使用 CREATE2
操作码部署 SimpleContract
合约。
salt
: 用于生成确定性地址的盐值。_value
: 传递给SimpleContract
构造函数的参数。- 使用
assembly
代码调用CREATE2
操作码,部署合约并检查部署是否成功。
computeAddress
: 计算给定盐值和字节码哈希的合约地址。
salt
: 用于生成确定性地址的盐值。bytecodeHash
: 部署合约字节码的哈希值。
getBytecodeHash
: 计算 SimpleContract
合约字节码的哈希值。
_value
: 传递给SimpleContract
构造函数的参数。
部署和使用步骤
1、部署 Factory
合约: 部署 Factory
合约到以太坊网络上。
2、计算 SimpleContract
合约字节码的哈希值:调用 getBytecodeHash
函数,传递 _value
参数,获取 SimpleContract
的字节码哈希值。
3、计算合约地址: 调用 computeAddress
函数,传递 salt
和前一步获取的 bytecodeHash
,计算将要部署的 SimpleContract
合约的地址。
4、部署 SimpleContract
合约: 调用 deploy
函数,传递 salt
和 _value
参数,使用 CREATE2
操作码部署 SimpleContract
合约。
这里有一个细节需要注意:salt需要传递一个bytes32的类型,如果你输入一个int类型,需要转换一下。
通过上述步骤,可以使用 CREATE2
操作码在部署之前计算合约地址,并在部署时确保合约被部署到预期地址。
- 我的微信
- 这是我的微信扫一扫
- 我的电报
- 这是我的电报扫一扫