这几天我写了一个DEX交易聚合器(2)

简介: 这几天我写了一个DEX交易聚合器

view函数的限制

刚开始的时候,我写过下面这个函数,用来获取两个代币间的所有路径,不包括三级路径。但实际上,这里面存在着一些问题。

WechatIMG66

首先,从业务逻辑上来说,tokenA > bases[i] > tokenB 路径,缺失了是否可配对的检查,应该对 tokenA-bases[i]bases[i]-tokenB 这两对分别检查 pair 是否都存在,通过 factory.getPair() 函数得到币对的 pair,如果 pair 不为零地址就说明是匹配的,如果不匹配就说明该路径是无效的。示例代码如下:

if (factory.getPair(tokenA, bases[i]) != address(0) 
    && factory.getPair(bases[i], tokenB) != address(0)) {
  paths.push([tokenA, bases[i], tokenB]);
}

其次,从 solidity 层面来说,数组的 push() 函数是不能在 view 函数中使用的,因为调用 push 函数会有固定的 gas 成本,但 view 函数是不能产生 gas 的,所以就用不了。因此,在 view 函数中使用数组只能用下标的方式进行赋值,如以下代码:

address[] memory tempPath = new address[](3);
tempPath[0] = tokenIn;
tempPath[1] = baseTokens[i];
tempPath[2] = tokenOut;

最后,返回二维数组,在默认情况下是不支持的,要用 ABIEncoderV2 才能支持,需要对合约添加以下指令才能使用:

pragma experimental ABIEncoderV2;

experimental 说明这还是实验性的,所以建议尽量少用,因为可能存在未知的 bug。

最后,我就完全抛弃了该函数,将路径的遍历和价格对比的逻辑都放在了同一个函数去完成。

链式授权转账

而我遇到的第二个错误则是关于授权转账的,也是因为我对授权转账的原理没真正理解导致的。

在我的实现中,兑换函数存在着几层不同合约之间的链式调用。假设我编写了 A 和 B 两个合约,两个合约都分别定义了 swap() 函数,在 A 合约的 swap() 函数中会调用 B 合约的 swap() 函数,而 B 合约的 swap() 函数再去调用 Uniswap 的路由合约的 swap() 函数。

A.swap() -> B.swap() -> Router.swap()

而在 Router.swap() 中会调用代币的 transferFrom() 函数将调用者 msg.sender 的代币转入 Pair 合约。所以,在兑换之前,还需要调用者对合约进行授权。一开始我以为,只要对 A 合约进行授权就可以了,当然,结果就是兑换失败了。后来,我又添加了链式授权,即调用者授权给 A,A 再授权给 B,B 再授权给 Router,但结果依然还是失败。最后,真正理解了授权转账的原理之后,只需要调用者授权给A,B 授权给 Router,并在 A 合约增加一步操作,调用代币的 transferFrom() 函数将调用者 msg.sender 的代币转入 B 合约,整个链条的兑换就能成功了。

首先,先搞清楚在整个链条中,每一步的 msg.sender 是谁?像这种合约之间的直接调用,msg.sender 都是上一步的调用者,如下图:

而在 Router.swap() 中会调用代币的 transferFrom() 函数将 msg.sender 的代币转入 Pair 合约,即是说,Router 会从 B 合约中将代币转入 Pair 合约,所以 B 合约中必须有代币才能完成转账。那 B 合约的代币从哪来呢?自然是要从 Caller 中来。只要 Caller 授权给 A,A 再用 transferFrom 将 Caller 的代币转给 B,如此就解决问题了。

总结

虽然这个 DEX 交易聚合器功能很简单,只有查询和兑换功能,但扩展起来很简单,后续还会接入 UniswapV3、Bancor、DODO 等,功能上也还可以再加入添加流动性、移除流动性等功能。

相关文章
|
6月前
|
消息中间件 NoSQL Kafka
118 Storm实时交易金额计算案例分析
118 Storm实时交易金额计算案例分析
39 0
|
9月前
|
区块链
去中心化交易所DEX开发[完整功能代码演示]
去中心化交易所DEX开发[完整功能代码演示]
|
4天前
|
消息中间件 存储 Kafka
用户购物行为分析(订单路径树)
用户购物行为分析(订单路径树)
64 0
|
9月前
|
API 数据处理 Python
量化合约交易连接交易所API合约开发Python源码详情
# 获取特定市场的行情数据 symbol = 'BTC/USDT' market = next(m for m in markets if m['symbol'] == symbol) ticker = exchange.fetch_ticker(market) print(ticker)
|
9月前
|
算法 数据处理 调度
(DeFi、DEX、去中心化游戏)矩阵公排系统DAPP合约逻辑部署源代码详情
// 构造函数,初始化矩阵的行数和列数 constructor(uint256 _rowCount, uint256 _columnCount) { rowCount = _rowCount; columnCount = _columnCount;
|
11月前
|
前端开发 安全 JavaScript
去中心化交易所dex开发源码规则分析
去中心化交易所dex开发源码规则分析
|
12月前
|
安全 区块链 开发工具
去中心化交易平台dex开发规则设计 | 去中心化交易平台dex源码示例
去中心化交易所(DEX)是一种基于区块链技术的交易所,它通过智能合约实现交易的执行和记录,避免了传统交易所存在的中心化风险和操作不透明等问题。如果您想开发一款去中心化DEX,需要考虑以下几个方面:
|
前端开发 算法 开发工具
这几天我写了一个DEX交易聚合器(1)
这几天我写了一个DEX交易聚合器
|
12月前
|
NoSQL 区块链 Redis
区块链聚合交易所平台开发源码实例分析
区块链聚合交易所平台开发源码实例分析
|
存储 区块链
迪斯克Disrupt DEX流动性质押挖矿系统开发详情介绍/案例开发/源码功能
Digital currency is another important application area of Web3.0 technology.Digital currency is a digital asset issued based on blockchain technology,which can achieve decentralized value exchange and storage.