默认实现宏
概述
#[default_impl]
宏是一个实用工具,通过自动生成 trait 方法的默认实现,简化了 OpenZeppelin Stellar
合约 trait 的实现。这允许开发者只专注于重写他们需要自定义的方法,而宏会处理其余部分。
背景
当使用 Soroban 的 #[contractimpl]
宏时,所有方法(包括默认实现)必须显式地包含在实现块中,以便它们可以被生成的客户端访问。这是由于 Rust 宏的工作方式——它们无法访问不在宏作用域内的 trait 方法的默认实现。
#[default_impl]
宏通过自动为 OpenZeppelin Stellar trait 生成缺失的默认实现来解决这个问题。
支持的 Traits
#[default_impl]
宏支持以下 OpenZeppelin Stellar traits:
-
FungibleToken
-
FungibleBurnable
-
NonFungibleToken
-
NonFungibleBurnable
-
NonFungibleEnumerable
-
AccessControl
-
Ownable
#[default_impl]
宏有意不支持以下 traits:
-
FungibleAllowlist
-
FungibleBlocklist
-
NonFungibleRoyalties
这种限制是特意设计的:授权配置需要根据每个项目的安全需求进行特定的实现。通过要求手动实现这些 traits,我们确保 开发者仔细考虑并显式定义他们的授权逻辑,而不是依赖于通用的默认设置。
用法
要使用 [default_impl]
宏,当实现一个支持的 traits 时,将其放在 [contractimpl]
宏之上:
#[default_impl] // 重要:将其放在 `#[contractimpl]` 之上
#[contractimpl]
impl NonFungibleToken for MyContract {
type ContractType = Base;
// 只重写你需要自定义的方法
// 所有其他方法将自动使用其默认行为实现
}
工作原理
#[default_impl]
宏:
-
识别正在实现的 trait
-
确定用户显式定义了哪些方法
-
使用用户定义的方法覆盖默认实现
-
使用默认实现填充其余的方法(未由用户定义)
-
为 trait 添加任何必要的导入
这个过程确保了所有 trait 方法都可以被 #[contractimpl]
生成的客户端访问,同时允许开发者只编写他们需要自定义的代码。
示例
Fungible Token 示例
use soroban_sdk::{contract, contractimpl, Address, Env};
use stellar_tokens::fungible::FungibleToken;
use stellar_macros::default_impl;
#[contract]
pub struct MyToken;
#[default_impl]
#[contractimpl]
impl FungibleToken for MyToken {
type ContractType = Base;
// 只重写需要自定义行为的方法
fn transfer(e: &Env, from: Address, to: Address, amount: i128) {
// 自定义 transfer 逻辑在这里
}
// 所有其他 FungibleToken 方法将自动实现
}