Skip to main content

创建新合约的方式

create

  1. 使用new关键字

每个账户都有一个与之关联的 nonce:对外部账户而言,每发送一个交易,nonce 就会随之 +1;对合约账户而言,每创建一个合约,nonce 就会随之 +1

在合约中可以使用new关键字来创建一个新的合约。例如

contract TokenFactory {
function createToken() external {
new Token();
}
}

新的合约地址是由sender+nonce进行 hash 计算得出

newContractAddress = hash(sender,nonce)

只要能够预测到sender部署合约交易的nonce值,就可以提前预测到新合约的地址

  1. create2

create2方法部署的新合约地址是由几个参数通过hash计算出来的。也就是只要参数相同,就可以提前计算出新创建合约的地址

new_address = hash(0xFF, sender, salt, bytecode)
  • 0xFF: 一个常量,防止与create方法发生冲突。比如设置为 0
  • sender: sender的地址,如果是合约创建,则为当前合约地址
  • salt: 由sender提供的盐
  • bytecode: 待部署合约的字节码

例如: Uniswap部署新的Pair合约的代码

bytes memory bytecode = type(UniswapV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
// 0xFF,部署着地址,待部署合约字节码,盐
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}

提前获取被部署合约地址的代码示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;
//Use Create2 to know contract address before it is deployed.
contract DeployWithCreate2 {
address public owner;
constructor(address _owner) {
owner = _owner;
}
}
contract Create2Factory {
event Deploy(address addr);
// to deploy another contract using owner address and salt specified
function deploy(uint _salt) external {
DeployWithCreate2 _contract = new DeployWithCreate2{
salt: bytes32(_salt) // the number of salt determines the address of the contract that will be deployed
}(msg.sender);
emit Deploy(address(_contract));
}

// get the computed address before the contract DeployWithCreate2 deployed using Bytecode of contract DeployWithCreate2 and salt specified by the sender
function getAddress(bytes memory bytecode, uint _salt) public view returns (address) {
bytes32 hash = keccak256(
abi.encodePacked(
bytes1(0xff), address(this), _salt, keccak256(bytecode)
)
);
return address (uint160(uint(hash)));
}
// get the ByteCode of the contract DeployWithCreate2
function getBytecode(address _owner) public pure returns (bytes memory) {
bytes memory bytecode = type(DeployWithCreate2).creationCode;
return abi.encodePacked(bytecode, abi.encode(_owner));
}
}

参考文档