Skip to main content

DEX事例

为了在 IC 上实现 DEFI 应用,合约罐需要与代币合约罐和账本合约罐互动。这个样本 dapp 说明了如何促进这些互动。你可以在YouTube上看到一个快速介绍。

这个样本交换是用MotokoRust实现的,可以看到在 IC 上运行

架构

IC 的设计允许更复杂的链上计算。结合廉价的存储,有可能拥有链上订单簿。这个样本代码利用了这些功能,并将用户的余额和订单存储在交易所的合约罐里。样本交易所的功能可以浓缩为以下几个步骤。

  • 交易所保管资金(代币和 ICP 的机制不同,见下文)。

  • 交易所更新内部余额簿。

  • 用户在交易所进行交易,导致交易所更新其内部余额簿。

  • 从交易所提取资金,将保管权交还给用户。

实现接口

向交易所请求用户特定的分类账标识符。这个唯一的账户标识代表了交易所分类账中的一个用户专用子账户,使其能够区分用户的存款。

getDepositAddress: () -> (blob);

发起用户向交易所存款。如果用户想存入 ICP,交易所会将资金从用户特定的存款地址转移到其默认的子地址,并调整用户在 DEX 上的 ICP 余额。如果用户想存入 DIP 代币,交易所会尝试将批准的资金转移到其代币账户并调整用户的余额。

deposit: (Token) -> (DepositReceipt);

向交易所提出提现请求。如果用户有足够的余额,交易所会将资金送回给用户。

withdraw: (Token, nat, principal) -> (WithdrawReceipt);

向交易所下达新的订单。如果该订单与现有订单相匹配,它将被执行。

placeOrder: (Token, nat, Token, nat) -> (OrderPlacementReceipt);

允许用户取消已提交的订单。

cancelOrder: (OrderId) -> (CancelOrderReceipt);

请求用户在交易所的特定代币的余额。

getBalance: (Token) -> (nat) query;

费用

交易所有责任从交易中减去费用。这很重要,因为交易所必须为提款和内部转账支付费用。

通证交换演示

本节包含核心交易所功能的详细演练。大多数互动需要多个步骤,并通过使用提供的前端来简化。由于交易所的合约罐功能是公开的,高级用户可以使用dfx来与交易所互动。

存放 ICP

账本罐提供了一个独特的接口,因此与 ICP 的互动需要单独解决。

  • 用户调用getDepositAddress函数。响应包含一个唯一的账户标识符,代表一个由交易所控制的用户特定的子账户。交易所可以通过这个地址识别负责存款的用户。

  • 用户将 ICP 转移到获取的存款地址,并等待转移的完成。

  • 为了通知交易所,用户用 ICP 代币本金调用deposit。交易所将查看用户的子账户并调整用户在交易所的余额。在第二步中,交易所将把用户子账户中的资金转移到其默认的子账户中,交易所将所有的 ICP 保存在这里。

存放代币

存放代币是比较直接的,因为 DIP20 提供了一个更丰富的交互界面。

  • 用户调用代币罐的approve功能。这使交易所有能力代表用户向自己转移资金。

  • 与 ICP 存款类似,用户调用交易所的 "存款 "功能。交易所然后将批准的代币资金转移到自己身上,并调整用户的交易所余额。

下单

在向交易所存入资金后,用户可以下订单。一个订单由两个图元组成。from: (Token1, amount1)to: (Token2, amount2)。这些订单被添加到交易所。发生在这些订单上的事情是特定于交易所的实现。这个例子提供了一个简单的交易所,只执行完全匹配的订单。请注意,这只是一个玩具交易所,交易所的功能只是为了完整。提示:交易所有时会很贪婪;)

提取资金

与存入资金相比,提取资金更简单。由于交易所拥有资金的保管权,交易所会在 "取款 "请求时将资金送回给用户。交易所的内部余额也会相应调整。

常见错误

  • 并行执行。如果 canister 函数有await语句,就有可能出现执行交错的情况。为了避免 bug,有必要仔细考虑数据结构更新的位置,以防止双重花费的攻击。

  • 滑点。更高级的交换应该考虑到滑点,并确保限制的小数位。

  • 异步后没有恐慌:当恐慌发生时,状态会被回滚。这可能会导致交换的正确性问题。

当前最好的 DEX

sonic

Sonic 是互联网计算机 DeFi 中心,满足您所有的交换、流动性池和交易需求。它建立在互联网计算机上,以利用无限的可扩展性和超音速的交易终结性。