Skip to main content

Command Palette

Search for a command to run...

智能合约实例-7: 使用 Create2 预计算合约地址

Published
2 min read

实现功能

使用create2, 可以在部署合约之前预先计算合约地址

源码示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;


// 创建合约时,合约的地址是根据创建合约的地址和随着每次合约创建而增加的计数器计算出来的。

// 如果您指定选项salt(bytes32 值),则合约创建将使用不同的机制来提供新合约的地址:

// 它将根据创建合约的地址、给定的盐值、创建合约的(创建)字节码和构造函数参数来计算地址。


contract Factory {
    // 返回新部署的合约地址  
    function deploy(
        address _owner,
        uint _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, uint salt);

    // 1. 获取要部署的合约字节码
    // 注意:_owner 和 _foo 是 TestContract 构造函数的参数
    function getBytecode(address _owner, uint _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, uint _salt)
        public
        view
        returns (address)
    {
        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
        );

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

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

        /*
        注意: 如何调用 create2 ? 

        create2(v, p, n, s)
        使用内存 p 到 p + n 的代码创建新合约
        并发送 v wei
        并返回新地址
        where new address = 前 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n)))
              s = big-endian 256-bit value
        */
        assembly {
            addr := create2(
                callvalue(), // wei sent with current call
                // Actual code starts after skipping the first 32 bytes
                add(bytecode, 0x20),
                mload(bytecode), // Load the size of code contained in the first 32 bytes
                _salt // Salt from function arguments
            )

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

        emit Deployed(addr, _salt);
    }
}


contract TestContract {
    address public owner;
    uint public foo;

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

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

    function convert(uint256 n) public pure returns (bytes32) {
        return bytes32(n);
    }
}

实例演示

  • 采用 Create
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;


contract CreateDemo {
    function deploy (address owner, uint foo) public returns(address) {
        TestContract new_address = new TestContract(owner, foo);

        return address(new_address);
    }
    // 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4,1     ==>      0xD3e2008b4Da2cD6DEAF73471590fF30C86778A48


    // create 计算地址方式 
    function getCreateAddress(address senderAddress, uint8 nonce) public pure returns(address){

        address nonce0 = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), senderAddress, bytes1(nonce))))));
        // 注意:将最后 20 个字节的哈希值转换为地址
        return nonce0;

        // nonce 0 : 0xa131AD247055FD2e2aA8b156A11bdEc81b9eAD95
    }


    // keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))[12:]

}

contract TestContract {
    address public owner;
    uint public foo;

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

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

    function convert(uint256 n) public pure returns (bytes32) {
        return bytes32(n);
    }
}

关注更多

Web3 技术与应用,研究实践分享!

Twitter: @AntCaveClub

蚁穴Web3社区: https://antcave.club/

1.1K views

More from this blog

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。 因为市场完全依赖于他们的操纵, 他们在任何游戏中,拥有绝对优势。 因为Axiom等工具具备监控功能,所以他们也会经常替换钱包: 💰钱包实时监控:https://axiom.trade/@0xcii 📱钱包监控:https://debot.ai?inviteCode=174709 分享一批上周的链上顶级内幕钱包🧵👇 我花了很多时间在链上筛选这些钱包! 请关注我 @AntCaveClub,点赞并转发——确保不再...

Apr 18, 20251 min read32

这个钱包昨天一笔交易用 0.9 Eth 赚了 8.4 Eth

几乎是交易市场的一条定律: 不管新闻是真假, 它带来的影响是真的就行。 昨天,我们知道 特朗普团队发币这一消息后, 第一时间关注市场上的新币。 发现了 ETH 链上的 $DJT 代币, 当时市值仅 $450K , 而现在达到了 $ 3.3 M 。 由于信息较少, 小入了一手, 然后发公告了,估计都跌麻木了没人上车,结果今天获利 8 倍。 另一个值得 关注的信息是特朗普最大主题代币 $TRUMP 今日突然下跌 -40% 我们通过链上数据观察, 这部分游资进入了 $DJT 而这个...

Jun 18, 20241 min read355

Ton 会成为真正的独角兽,因为它拥有

TON 才是独角兽。 正确使用TON 工具能给你带来财富。 SOL / ETH 的 memcoins 交易良好,但 TON 正在超越它。 以下 5 个基本工具可帮助你获得 10-100 倍收益 1⃣️ TON 的土壤 显然,TON 上的 memcoin 越来越受欢迎,TON 市值已超过 160 亿美元。 $NOT 上线币安,其涨幅众所周知。其他大量 TON memcoin 会增值 10-100 倍。让我们学习一下用于搜寻早期 TON 山寨币的主要工具…… 2⃣️ Defilla...

Jun 5, 20241 min read109

昨晚用 1 Eth 赚了 10 Eth ! 没想到睡觉起来就这样了。

昨天睡觉前搞了 $DEW 建仓时市值 500K 附近, 现在 6M 左右了, 一晚上 10 倍。 最近确实以太坊链上出金狗,千万市值天天都有。 也主要因为我睡着了, 睡之前和朋友讲了下,建议他上车,他说他在打球🏀 推荐 $DEW 的主要原因是, 我前几天不是推了 $PEW ,推的时候市值 $2 M 附近,结果 3天一路干到了 $94 M , 大概快有 50 倍... 当时跟朋友讲让他上点车, 他在追剧,忘上车了, 我说下次一定。 他推荐我看《庆余年》,说这个好看。 昨晚看到出...

Jun 1, 20241 min read324

专注 Web3 网络赚钱模式, 区块链实践教程与交流分享

127 posts

专注 Web3 网络赚钱模式, 实践教程与交流分享 !

加入社群 | 订阅Youtube