创建新合约的方式
create
- 使用
new
关键字
每个账户都有一个与之关联的 nonce
:对外部账户而言,每发送一个交易,nonce
就会随之 +1
;对合约账户而言,每创建一个合约,nonce
就会随之 +1
在合约中可以使用new
关键字来创建一个新的合约。例如
contract TokenFactory {
function createToken() external {
new Token();
}
}
新的合约地址是由sender
+nonce
进行 hash 计算得出
newContractAddress = hash(sender,nonce)
只要能够预测到sender
部署合约交易的nonce
值,就可以提前预测到新合约的地址
- 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));
}
}