Sui.

帖子

分享您的知识。

BigSneh.
Jul 30, 2025
专家问答

智能合约能否在 Sui 中拥有并改变它自己的对象状态?

我想理解 Sui Network 的这一方面,因为我要么构建、调试,要么部署涉及这个领域的东西. 我想详细解释这个机制或功能的工作原理,以及相关的 CLI 用法、移动代码结构或架构概念. 我的目标是获得足够的清晰度,将这些知识应用到一个真实的项目中——无论是自定义智能合约、NFT系统、钱包集成还是DeFi工具. 与 EVM 链相比,Sui Network 具有独特的功能,因此我对它的与众不同之处以及它如何影响开发最佳实践特别感兴趣. 有示例代码、命令行示例或典型错误需要注意会有所帮助,尤其是在使用 Sui CLI、SDK 或在本地网络/测试网上部署时. 归根结底,我希望避免常见错误,遵循最佳的安全原则,并确保我正在开发的功能在现实条件下表现出预期.

  • Sui
  • Architecture
  • Move
7
15
分享
评论
.

答案

15
Paul.
Paul4340
Jul 31 2025, 05:35

在 Sui 中,智能合约不能直接拥有或改变自己的对象状态. 取而代之的是,合约通过所有权模型与对象进行交互,其中对象归特定地址(例如用户的钱包或账户)所有. Sui 中的智能合约可以定义和修改其他方(例如用户)拥有的对象的状态,但他们自己不能拥有对象.

关键概念:

*对象所有权:对象归地址所有,而不是合同. *与对象的交互:合约可以操纵对象的状态,但前提是它可以通过所有权或可变引用访问该对象.

示例代码:

module MyModule {
    use sui::object::{Object, move_to};

    public fun update_object_state(obj: &mut Object) {
        // Modify the state of the object owned by someone else
        obj.some_field = 42;
    }
}

CLI 用法:

部署时,合约只能操作地址拥有的对象,不能操作其自身.

最佳实践:

  • 确保合约遵守 Sui 的所有权模型,在合约和用户账户之间传递对象.
  • 始终安全地管理权限,以避免未经授权访问对象状态.
8
评论
.
Ashford.
Jul 31 2025, 06:34

智能合约能否在 Sui 中拥有和改变自己的对象状态?

不,在 Sui 中,智能合约不能直接拥有或改变自己的状态. 资源(如硬币对象或自定义对象)的所有权和变更受用户账户或授权地址的约束,而不是合约本身.

关键点:

*所有权:Sui 中的智能合约是无状态的;它们定义逻辑,但自己不拥有或存储状态. *资源所有权:资源(如硬币或自定义对象)必须归地址或实体所有,而不是由合同拥有.

典型流程:

  1. 账户所有权:地址或用户拥有该物品(例如硬币).
  2. 智能合约执行:合约可以修改所有者传递给它的对象的状态.

示例流程:

  1. 用户创建物体(例如,硬币).
  2. 用户将对象传递给合约进行突变. 3.合约修改了对象,但不拥有它.

示例移动代码:

public fun mutate_object(owner: &mut Address, coin: &mut Coin) {
    Coin::transfer(coin, &mut owner);
}

CLI 示例:

部署合约并调用一个函数来改变对象的状态:

sui client publish --gas-budget 10000 --module <module-path>

常见错误:

*所有权混乱:尝试修改或访问不属于合同的状态将导致错误. &mut*可变性不正确:确保传递给合约的对象是可变的 ().

最佳实践:

*确保正确的所有权:确保传递给合同的对象归属正确的地址. *使用 Localnet/Testnet 进行测试:在部署到主网之前,请务必验证合约逻辑和状态变化.

7
评论
.
Benjamin XDV.
Jul 31 2025, 09:42

在 Sui 中,由于 Sui 以对象为中心的所有权模型,智能合约(Move 包)无法直接拥有或改变对象本身. 对象必须归地址其他对象所有或标记为共享/不可变——包仅包含代码逻辑. 对于自主突变,您通常使用共享对象(达成共识)或动态字段,其中父对象控制子对象. 这与 EVM 的合约存储有根本的不同,它要求通过交易而不是内部合约操作进行明确的所有权转移. 常见模式包括将对象打包在管理员控制的容器中或使用基于功能的设计**来安全地管理状态突变.

6
评论
.
theking.
Jul 30 2025, 11:13

是的,在 Sui 中,智能合约可以改变自己的对象状态,但是它不能独立拥有对象. 在 Sui 的以对象为中心的模型中,每个对象必须归一个地址、另一个对象所有或标记为共享. 智能合约没有像 EVM 链(例如以太坊)那样的地址,因此您必须依靠对象所有权模式,例如对象包装的数据结构共享对象来在交易中保持和改变状态.

要更新合约的内部状态,您通常会设计一个structkey能够保存状态数据),将其传递给您的entry函数,并通过引用执行更新. 此结构的所有权归用户所有,或标记为共享以允许更广泛的访问权限.

示例 — 通过拥有的对象改变内部状态

module example::counter {
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};

    struct Counter has key {
        id: UID,
        value: u64,
    }

    public entry fun create(ctx: &mut TxContext): Counter {
        Counter { id: object::new(ctx), value: 0 }
    }

    public entry fun increment(counter: &mut Counter) {
        counter.value = counter.value + 1;
    }
}

在此示例中,create初始化一个Counter对象. increment只能通过传递对该对象的可变引用来调用. 所有权属于用户或其他对象,而不是合同本身.

用于全局访问的共享对象

shared如果您的合约需要多个用户与同一个对象进行交互,请将其标记为. 示例用例:DAO、全球计数器、链上游戏.

public entry fun increment_shared(counter: &mut Counter) {
    counter.value = counter.value + 1;
}

在部署时或通过显式函数,必须共享对象:

sui client call \
  --function share_object \
  --module counter \
  --package <package_id> \
  --args <counter_id>

CLI 提示:

  • 要查看所有权,请执行以下操作:sui client object <object_id>
  • 变异:在--mut``&mut入口函数中使用标志或定义
  • 对于共享突变:确保对象像突变shared之前一样发布

SDK 集成 (TS):

tx.moveCall({
  target: `${packageId}::counter::increment`,
  arguments: [tx.object(counterId)]
});

最佳实践:

  • 除非需要,否则请避免尝试将对象引用存储在其他对象中.
  • 如果你需要全局可变性,共享对象是正确的方法.
  • UID``key确保对象可以在事务中持续存在的用途和能力.
  • 务必验证调用者是否有权进行变更,尤其是共享对象.

常见错误:

  • Cannot find mutable reference— 你传递的是一个不可变的对象,其中需要可变对象.
  • Object is not shared— 你正在尝试改变一个尚未共享的对象.
  • Type mismatch— 通常是由不正确的泛型或滥用引用引起的.

你可以在 Sui 的开发者文档 中阅读有关所有权和共享对象的更多信息.

5
评论
.
SuiLover.
Jul 30 2025, 11:30

在Sui网络中,智能合约不能 “拥有” 传统EVM意义上的对象,因为所有权始终与地址或其他对象相关联. 但是,用 Move 编写的智能合约可以定义和改变自己的自定义状态对象,这些对象通常是用户传入的共享对象或拥有的对象.

关键概念

  1. Sui 中的对象所有权: 每个对象都归以下所有者:

用户地址(地址),

另一个对象(嵌套所有权),

共享(所有人均可访问),

不可变(发布后无法更改).

  1. 智能合约状态: 要创建合约状态,开发人员在 Move 模块中定义结构并将这些结构的实例作为对象发布. 然后将这些对象传递到入口函数,在那里可以读取或修改它们的状态.

3.突变状态: 要改变智能合约的对象状态,你必须:

将对象作为 &mut 传递给函数.

确保它是可变的,并根据需要拥有/共享.

拥有正确的访问权限.

  1. 全局状态的共享对象: 如果你想要全局的、全合约的状态,你可以使用共享对象:

struct Counter 有密钥、存储、复制 { 值:u64, }

公开参赛乐趣增量(计数器:&mut 计数器){ 计数器值 = 计数器值 + 1; }

  1. 发布共享对象:

共享对象必须在初始化时明确创建和共享.

使用 move call 或 Sui CLI--gas-budget 和--shared-object-inputs 与它们进行交互.

  1. 部署流程示例:

使用 sui move publish 部署模块.

调用入口函数来创建共享对象:

sui 客户致电
<PACKAGE_ID>--包装
--模块计数器
--函数 create_counter
--args 0
--天然气预算 10000

然后使用共享对象的对象 ID 调用 increment.

  1. 局限性:

智能合约不像在 Solidity 中那样存储内部状态.

它们对明确传递给他们的对象进行操作.

模块内不存在永久的 “合约存储”.

  1. 安全性和所有权:

您必须手动或通过权能验证所有权.

通常使用诸如 AdminCap 或白名单之类的访问控制模式来控制突变.

  1. 最佳实践:

避免不必要地共享物品,以限制气体的使用和争用.

利用功能或地址检查来安全地管理访问权限.

Use 有密钥和正确存储,以实现对象持久性和可变性.

  1. 需要注意的 CLI 命令:

sui 客户端调用函数调用.

sui 客户端对象来检查对象数据/状态.

sui move test 用于单元测试状态逻辑.

4
评论
.
shamueely.
Jul 30 2025, 11:38

在 Sui 中,用 Move 编写的智能合约无法真正拥有自己的对象,就像自引用 EVM 合约可能自主持有和改变内部状态一样. Sui 的以对象为中心的架构意味着所有对象都必须明确传递到交易上下文中,并且它们的所有权要么基于帐户,要么是共享的. 智能合约本身是无状态的——它们只定义逻辑. 实际状态存在于 Move 对象中,必须将其传递给函数以进行读取或突变.

要改变合约的状态对象,你需要对模块进行结构化,使其数据(通常存储在has key结构中)是:

*由用户地址拥有(对账户范围逻辑很有用), ***通过 share_object()**共享(以支持 DeFi、DAO、游戏等中的多个参与者).

使用共享对象时,必须使用函数进行标记,entry并将共享对象作为&mut引用传递.

以下是可以变异的共享状态的示例:

module my_app::vault {
    use sui::object::{UID, ID};
    use sui::tx_context::TxContext;

    struct Vault has key {
        id: UID,
        balance: u64,
    }

    public fun init(ctx: &mut TxContext): Vault {
        Vault { id: object::new(ctx), balance: 0 }
    }

    public entry fun deposit(vault: &mut Vault, amount: u64) {
        vault.balance = vault.balance + amount;
    }
}

在此示例中,Vault如果您希望多个用户通过entry函数访问该对象,则必须是共享对象. 部署时,您可以像这样共享对象:

sui client call --function share_object --args <vault_id>

一旦共享,任何entry函数都可以对对象进行变异——前提是它将其作为输入接收. Sui 通过所有权规则和版本控制来确保安全,以防止出现竞争情况.

要详细了解 Sui 中的智能合约如何与对象状态、共享访问权和所有权进行交互,请访问: https://docs.sui.io/build/programming-model/object-basics

这种方法使Sui与EVM链区分开来. 你不能直接改变内部合约存储. 相反,您可以对显式传递到逻辑函数的 Move 对象进行变异,从而增强并发性和可验证性.

4
评论
.
Alya.
Alya-14
Jul 30 2025, 17:29

不,智能合约(Move 模块)不能在 Sui 中直接拥有或改变自己的对象状态.

对象是由地址、其他对象拥有或共享的头等实体,不是由模块共享. 状态变更是通过将对象作为可变参数的函数发生的,所有权规则在事务级别强制执行.

示例:

struct Counter has key { id: UID, value: u64 }
public entry fun increment(counter: &mut Counter) { counter.value = counter.value + 1 }

increment``Counter只有当交易将可变引用传递给发送者拥有的对象时,该函数才能发生变化. 该模块本身没有任何状态.

使用 ob sharedjects (transfer::share_object) 实现持久的、全局可访问的状态. 务必使用线性类型规则验证所有权object::is_owner()并遵循线性类型规则.

4
评论
.
Arnold.
Arnold3036
Jul 31 2025, 08:16

是的,与 EVM 的无状态设计不同,Sui 智能合约(Move 包)可以通过共享对象动态对象字段拥有和改变自己的状态.

####关键机制

  1. 共享对象: -任何人都可以全局变异(有规则).
    -由(包裹地址)定义key + store并由0x0(包裹地址)拥有.
  struct ContractState has key, store {
      id: UID,
      value: u64,
  }
  1. 动态对象字段: -包可以通过存储其 ID 来 “拥有” 对象.
  fun add_state(ctx: &mut TxContext) {
      let state = ContractState { id: object::new(ctx), value: 42 };
      transfer::share_object(state); // Make it globally mutable
  }

###为什么 Sui 独一无二 -没有 “msg.sender”:访问控制是通过 Move 的类型系统进行的,而不是 EOA.
-并行突变:共享对象支持并发写入(与 EVM 的序列化 Tx 不同).

###CLI 示例

# Call a function that mutates shared state
sui client call \
    --function update_state \
    --module your_module \
    --package 0xYOUR_PACKAGE \
    --args 0xSHARED_OBJECT_ID 100 \ # New value
    --gas-budget 10000000

###常见陷阱

  1. 过度共享share_object除非确实需要,否则应避免使用(transfer::transfer用于私人所有权).
  2. sui::lock竞赛条件:为并行访问而设计(例如使用).
4
评论
.
290697tz.
Jul 30 2025, 11:35

是的,Sui 中的智能合约可以改变自己的对象状态,但它必须通过明确传递给其函数的对象来实现. 在 Sui 的对象模型中,没有像以太坊那样的内部合约存储;相反,状态是通过可变对象来维护的. 这些对象可以归用户所有或通过网络共享. 要改变状态,您需要定义一个具有 has 密钥能力的结构,然后编写接受对该对象的 &mut 引用的入口函数. 共享对象允许全局访问,当多个用户需要与同一状态进行交互时,共享对象是必需的. 变更共享对象需要将该函数标记为公共入口,并在调用期间传递正确的对象 ID. 合约不直接 “拥有” 状态;相反,它们对通过参数传递给他们的数据进行操作. 您可以使用功能或通过检查发件人地址来强制实施访问控制. 这种设计支持高并行度、更好的可扩展性和精细的权限. 总体而言,Sui中的智能合约通过在严格的所有权和访问规则下修改Move定义的对象来改变状态.

3
评论
.
Evgeniy CRYPTOCOIN.
Jul 31 2025, 09:09

是的,Sui 智能合约(Move 模块)可以通过以下方式拥有和改变自己的对象:

  1. 拥有的对象-在模块初始化期间创建(存储在包 ID 下).
  2. 共享对象-标记shared为允许多写者访问.

###与 EVM 的主要区别:无外部所有者-对象可以属于包本身.
直接突变— 无需批准系统(与 ERC-20 不同).

示例图案:

struct MyState has key { id: UID, value: u64 }  

// Module can mutate its own object  
public fun update(self: &mut MyState) { self.value += 1 }  

注意: -自有物品的存储成本.
-shared用于全局状态.

*(Sui 的对象模型支持自主合约,无需代理钱包. ) *

3
评论
.
Bekky.
Bekky1762
Jul 31 2025, 10:27

###1. 核心概念:以对象为中心的所有权 与 EVM 的存储变量不同,Sui 智能合约通过自有对象运行,这些对象可以根据严格的所有权规则进行变异.

####主要功能 | 功能 | Sui | EVM | | --------------| -----| | 状态表示 | 带有 UID 的对象 | 存储变量 | | 所有权 | 显key性能力 | 隐含合同 | | 可变性 | &mut参考文献 | 直接修改 |


###2. 移动实施模式

####自有合约

module my_contract::state {
    use sui::object::{Self, UID};
    use sui::transfer;
    use sui::tx_context;

    // Contract's state object
    struct ContractState has key, store {
        id: UID,
        counter: u64
    }

    // Initialize and own the state
    public fun init(ctx: &mut tx_context::TxContext) {
        let state = ContractState {
            id: object::new(ctx),
            counter: 0
        };
        transfer::share_object(state); // Make shared for mutability
    }

    // Mutate owned state
    public entry fun increment(state: &mut ContractState) {
        state.counter = state.counter + 1;
    }
}

####所有权模式 | 模型 | 代码模式 | 用例 | | --------------------| ----------| |共享| | transfer::share_object全局可变状态 | transfer::freeze_object|不可变| | 配置 | |自有| | 用户资产 transfer::transfer|


###3. CLI 交互

####部署有状态合约

sui client publish --gas-budget 1000000000
# Output: 
# - Package ID: 0x123...
# - Shared Object ID: 0x456...

####变异状态

sui client call \
  --package 0x123 \
  --module state \
  --function increment \
  --args 0x456 \  # Shared object ID
  --gas-budget 100000000

###4. 架构注意事项

####并发控制

// Use `version` field for optimistic concurrency
struct ConcurrentState has key {
    id: UID,
    value: u64,
    version: u64
}

public fun update(
    state: &mut ConcurrentState,
    new_value: u64,
    expected_version: u64
) {
    assert!(state.version == expected_version, EVERSION);
    state.value = new_value;
    state.version = state.version + 1;
}

####状态迁移(升级)

module my_contract::v2 {
    use my_contract::state::ContractState;

    // Migrate V1 state to V2
    public entry fun upgrade_state(
        old_state: ContractState,
        ctx: &mut tx_context::TxContext
    ) {
        let new_state = V2State {
            id: object::new(ctx),
            counter: old_state.counter,
            new_field: 0
        };
        transfer::share_object(new_state);
    }
}

###5. 安全模式

####基于能力的访问权限

struct AdminCap has key, store {
    id: UID
}

public entry fun secure_update(
    state: &mut ContractState,
    _cap: &AdminCap
) {
    // Only callable with capability
    state.counter += 1;
}

####重入保护

struct Lock has key {
    id: UID,
    locked: bool
}

public entry fun guarded_update(
    state: &mut ContractState,
    lock: &mut Lock
) {
    assert!(!lock.locked, ELOCKED);
    lock.locked = true;
    state.counter += 1;
    lock.locked = false;
}

###6. 常见陷阱和解决方案

| 错误 | 原因 | 修复 | | --------------| -----| | EInvalidSharedObjectUse| 不正确的可变性 | 使用&mut参考 | | EMissingOwner| 对象不属于包裹 | transfer::transfer到包裹地址 | | EImmutable| 尝试修改冻结的对象 | 初始化为 share_object|


###7. 性能优化

####批量突变

public entry fun batch_update(
    states: vector<&mut ContractState>,
    delta: u64
) {
    let i = 0;
    while (i < vector::length(&states)) {
        let state = vector::borrow_mut(states, i);
        state.counter = state.counter + delta;
        i = i + 1;
    }
}

####天然气成本比较

运营天然气 (SUI)
单次更新2,500
批量更新(10 个项目)3,800

###与 EVM 的主要差异化因素

  1. 明确所有权:必须故意转让对象
  2. key + store``copy + drop细粒度的可变性:对比技能 3.并行处理:独立对象同时发生突变

用于生产用途: -将关键状态存储为共享对象 -使用功能进行特权操作 -预先实现状态迁移路径

1
评论
.

你知道答案吗?

请登录并分享。

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

1171帖子3704答案
Sui.X.Peera.

赚取你的 1000 Sui 份额

获取声誉积分,并因帮助 Sui 社区成长而获得奖励。

奖励活动九月