创建合约 #
一、合约创建概述 #
Solidity支持在合约中动态创建新合约:
| 方式 | 说明 | 地址确定性 |
|---|---|---|
| new | 创建新合约 | 不确定 |
| create2 | 创建新合约 | 确定 |
二、使用new创建合约 #
2.1 基本用法 #
solidity
contract Child {
uint256 public value;
constructor(uint256 _value) {
value = _value;
}
function getValue() public view returns (uint256) {
return value;
}
}
contract Factory {
Child[] public children;
event ChildCreated(address child, uint256 value);
function createChild(uint256 value) public returns (Child) {
Child child = new Child(value);
children.push(child);
emit ChildCreated(address(child), value);
return child;
}
function getChildCount() public view returns (uint256) {
return children.length;
}
}
2.2 创建并发送ETH #
solidity
contract PayableChild {
uint256 public value;
constructor(uint256 _value) payable {
value = _value;
}
receive() external payable {}
}
contract PayableFactory {
event ChildCreated(address child, uint256 value, uint256 balance);
function createChildWithValue(uint256 value) public payable returns (PayableChild) {
PayableChild child = new PayableChild{value: msg.value}(value);
emit ChildCreated(address(child), value, address(child).balance);
return child;
}
}
三、使用create2创建合约 #
3.1 基本概念 #
create2允许预先计算合约地址,地址由以下因素决定:
- 创建者地址
- 盐值(salt)
- 合约字节码
3.2 create2示例 #
solidity
contract DeterministicChild {
uint256 public value;
constructor(uint256 _value) {
value = _value;
}
}
contract DeterministicFactory {
event ChildCreated(address child, bytes32 salt, uint256 value);
function createChild(
uint256 value,
bytes32 salt
) public returns (DeterministicChild) {
DeterministicChild child = new DeterministicChild{salt: salt}(value);
emit ChildCreated(address(child), salt, value);
return child;
}
function computeAddress(
bytes32 salt,
bytes memory bytecode
) public view returns (address) {
bytes32 hash = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
keccak256(bytecode)
)
);
return address(uint160(uint256(hash)));
}
}
四、实际应用示例 #
4.1 工厂模式 #
solidity
contract Token {
string public name;
string public symbol;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
constructor(
string memory _name,
string memory _symbol,
uint256 _supply
) {
name = _name;
symbol = _symbol;
totalSupply = _supply;
balanceOf[msg.sender] = _supply;
}
}
contract TokenFactory {
struct TokenInfo {
address tokenAddress;
string name;
string symbol;
uint256 totalSupply;
address creator;
}
TokenInfo[] public tokens;
event TokenCreated(
address indexed tokenAddress,
string name,
string symbol,
uint256 totalSupply,
address creator
);
function createToken(
string memory name,
string memory symbol,
uint256 supply
) public returns (Token) {
Token token = new Token(name, symbol, supply);
tokens.push(TokenInfo({
tokenAddress: address(token),
name: name,
symbol: symbol,
totalSupply: supply,
creator: msg.sender
}));
emit TokenCreated(
address(token),
name,
symbol,
supply,
msg.sender
);
return token;
}
function getTokenCount() public view returns (uint256) {
return tokens.length;
}
}
4.2 钱包工厂 #
solidity
contract Wallet {
address public owner;
constructor(address _owner) {
owner = _owner;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function withdraw(uint256 amount) public onlyOwner {
payable(owner).transfer(amount);
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
receive() external payable {}
}
contract WalletFactory {
mapping(address => address[]) public userWallets;
event WalletCreated(address indexed owner, address wallet);
function createWallet() public returns (Wallet) {
Wallet wallet = new Wallet(msg.sender);
userWallets[msg.sender].push(address(wallet));
emit WalletCreated(msg.sender, address(wallet));
return wallet;
}
function getWallets(address user) public view returns (address[] memory) {
return userWallets[user];
}
}
五、总结 #
合约创建要点:
| 方式 | 说明 | 地址 |
|---|---|---|
| new | 动态创建 | 不确定 |
| create2 | 确定性创建 | 可预测 |
使用建议:
- 使用工厂模式管理合约
- create2用于需要预测地址的场景
- 注意Gas消耗
接下来,让我们学习ABI编码!
最后更新:2026-03-27