此篇文章教你如何在部署合约前就可以确定合约地址

一、合约源码

让我们创建一个工厂合约,它包含两个合约。

  • 第一个是Demo合约,其中一个函数可以读取全县所有者的钱包地址。
  • 第二个合约是工厂合约,它可以在部署Demo合约前获取其合约地址。

这个合约将使用Solidity文档中所说的CREATE2操作码:加“盐”的合约创建 / create2。

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;contract ContractDemo {    address public owner;    // Only owners can call transactions marked with this modifier    modifier onlyOwner() {        require(owner == msg.sender, "Caller is not the owner");        _;    }    constructor(address _owner) payable {        owner = _owner;    }    function getOwner() public view returns (address) {        return owner;    }    }contract Factory {    // Returns the address of the newly deployed contract    function deploy(        uint _salt    ) public payable returns (address) {        return address(new ContractDemo{salt: bytes32(_salt)}(msg.sender));    }    //  获取待部署合约字节码    function getBytecode()        public        view        returns (bytes memory)    {        bytes memory bytecode = type(ContractDemo).creationCode;        return abi.encodePacked(bytecode, abi.encode(msg.sender));    }    /** 获取待部署合约地址        params:            _salt: 随机整数,用于预计算地址    */     function getAddress(uint256 _salt)        public        view        returns (address)    {        // Get a hash concatenating args passed to encodePacked        bytes32 hash = keccak256(            abi.encodePacked(                bytes1(0xff), // 0                address(this), // address of factory contract                _salt, // a random salt                keccak256(getBytecode()) // the wallet contract bytecode            )        );        // Cast last 20 bytes of hash to address        return address(uint160(uint256(hash)));    }}

二、合约部署

在Remix中选择部署选项,并将要部署的合约切换到 Factory,点击部署:

部署被确认后,选择已部署的合约,我们就可以利用Factory合约获取Demo合约的合约地址了。
getAddress函数返回一个新的Demo实例的预计算的地址。传递一个salt参数,就可返回这个地址。为了简单,我们将使用111作为盐,但它可以是任何uint256值。
让我们把111作为参数传给getAddress函数,并在Remix中执行:

在这个特殊的例子中,预先计算的地址是0x9aBE429F1484622d7511aA9bc2C361EE6967b20b

接下来我们部署 Demo 合约,检查它是否正确部署到之前预先计算的地址上。在Remix中,在Factory合约实例中找到Deploy函数,并传递111作为盐。等待交易,并前往区块链浏览器确认它是否正确部署:

在交易细节部分(在区块链浏览器上)选择Internal Txns标签:

在页面上,我们看到CREATE2函数被我们的工厂合约调用,一个新的Demo合约被创建。点击创建的合约的地址,可以看到与之前预先计算的相同。

笔者整理了常见的一些智能合约并进行分类,如有需要请自取。
点击跳转