原文作者:PaperMoon 团队
假设你在 Polkadot Hub 上发行了自己的代币,现在你希望让用户能够随时用 DOT 来兑换它,不依赖中心化交易所,不需要撮合引擎,只需要一个流动性池。这正是本文要介绍的功能:Asset Conversion pallet。
一、Asset Conversion 是什么?
Asset Conversion pallet 是 Polkadot Hub 内置的去中心化资产兑换模块,采用 AMM(自动做市商,Automated Market Maker)机制,实现了 Uniswap V2 逻辑。
AMM 是 DeFi 世界里的一种定价方式:不需要买卖双方挂单撮合,而是通过数学公式(通常是 `x * y = k`)自动计算兑换价格。只要池子里有流动性,任何人都可以随时兑换。Uniswap V2 是以太坊上最经典的 AMM 实现,已被无数 DeFi 协议借鉴。Polkadot Hub 将同样的逻辑以 pallet 形式内置在链上,不需要部署合约即可使用。
pallet(保留英文):Substrate 框架中的功能模块,类似乐高积木,开发者可以组合不同 pallet 来构建区块链的功能。
Asset Conversion pallet 提供四个核心功能:
1. 创建流动性池:为两种资产建立一个新的兑换池
2. 添加流动性:向池子注入资产,获得 LP Token(流动性凭证)
3. Swap 兑换:用一种资产换取另一种资产
4. 撤出流动性:销毁 LP Token,取回原始资产
二、前置条件
开始操作前,请确保:
- 能够访问 Polkadot.js Apps 界面,并连接到 Asset Hub(Polkadot Hub)
- 钱包中有足够的资产用于兑换,以及覆盖交易手续费
- 已在 Asset Hub 上注册了至少一个资产(可参考本系列前两篇:《注册本地资产》和《注册外部资产》)
本文示例使用 DOT 和一个测试代币 PPM(资产 ID:1112,精度 10 位),基于 Polkadot Hub 本地测试环境演示。相同步骤适用于任何在 Asset Hub 上注册的资产。
三、Multilocation 快速回顾
本文会频繁用到 Multilocation(区块链坐标格式)来标识资产。在 Asset Hub 的语境下:DOT 原生代币的 Multilocation:
{
"parents": 0,
"interior": "Here"
}
```
`parents: 0` 表示"当前链内部";`interior: Here` 表示 Asset Hub 本链的原生代币。
本地资产(如 PPM,ID 1112)的 Multilocation:
```json
{
"parents": 0,
"interior": {
"X2": [{ "PalletInstance": 50 }, { "GeneralIndex": 1112 }]
}
}
```
PalletInstance: 50 指向 Asset Hub 上的 Assets pallet(pallet 编号固定为 50);
GeneralIndex: 1112 是该资产在 Assets pallet 中的 ID。
四、创建流动性池
如果两种资产之间还没有流动性池,需要先创建一个。创建操作会生成一个空池子,并同时创建对应的 LP Token(流动性凭证)资产。
LP Token 是流动性提供者的权益凭证:你向池子注入资产时会收到 LP Token,撤出流动性时需要销毁 LP Token 来换回原始资产。它代表你在整个池子中所占的份额。
操作步骤
第一步:在 Polkadot.js Apps 中进入外部调用页面
- 点击顶部菜单 Developer(开发者)
- 选择 Extrinsics(外部调用)
第二步:选择 pallet 和调用
- pallet 选择 `AssetConversion`
- 调用选择 `createPool`
第三步:填写字段
|
参数 |
含义 |
示例 |
|---|---|---|
|
asset1 |
流动性池中的第一种资产(通过 Multilocation 标识的链上资产) |
DOT |
|
asset2 |
流动性池中的第二种资产(另一种 Multilocation 资产) |
PPM(Asset ID: 1112) |
填写完毕后点击 Submit Transaction(提交交易)并签名确认。
验证
交易成功后,在 Polkadot.js Apps 的 Network → Explorer 页面查看链上事件,应能看到 `PoolCreated` 事件。事件中会显示为该池子分配的 `lpToken` ID(如 ID = 19),这个 ID 在后续操作中会用到。
五、添加流动性
流动性池创建后是空的,需要向其中注入资产才能开始兑换。`addLiquidity` 调用允许你向池子提供两种资产,并收到 LP Token 作为凭证。
你指定希望注入的数量(Desired)和愿意接受的最低数量(Min),pallet 会在这个范围内找到最优的注入比例,确保注入后不会造成过大的价格滑点。
滑点(Slippage):由于 AMM 的定价基于池子里两种资产的比例,每一笔注入或兑换操作都会轻微改变价格。设置最低数量参数,是在价格发生波动时的自我保护——不要以为填个默认值就好,实际操作时建议根据当前池子深度酌情调整。
操作步骤
第一步:进入 Developer → Extrinsics
第二步:选择 pallet 和调用
- pallet 选择 `assetConversion`
- 调用选择 `addLiquidity`
第三步:填写字段
|
参数 |
类型 |
作用 |
解释(开发者视角) |
|---|---|---|---|
|
asset1 |
Multilocation |
第一种资产 |
交易对中的基础资产(如 DOT) |
|
asset2 |
Multilocation |
第二种资产 |
交易对中的配对资产(如 PPM) |
|
amount1Desired |
Balance |
期望注入数量 |
希望向池子提供的 asset1 数量 |
|
amount2Desired |
Balance |
期望注入数量 |
希望向池子提供的 asset2 数量 |
|
amount1Min |
Balance |
最低接受数量 |
防止价格滑点过大时仍然成交(asset1) |
|
amount2Min |
Balance |
最低接受数量 |
防止价格滑点过大时仍然成交(asset2) |
|
mintTo |
AccountId |
LP 接收地址 |
LP Token 将铸造到的账户 |
数量单位说明:链上所有数量以最小单位(无小数)的 `u128` 整数表示。以精度为 10 的代币为例,`1 个代币 = 1,000,000,000,000`(即 10 的 12 次方)。本例中注入 1 DOT 和 1 PPM,两者的 `u128` 值均为 `1000000000000`。
在添加流动性之前,确保账户中已有足够数量的两种代币。
填写完毕后点击 Submit Transaction 并签名。
验证
在 Network → Explorer 中查看 `LiquidityAdded` 事件,确认流动性注入成功。
六、资产兑换(Swap)
Asset Conversion pallet 提供两种 Swap 模式,适用于不同场景。
6.1 模式一:精确输入换取最低输出(swapExactTokensForTokens)
场景:你有固定数量的代币 A,想换取尽量多的代币 B,但要保证换回来的 B 不低于某个最低值。
pallet 选择 `AssetConversion`,调用选择 `swapExactTokensForTokens`。
|
参数 |
类型 |
作用 |
解释(开发者视角) |
|---|---|---|---|
|
path |
Multilocation[] |
兑换路径 |
指定兑换路线(如 DOT → USDC → PPM),用于跨资产或跨链路由 |
|
amountIn |
Balance |
输入数量 |
你确定要花掉的资产数量(精确输入) |
|
amountOutMin |
Balance |
最小输出 |
可接受的最低获得数量,用于防止滑点与 MEV |
|
sendTo |
AccountId |
接收地址 |
兑换得到的资产发送到的账户 |
|
keepAlive |
bool |
账户保护 |
若交易后余额低于 Existential Deposit,则自动取消交易 |
`path` 数组示例(DOT → PPM):
- 第 0 个元素:DOT 的 Multilocation(`parents: 0, interior: Here`)
- 第 1 个元素:PPM 的 Multilocation(`parents: 0, interior: X2[PalletInstance:50, GeneralIndex:1112]`)
本例:花出 0.01 DOT(`u128 = 100000000000`),换取至少 0.04 PPM(`u128 = 400000000000`)。
6.2 模式二:精确输出控制最大输入(swapTokensForExactTokens)
场景:你明确知道自己需要多少代币 B,想用尽量少的代币 A 来换,同时设一个上限,不愿意花超过这个数量的 A。
pallet 选择 `AssetConversion`,调用选择 `swapTokensForExactTokens`。字段与模式一相同,区别只有两个:
|
参数 |
类型 |
作用 |
解释(开发者视角) |
|---|---|---|---|
|
amountOut |
Balance |
精确输出数量 |
你希望最终“必须收到”的目标资产数量 |
|
amountInMax |
Balance |
最大输入上限 |
你最多愿意支付的输入资产数量,超过则交易回滚 |
`path` 数组的顺序很重要:第一个元素是你付出的资产,最后一个元素是你收到的资产。顺序填反就是反向兑换,确认清楚再提交。
验证
两种 Swap 操作成功后,在 Network → Explorer 中均可看到 `SwapExecuted` 事件。
七、撤出流动性(Withdraw Liquidity)
当你想取回注入的资产时,使用 `removeLiquidity` 调用,通过销毁 LP Token 来换回原始资产。
pallet 选择 `AssetConversion`,调用选择 `removeLiquidity`。
|
参数 |
类型 |
作用 |
解释(开发者视角) |
|---|---|---|---|
|
asset1 |
Multilocation |
第一种资产 |
交易对中的基础资产(如 DOT) |
|
asset2 |
Multilocation |
第二种资产 |
交易对中的配对资产(如 PPM) |
|
lpTokenBurn |
Balance |
销毁 LP 数量 |
要赎回的 LP Token 数量(代表你在池子的份额) |
|
amount1MinReceived |
Balance |
最低接收数量 |
可接受的 asset1 最少返还量,防止滑点或池子变化 |
|
amount2MinReceived |
Balance |
最低接收数量 |
可接受的 asset2 最少返还量 |
|
withdrawTo |
AccountId |
接收地址 |
撤出资产发送到的钱包账户 |
`amount1MinReceived` 和 `amount2MinReceived` 是关键保护参数——如果撤出时能换回的资产少于你设定的最低值,交易会自动中止。池子内比例变化较大的时候,这两个数字要填得保守一些。
本例:销毁 0.05 LP Token,期望至少收回 0.004 DOT(`u128 = 40000000000`)和 0.04 PPM(`u128 = 400000000000`)。
验证
在 Network → Explorer 中确认 `LiquidityRemoved` 事件已触发。
八、本地测试环境搭建
在主网操作前,建议先用 Chopsticks 在本地搭建一个 Asset Hub 的镜像环境演练一遍。
# Fork Polkadot Asset Hub 到本地运行
# 中文:将 Polkadot Asset Hub 的最新状态复制到本地,所有操作在沙箱中进行,不影响真实网络
npx @acala-network/chopsticks \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml
测试 Kusama Asset Hub,替换配置文件名:
```bash
# Fork Kusama Asset Hub 到本地运行
# 中文:与上方命令相同,改为使用 Kusama 网络的状态
npx @acala-network/chopsticks \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/kusama-asset-hub.yml
```
启动后,在 Polkadot.js Apps 中连接到本地节点 `ws://127.0.0.1:8000`,即可在本地完整演练上述所有操作。流程和主网完全一致,测试通过再切主网。
总结
用 Asset Conversion pallet 做 DeFi,不是什么新鲜事——Uniswap V2 的逻辑在以太坊生态已经跑了好几年。Polkadot 做的事情是把这套逻辑直接内置在 Asset Hub 上,省掉了合约部署这一层。对开发者来说,最大的好处是:不用管合约安全、不用维护额外基础设施,用 Polkadot.js Apps 直接调用 extrinsic 就能搞定。
四个操作记住这个顺序:先建池(`createPool`),再注资(`addLiquidity`),然后就可以 Swap,最后撤资(`removeLiquidity`)。Swap 那两种模式选哪个,看你是"手里有多少花多少"还是"我要拿到这么多"——前者用精确输入,后者用精确输出。
阅读原文:https://docs.polkadot.com/chain-interactions/token-operations/convert-assets/

529

被折叠的 条评论
为什么被折叠?



