Create2 创建合约、预测合约地址,看这一篇就够了

本文使用create2创建合约、预测合约地址

Target 合约 (本文使用 create2 创建这个合约)

contract Target {
    address public immutable owner;
    uint256 public count;

    constructor(address _owner, uint256 _count) {
        owner = _owner;
        count = _count;
    }

    function test() public {
        require(msg.sender == owner, "only owner");
        count = 100;
    }
}

这里故意给Target 合约设置 2 个构造函数参数:_owner 和 _count,目的是完整演示Create2创建合约的方法。下面需要传这个两个参数创建合约。

Create2 工厂合约

create2 有两种方式,这里一一列出

  1. create2 第一种创建合约的方法,这是最新的,旧版需要汇编
// 以下的各个方法都在 Factory 合约内,为了突出重点,下面的方法不再给出Factory{}包裹
contract Factory {
    function deploy(address _owner, uint256 _count, bytes32 _salt) 
        public 
        returns (address) 
    {
        return address(new Target{salt: _salt}(_owner, _count));
    }
}
  1. create2 第二种创建合约的方法,旧版汇编的方式
// @_bytecode Target合约字节码,下面有方法可以方便获取
// @_salt 盐值,下面有公共方法可以获取盐值
function deployAssembly(bytes memory _bytecode, bytes32 _salt) public returns (address addr) {
    assembly {
        addr := create2(
            0,
            add(_bytecode, 32),
            mload(_bytecode),
            _salt
        )

        if iszero(extcodesize(addr)) {
            revert(0, 0)
        }
    }
}
  1. 第 2 步 Target 合约的字节码,可以抽象出一个公共方法来获取合约字节码
// 要部署合约的字节码, _owner 和 _count 是构造函数的参数
function getBytecode(address _owner, uint256 _count) public pure returns (bytes memory) {
    bytes memory bytecode = type(Target).creationCode;
    return abi.encodePacked(bytecode, abi.encode(_owner, _count));
}
  1. 预测 Target 合约地址
function getAddress(bytes memory _bytecode, bytes32 _salt) public view returns (address) {
    bytes32 addrHash = keccak256(abi.encodePacked(
        bytes1(0xff), // 这里可以写 hex'ff'  不能写 "0xff"
        address(this), // 这里是调用create2的合约,在本文中就是当前的Factory合约
        _salt, // 盐值
        keccak256(_bytecode) // 这里可以提前进行 keccak256 后写到这里,写法是 bytes32(0xABC...) 或 hex'ABC...',不能写 "0xABC..."
    ));
    // 将最后 20 个字节的哈希值转换为地址
    return address(uint160(uint(addrHash)));
}
  1. 公共方法
// 生成盐值,盐值可以是任意值,也可以是地址,字符串等,这里只是个例子
function hash(uint256 n) public pure returns (bytes32) {
    return keccak256(abi.encode(n));
}

// 生成合约字节码的hash,用于提前hash字节码,通过参数传递给预测地址的方法
// 预测地址的时候,除了上面 getAddress 方法传递字节码以外,还可以将字节码hash后传入,这种情况要注意写法,上面getAddress方法每个参数有说明,不再赘述
function hash(bytes memory bytecode) public pure returns (bytes32) {
    return keccak256(bytecode);
}
点赞 3
收藏 7
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
认知那些事
认知那些事
0x2b62...95a0
人立于天地之间,必然有我们的出路。