3分钟Solidity: 9.3 通过 Create2 预计算合约地址

欢迎订阅专栏3分钟Solidity--智能合约--Web3区块链技术必学

如需获取本内容的最新版本,请参见 Cyfrin.io 上的 Precompute Contract 地址与 Create2(代码示例)

合约地址可以在合约部署前通过create2预先计算出来

scss 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract Factory {
    // 返回新部署合约的地址
    function deploy(address _owner, uint256 _foo, bytes32 _salt)
        public
        payable
        returns (address)
    {
        // 这种语法是一种无需汇编即可调用 create2 的新方法,你只需要传递 salt 参数。
        // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
        return address(new TestContract{salt: _salt}(_owner, _foo));
    }
}

// 这是使用汇编语言的旧方法
contract FactoryAssembly {
    event Deployed(address addr, uint256 salt);

    // 1.  获取待部署合约的字节码
    // 注意:_owner 和 _foo 是 TestContract 构造函数的参数
    function getBytecode(address _owner, uint256 _foo)
        public
        pure
        returns (bytes memory)
    {
        bytes memory bytecode = type(TestContract).creationCode;

        return abi.encodePacked(bytecode, abi.encode(_owner, _foo));
    }

    // 2.  计算要部署的合约地址
    //注意:_salt是一个随机数,用于生成地址。
    function getAddress(bytes memory bytecode, uint256 _salt)
        public
        view
        returns (address)
    {
        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff), address(this), _salt, keccak256(bytecode)
            )
        );

        // 注意:将哈希的最后20个字节转换为地址
        return address(uint160(uint256(hash)));
    }

    // 3. 部署合约
    // 注意:
    // 检查事件日志 Deployed,其中包含已部署的 TestContract 的地址。
    // 日志中的地址应与上述计算的地址一致。
    function deploy(bytes memory bytecode, uint256 _salt) public payable {
        address addr;

        /*
        注意:如何调用create2
        create2(v, p, n, s)
        在内存位置p到p + n处创建新合约代码
        并发送v wei
        返回新地址
        其中新地址 = keccak256(0xff + address(this) + s + keccak256(mem[p...(p+n)))的前20字节
        s = 大端序256位值
        */
        assembly {
            addr :=
                create2(
                    callvalue(), // 当前调用中发送的wei
                    // 跳过前32字节后开始实际代码
                    add(bytecode, 0x20),
                    mload(bytecode), // 加载前32字节中包含的代码大小
                    _salt // 来自函数参数的盐
                )

            if iszero(extcodesize(addr)) { revert(0, 0) }
        }

        emit Deployed(addr, _salt);
    }
}

contract TestContract {
    address public owner;
    uint256 public foo;

    constructor(address _owner, uint256 _foo) payable {
        owner = _owner;
        foo = _foo;
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

Remix Lite 尝试一下

相关推荐
程序员李程峰1 天前
基础知识——区块链钱包
web3·去中心化·区块链·同态加密·零知识证明·共识算法·分布式账本
BlockChain8882 天前
Web3钱包开发的最佳实践:从架构设计到安全实现
安全·web3
长安链开源社区2 天前
2025 长安链开发大赛正式启动!
web3·区块链
麦麦大数据2 天前
基于以太坊区块链+Spring Boot+Solidity智能合约的投票系统设计与实现
spring boot·后端·区块链·智能合约·投票系统
程序员李程峰3 天前
基础知识④链和代币之间的关系
web3·去中心化·区块链·智能合约·同态加密·共识算法·信任链
程序员李程峰3 天前
基础知识⑤ERC-20、BEP-20 和TRC-20 这三种流行的加密代币标准
web3·去中心化·区块链·智能合约·同态加密·共识算法·信任链
长安链开源社区4 天前
长安链开发大赛决赛入围名单揭晓
web3·区块链·共识算法
程序员李程峰4 天前
基础知识——各种钱包之间的联系与区别
web3·去中心化·区块链·智能合约·同态加密·零知识证明·信任链
程序员李程峰4 天前
基础知识①区块链钱包基础
去中心化·区块链·智能合约·同态加密·共识算法·信任链·分布式账本
程序员李程峰4 天前
基础知识②区块链的链是什么
web3·去中心化·区块链·智能合约·同态加密·共识算法·信任链