使用CREATE2
可以创建确定的合约地址,并且事先可以知道合约地址。如何在合约中使用CREATE2
? 其实很简单, 就是在创建合约时加入salt
参数即可,例如 Pair p = new Pair{salt: salt}()
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract Pair {
function foo(uint8 x) public returns(uint8) {
return x;
}
}
contract Test {
function f(uint8 x) public returns (uint8) {
return x;
}
function f(uint256 x) public returns (uint256) {
return x;
}
// 提前计算pair合约地址
function calculateAddr(address tokenA, address tokenB) public view returns(address predictedAddress){
require(tokenA != tokenB, "IDENTICAL_ADDRESSES"); //避免tokenA和tokenB相同产生的冲突
// 计算用tokenA和tokenB地址计算salt
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); //将tokenA和tokenB按大小排序
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
// 计算合约地址方法 hash()
predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
salt,
keccak256(type(Pair).creationCode)
)))));
}
// 创建合约
function mycreate(address tokenA, address tokenB) public returns(address addr) {
require(tokenA != tokenB, "IDENTICAL_ADDRESSES"); //避免tokenA和tokenB相同产生的冲突
// 计算用tokenA和tokenB地址计算salt
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
Pair p = new Pair{salt: salt}();
return address(p);
}
}
可以看到,calculateAddr
预先计算的合约地址与实际调用CREATE2
创建出来的地址是一样的。
更多关于solidity的内容可以看WTF的solidity教程, 非常推荐的入门教程:https://wtf.academy/solidity-advanced/Create2/