Solidity进阶:通过合约部署合约

使用new在工厂合约部署合约

使用new在工厂合约部署合约,新的合约地址是通过工厂合约的地址和工厂合约对外发出交易的nonce值计算出来的。
new的用法很简单,就是new一个合约,并传入新合约构造函数所需的参数。其中Contract是要创建的合约名,x是合约地址,如果构造函数是payable,可以创建时转入_value数量的ETH,params是新合约构造函数的参数,规则如下:

Contract x = new Contract{value: _value}(params)

示例:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract Test {
    address public owner;
    uint public x;
    constructor(uint _x) {
        owner = msg.sender;
        x = _x;
    }
}

// 工厂合约:创建Test合约
contract TestFactory {
    Test public addr; // 部署的合约地址
    function create(uint _x) external {
        addr= new Test(_x);
    }
}

create2部署合约

create2方法是使用工厂合约的地址加盐值去计算新合约的地址,所以新合约的地址在被部署前就可以计算出来。

create2方法同样使用new来部署合约,加一个salt就可以使用create2来部署,规则如下:

Contract x = new Contract{salt: salt}(params)

部署函数如下:

event Deploy(address addr);
function deploy(uint _salt, uint _x) external {
	Test _contract = new Test{salt: bytes32(_salt)}(_x);
	emit Deploy(address(_contract));
}

预测地址是通过当前工厂合约的地址+salt+被部署合约的bytecode来计算,这就意味着工厂合约地址不变、salt不变、被部署合约不变的情况下,新合约地址也不会变,所以相同的salt只能使用一次,否则会发生重复部署合约的情况。新合约具有自毁功能,就可以使用之前的salt把合约部署到原来的地址上。
示例代码如下:

// 获取被部署合约bytecode,参数_x为被部署合约构造函数的参数
function getBytecode(uint _x) public pure returns(bytes memory) {
	bytes memory bytecode = type(Test).creationCode;
	return abi.encodePacked(bytecode, abi.encode(_x));
}

// 计算合约地址
function getNewAddr(bytes memory bytecode, uint _salt) public view returns(address) {
	bytes32 hash = keccak256(
		abi.encodePacked(
			bytes1(0xff),   // 固定字符串
			address(this),  // 当前工厂合约地址
			_salt,          // salt值
			keccak256(bytecode) // 被部署合约机器码的hash
		)
	);

    return address(uint160(uint(hash)));
}

Remix验证:计算的地址与实际部署的地址一致
在这里插入图片描述

通过内联汇编部署合约

使用内联汇编中的create(v, p, n)方法部署合约,返回地址不为0地址表示成功。

  • v:部署合约时发送的主币数量
  • p:内存中机器码开始的位置
  • n:内存中机器码的大小
event Deploy(address);
// _bytecode:被部署合约机器码
function deploy(bytes memory _bytecode) external payable returns(address addr) {
	assembly {
		addr := create(callvalue(), add(_bytecode, 0x20), mload(_bytecode))
	}
	require(addr != address(0), "deploy failed");

	emit Deploy(addr);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值