Ownable

概述

Ownable 模块提供了一个简单的访问控制机制,其中合约具有一个可以被授予对特定函数的独占访问权限的账户(所有者)。此模式对于需要具有单个特权账户的简单授权系统的合约非常有用。

主要概念

所有权管理

该系统指定一个所有者,该所有者具有对标有 #[only_owner] 宏的函数的独占访问权限。为了使模块正常运行,理想情况下,必须在合约初始化期间设置初始所有者。

与 Access Control 模块一样,所有权转移以两步流程实现,以防止意外或恶意的接管:

  1. 当前所有者通过指定新所有者和到期时间 (live_until_ledger) 发起 转移。

  2. 指定的新所有者必须*显式接受*转移才能完成它。

在转移被接受之前,原始所有者保留完全控制权,并且可以通过发起新的转移或使用 live_until_ledger0 来覆盖或取消转移。

所有权放弃

Ownable 模块允许所有者永久放弃合约的所有权。这是一个单向操作,无法撤消。放弃所有权后,所有标有 #[only_owner] 的函数将永久无法访问。

此功能对于需要在初始设置阶段后完全去中心化的合约非常有用。

过程宏

该模块包含一个过程宏,以简化所有者授权检查:

@only_owner

确保在执行函数之前,调用者是所有者:

#[only_owner]
pub fn restricted_function(e: &Env, other_param: u32) {
    // 函数体 - 只有所有者才能访问
}

这会扩展为从存储中检索所有者并在执行函数体之前需要授权的代码。

使用示例

这是一个使用 Ownable 模块的简单示例:

use soroban_sdk::{contract, contractimpl, Address, Env};
use stellar_access::ownable::{self as ownable, Ownable};
use stellar_macros::only_owner;

#[contract]
pub struct MyContract;

#[contractimpl]
impl MyContract {
    pub fn __constructor(e: &Env, initial_owner: Address) {
        // 设置合约所有者
        ownable::set_owner(e, &initial_owner);
    }

    #[only_owner]
    pub fn update_config(e: &Env, new_value: u32) {
        // 只有所有者可以调用此函数
        // 实现...
    }

    // 任何人都可以访问此函数
    pub fn get_config(e: &Env) -> u32 {
        // 实现...
        42
    }
}

优点和缺点

优点

  • 简单明了的所有权模型

  • 安全的两步所有权转移流程

  • 永久放弃所有权的选项

  • 易于与过程宏集成

  • 为重要操作发出事件

缺点

  • 限制为单个特权账户(与基于角色的系统相比)

  • 一旦放弃所有权,特权函数将永久无法访问