在前面的两篇文章中,我们已经已经实现了Exchange合约的所有核心机制,包括定价功能、交换、LP代币和费用。看起来已经比较完善了,但是还缺少了一部分:工厂合约。本篇文章,我们就来实现它。
在前面的两篇文章中,我们已经已经实现了Exchange合约的所有核心机制,包括定价功能、交换、LP代币和费用。看起来已经比较完善了,但是还缺少了一部分:工厂合约。本篇文章,我们就来实现它。
事实上工厂合约充当的角色是Exchange合约的注册表:每个新部署的Exchange合约都在工厂中注册。这是一个重要的机制:任何Exchange合约都可以通过查询注册表找到。通过注册表,当用户尝试将一个Token代币交换为另一个Token代币(而不是以太币)的时候,Exchange合约可以通过工厂合约找到其他的Exchange合约。
工厂合约提供的另一个比较实用的功能是能够方便的部署Exchange合约而无需处理代码、节点、部署脚本和任何其他开发工具。
Factory实现了一个功能,允许用户只需调用该函数即可创建和部署Exchange合约。所以,今天我们还将学习一个合约如何部署另一个合约。
Uniswap 只有一份工厂合约,因此只有一份 Uniswap 交易对的注册表。然而,没有什么可以阻止其他用户部署自己的工厂,甚至是未在官方工厂注册的Exchange合约。虽然这是可能的,但这样的交易所不会被 Uniswap 认可,也无法通过官方网站使用它们来交换代币。
让我们看看代码如何实现:
工厂合约本质上是一个注册表,我们需要一个数据结构来存储Exchange合约,这应该是一个地址到地址的映射,它允许通过代币查找另外一个代币(1 个交换只能交换 1 个代币,还记得吗?)。
pragma solidity ^0.8.24;
import "./Exchange.sol";
contract Factory {
mapping(address => address) public tokenToExchange;
...
接下来是 createExchange
函数,它允许通过Token地址来创建和部署Exchange合约:
function createExchange(address _tokenAddress) public returns (address) {
require(_tokenAddress != address(0), "invalid token address");
require(
tokenToExchange[_tokenAddress] == address(0),
"exchange already exists"
);
Exchange exchange = new Exchange(_tokenAddress);
tokenToExchange[_tokenAddress] = address(exchange);
return address(exchange);
}
让我们来做个简单的梳理:
这里有两项检查:
1、第一个确保令牌地址不是零地址( 0x0000000000000000000000000000000000000000
)。
2、下一步确保Token合约还没有被添加到注册表中(默认地址值为零地址)。我们的想法是,我们不希望同一个Token代币有不同的Exchange合约,因为我们不希望流动性分散在多个Exchange合约中。它应该更好地集中在一个Exchange合约,以减少滑点并提供更好的汇率。
Exchange exchange = new Exchange(_tokenAddress);
创建一个新的 Exchange
合约实例,并将 _tokenAddress
传递给该合约的构造函数。
我们使用提供的代币地址实例化 Exchange,这就是我们之前需要导入“Exchange.sol”的原因。这种实例化类似于OOP语言中的类实例化,但是,在Solidity中, new
操作符实际上会部署一个合约。返回的值具有Exchange合约的类型,并且每个合约都可以转换为地址 - 这就是我们在下一行中所做的,以获取新交易所的地址并将其保存到注册表中。
tokenToExchange[_tokenAddress] = address(exchange);
return address(exchange);
将新创建的 Exchange
合约地址存储在映射 tokenToExchange
中,以便以后可以通过代币地址查找到对应的兑换合约。返回新创建的 Exchange
合约的地址。
要完成合约,我们只需要再实现一个函数 - getExchange
,这将允许我们通过另一个合约的接口查询注册表:
function getExchange(address _tokenAddress) public view returns (address) {
return tokenT...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!