第三方依赖
第三方依赖是受控模块与之交互的外部 模块。通常,这些外部模块存在于不同的账户下。
多 DEX 路由器示例
多 DEX 路由器积极利用第三方依赖。与其提交多笔交易分别与不同 DEX 及其 swap 路径中的各自 entry 函数交互,不如让一个模块(或 脚本)将所有独立的 DEX 调用合并为一笔原子交易。多 DEX 路由器通过引用并调用每个第三方 DEX 模块中的函数来实现这一点。
来源
第三方依赖的可靠性和可用信息量会因其来源而异。具体来说,部分实例可能没有文档,且逻辑可能被重构。
应始终优先选择与链上已部署模块验证过的源代码,如 Git 仓库 和 本地源代码。如果这些不可用,还可以依赖其他可用代码,如 反编译代码、字节码 和基于 ABI 手工编写的代码。
Git 仓库
默认的 Move.toml
通过 git 仓库依赖包含了 AptosFramework
:
[dependencies.AptosFramework]
git = "<https://github.com/aptos-labs/aptos-framework.git>"
rev = "mainnet"
subdir = "aptos-framework"
当运行 Aptos CLI 命令时,依赖会自动更新并编译。
本地源代码
第三方源代码可以直接放入 sources
目录,基本上与自定义代码同等对待。
- {ControlledCode}.move
- {ThirdPartyCode}.move
- Move.toml
任何第三方依赖的升级都需要手动获取。
反编译代码
可以使用 Revela Compiler 对包的字节码进行反编译,重建 Move 代码:
aptos move decompile --package-path ./bytecode_modules
对应的 {ModuleName}.mv.move
文件会生成在 bytecode_modules
目录下。
- {ModuleName}.mv
- {ModuleName}.mv.move
- Move.toml
将其文件类型改为 {ModuleName}.move
并放入工作区的 sources
目录后,即可作为本地源文件引用。
- {ModuleName}.move
- Move.toml
反编译代码会保留链上执行行为,但结构会被重构。
字节码
Aptos CLI 支持下载 包 的字节码。
aptos move download --account {account_addr} --bytecode --package {package_name}
每个字节码依赖都需要独立的包,结构如下:
- 带有预定义包地址的
Move.toml
文件。 build/{ModuleName}/bytecode_modules
目录,内含字节码。- 空的 sources 目录。
受控模块在其 Move.toml
中引用该依赖包后,即可使用。
Aptos Token 示例
受控的 invoking_code.move
模块与外部 aptos_token
模块交互:
module invoker::invoking_code {
use aptos_token_objects_addr::aptos_token;
public entry fun wrapper_add_property(): u64 {
aptos_token::add_property(...);
}
}
以下命令可从主网获取所需的 AptosTokenObjects 包 字节码。
aptos move download --account 0x4 \
--bytecode --package AptosTokenObjects \
--output-dir ./aptos_token_bytecode_output/
- aptos_token.mv
- Move.toml
创建的 aptos_token
依赖包结构如下:
- aptos_token.mv
- Move.toml
[package]
name = "aptos_token"
version = "0.0.0"
[addresses]
aptos_token_module_addr = "0x4"
受控 invoking_code.move
模块的依赖列表会包含对字节码包的本地引用,从而支持编译。
[package]
name = "invoking_code"
[addresses]
invoker = "_"
[dependencies]
aptos_token = { local = "../aptos_token_objects_addr" }
ABI
可以通过读取包的 ABI,手工编写 Move 接口代码。需要注意的是,函数头必须完全一致,内部逻辑则无需实现。
所有可用的 public 和 entry 方法都在 ABI 中定义,包括名称、参数、返回值等。结构体和资源也会包含在内。
之后,接口代码与本地源代码同等对待。
Aptos Token 示例
以下是从 Aptos Explorer 获取的部分 AptosTokenObjects
ABI:
{
"address": "0x4",
"name": "aptos_token",
"friends": [],
"exposed_functions": [
{
"name": "add_property",
"visibility": "public",
"is_entry": true,
"is_view": false,
"generic_type_params": [
{
"constraints": [
"key"
]
}
],
"params": [
"&signer",
"0x1::object::Object<T0>",
"0x1::string::String",
"0x1::string::String",
"vector<u8>"
],
"return": []
},
...
]
}
可以手工编写接口 Move 文件,作为源文件使用。类似如下:
module 0x4::aptos_token {
// ...
public entry fun add_property<T: key>(
creator: &signer,
token: Object<T>,
key: String,
type: String,
value: vector<u8>,
) acquires AptosCollection, AptosToken {
abort 0
}
}
- {ControlledCode}.move
- aptos_token.move
- Move.toml