赞
踩
在以太坊链上,除了用户可以创建智能合约,智能合约同样也可以创建新的智能合约。两种常见的创建合约的方式:
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.20;
-
- import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
- import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
-
-
- contract MyToken {
- address public factory;//工厂合约地址
- address public token1;//代币合约地址1
- address public token2;//代币合约地址2
-
- constructor() payable{
- factory = msg.sender;
- }
-
- function initialize(address _token0, address _token1) external{
- require(msg.sender == factory, 'FORBIDDEN');
- token1 = _token0;
- token2 = _token1;
- }
- }
- // 工厂合约示例
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.20;
- import "./MyToken.sol";
- contract TokenFactory {
-
- mapping(address => mapping(address => address)) public getPair; // 通过两个代币地址查Pair地址
- address[] public allPairs; // 保存所有Pair地址
-
- function create(address token1,address token2) external returns(address pairAddr){
- // 创建新合约
- MyToken token = new MyToken();
- // 调用新合约的initialize方法
- token.initialize(token1,token2);
- // 更新地址map
- pairAddr = address(token);
- allPairs.push(pairAddr);
- getPair[token1][token2] = pairAddr;
- getPair[token2][token1] = pairAddr;
-
- }
-
- function getToken(address token1,address token2) external view returns(address) {
- return getPair[token1][token2];
- }
-
- function getFactory (address token) external view returns(address) {
- return MyToken(token).factory();
- }
-
- }
使用 keccak256 哈希函数计算合约的初始化代码(包括合约的字节码和构造函数的参数)的哈希值。
从创建者地址(通常是工厂合约的地址)和一个称为 salt 的值中构造创建合约时的合约地址。
使用 CREATE2 指令,通过调用一个现有合约的方法(通常是一个工厂合约)来创建新合约。
- // SPDX-License-Identifier: SEE LICENSE IN LICENSE
- pragma solidity ^0.8.20;
-
- contract Token1{
- uint256 public value;
-
- constructor(uint256 _value) {
- value = _value;
- }
- }
- // SPDX-License-Identifier: SEE LICENSE IN LICENSE
- pragma solidity ^0.8.20;
-
- import "./Token1.sol";
-
- contract TokenFactory1 {
-
- event ContractCreated(address indexed newContract);
-
- /// 使用 create2 创建合约
- function createContract(bytes32 _salt,uint _x) external{
- Token1 _contract = new Token1{salt: _salt}(_x);
- emit ContractCreated(address(_contract));
- }
-
- ///计算被部署合约地址
- function getContractAddr(bytes32 salt, bytes memory bytecode) external view returns(address){
- address newContract = address(
- uint160(
- uint256(
- keccak256(
- abi.encodePacked(
- bytes1(0xff),// 固定字符串
- address(this),// 当前工厂合约地址
- salt,// salt值
- keccak256(bytecode)// 被部署合约机器码的hash
- )
- )
- )
- )
- );
-
- return newContract;
- }
-
- // 获取被部署合约bytecode,参数_x为被部署合约构造函数的参数
- function getBytecode(uint _x) external pure returns(bytes memory) {
- bytes memory bytecode = type(Token1).creationCode;
- return abi.encodePacked(bytecode, abi.encode(_x));
- }
-
- }
在以太坊中,create 和 create2 都是用于创建新合约实例的指令,但它们有一些关键的区别:
地址生成方式:
合约地址可预测性:
用途:
重复部署:
总体而言,create2
提供了更多的地址生成灵活性和可预测性,特别是对于一些需要在合约中存储地址信息的应用场景。在某些情况下,选择使用 create
或 create2
取决于您的具体需求和设计。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。