Допис
Діліться своїми знаннями.
Чи може смарт-контракт володіти та мутувати власний об'єктний стан у Sui?
Я намагаюся зрозуміти цей аспект мережі Sui, тому що я або будую, налагоджую або розгортаю щось, що стосується цієї області. Я хочу детальне пояснення того, як працює цей механізм або функція, разом із відповідним використанням CLI, структурою переміщення коду або архітектурними концепціями. Моя мета — отримати достатню ясність, щоб застосувати ці знання в реальному проекті — будь то спеціальний смарт-контракт, система NFT, інтеграція гаманця чи інструмент DeFi. Мережа Sui має унікальні особливості порівняно з мережами EVM, тому мене особливо цікавить, що її відрізняє та як це впливає на найкращі практики розробки. Це допомогло б мати зразок коду, приклади командного рядка або типові помилки, на які слід стежити, особливо під час використання Sui CLI, SDK або розгортання в localnet/testnet. Зрештою, я хочу уникнути поширених помилок, дотримуватися найкращих принципів безпеки та гарантувати, що функціональність, над якою я працюю, поводиться так, як очікувалося в реалістичних умовах.
- Sui
- Architecture
- Move
Відповіді
15У 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, передаючи об'єкти між контрактами та обліковими записами користувачів.
- Завжди безпечно керуйте дозволами, щоб уникнути несанкціонованого доступу до стану об'єкта.
Чи може смарт-контракт володіти та мутувати власний об'єктний стан у 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: Завжди перевіряйте логіку контракту та зміни стану перед розгортанням у основну мережу.
У Sui смарт-контракти (пакети Move)не можутьбезпосередньо володіти або мутувати об'єкти самі через об'єктно-орієнтовану модель власності Sui. Об'єкти повинні належатиадреса,іншому об'єктаабо позначатися якспільний/незмінний— пакунки містять лише логіку коду. Для автономної мутації ви зазвичай використовуєтеспільні об'єкти(з консенсусом) абодинамічні поля, де батьківські об'єкти керують дочірніми об'єктами. Це принципово відрізняється від зберігання контрактів EVM, що вимагає явної передачі права власності через транзакції, а не внутрішні дії контракту. Поширені шаблони передбачаютьзагортання об'єктіву контейнери, керовані адміністратором, або використаннядизайну на основі можливостідля безпечного управління мутаціями стану.
Так, у Sui смарт-контрактможе мутувати власний стан об'єкта, алевін не може володіти об'єктами самостійно. У об'єктно-центричній моделі Суякожен об'єкт повинен належати або адресі, іншому об'єкту або позначатися як спільний. Розумні контракти не мають адреси, як у ланцюгах EVM (наприклад, Ethereum), тому ви повинні покладатися на шаблонивласність об'єктах, якструктури даних, обгорнуті об'єктамиабоспільні об'єкти, щоб зберегти та мутувати стан між транзакціями.
Щоб оновити внутрішній стан контракту, ви зазвичай розробля struct
єте (з key
можливістю) зберігати дані стану, передавати їх вашій 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.
У мережі Sui смарт-контракти не можуть «володіти» об'єктами в традиційному сенсі EVM, оскільки право власності завжди прив'язане до адреси чи іншого об'єкта. Однак смарт-контракти, написані в Move, можуть визначати та змінювати власні об'єкти власного стану — це, як правило, спільні об'єкти або власні об'єкти, передані користувачами.
Ключові поняття
- Власність об'єкта в Sui: Кожен об'єкт належить:
Адреса користувача (адреса),
Інший об'єкт (вкладене право власності),
Спільний (доступний всім),
Незмінний (не може змінюватися після публікації).
-
Стан смарт-контракту: Щоб створити стан контракту, розробники визначають структури в модулі Move і публікують екземпляри цих структур як об'єкти. Потім ці об'єкти передаються функціям введення, де їх стан можна прочитати або змінити.
-
Мутуючий стан: Щоб змінити стан об'єкта смарт-контракту, необхідно:
Передайте об'єкт у функцію як &mut.
Переконайтеся, що його можна змінювати та володіти/поділитися за потреби.
Мати правильні права доступу.
- Спільні об'єкти для глобального стану: Якщо ви хочете отримати глобальний стан для всього контракту, ви використовуєте спільні об'єкти:
Struct Counter має ключ, сховище, копіювання { значення: u64, }
приріст веселощів для публічного входу (лічильник: & mut Counter) { лічильник.значення = лічильник.значення + 1; }
- Публікація спільних об'єктів:
Спільні об'єкти повинні бути явно створені та спільними при ініціалізації.
Використовуйте виклик переміщення або Sui CLI --gas-budget та --shared-object-input для взаємодії з ними.
- Приклад потоку розгортання:
Розгорнути модуль за допомогою sui move publish.
Викликаємо функцію входу, щоб створити спільний об'єкт:
дзвінок суі-клієнта
<PACKAGE_ID>--пакет\
- лічильник модулів
--функція створення_лічильника
--аргс 0
--газовий бюджет 10000
Потім викликаємо increment з ідентифікатором об'єкта спільного об'єкта.
- Обмеження:
Розумні контракти не зберігають внутрішній стан, як у Solidity.
Вони діють на об'єктах, явно переданих їм.
Постійного «зберігання контрактів» всередині модуля не існує.
- Безпека та право власності:
Ви повинні підтвердити право власності вручну або за допомогою можливостей.
Зазвичай використовують шаблони контролю доступу, такі як AdminCap або Whitelist, для перекриття мутацій.
- Кращі практики:
Уникайте непотрібного спільного використання об'єктів, щоб обмежити використання газу та суперечки.
Використовуйте можливості або перевірку адреси, щоб безпечно керувати доступом.
Використовуйте ключ і зберігайте належним чином, щоб увімкнути стійкість об'єкта та змінність.
- Команди CLI для перегляду:
виклик клієнта sui для викликів функцій.
клієнтський об'єкт sui для
Тест sui move для логіки стану тестування одиниць.
У Sui смарт-контракт, написаний у Move, не може по-справжньому володіти* власнити* власним об'єктом у тому ж сенсі, що контракт EVM, що самопосилається, може утримувати та мутувати внутрішній стан автономно. Об'єктно-орієнтована архітектура Sui означає, що всі об'єкти повинні бути явно передані в контекст транзакції, і їх власність є або заснованою на обліковому записі, або спільною. Розумні контракти самі по собі є бездержавними — вони визначають лише логіку. Фактичний стан існує в об'єктах переміщення, які необхідно передати функціям для читання або мутації.
Щоб змінити об'єкт стану контракту, вам потрібно структурувати ваш модуль таким чином, щоб його дані (зазвичай зберігаються у 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, явно передані у ваші логічні функції, що покращує одночасність та перевірку.
Ні, смарт-контракт (модуль Move) не може безпосередньо володіти або мутувати власний стан об'єкта в Sui.
Об'єкти є першокласними сутностями, що належать адресам, іншим об'єктам або спільними, а не модулями. Мутація стану відбувається за допомогою функцій, які приймають об'єкти як змінні параметри, а правила власності застосовуються на рівні транзакції.
Приклад:
struct Counter has key { id: UID, value: u64 }
public entry fun increment(counter: &mut Counter) { counter.value = counter.value + 1 }
increment
Функція може мутувати Counter
лише тоді, коли транзакція передає змінне посилання на об'єкт, що належить відправнику. Сам модуль не тримає стану.
Використовувати shared
об'єкти (transfer::share_object
) для постійного, глобально доступного стану. Завжди перевіряйте право власності за object::is_owner()
правилами лінійного типу та дотримуйтесь їх.
Так, смарт-контракт Sui (пакет Move) може володіти та мутувати власний стан за допомогоюспільних об'єктівабополів динамічних об'єктів, на відміну від дизайну без статусу EVM.
####Ключові механізми 1.Спільні об'єкти:
- Глобально змінюється будь-ким (з правилами).
- Визначен
key + store
о та належить0x0
(адреса пакета).
struct ContractState has key, store {
id: UID,
value: u64,
}
2.Поля динамічних об'єктів:
- Пакет може «володіти» об'єктами, зберігаючи їх ідентифікатори.
fun add_state(ctx: &mut TxContext) {
let state = ContractState { id: object::new(ctx), value: 42 };
transfer::share_object(state); // Make it globally mutable
}
###Чому Суй унікальний -Немає «msg.sender": Управління доступом здійснюється через систему типу Move, а не EOA. -Паралельні мутації: Спільні об'єкти дозволяють одночасно записувати (на відміну від серіалізованих TX EVM).
###Приклад 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
Умови гонок: Дизайн для паралельного доступу (наприклад, використання).
Так, розумний контракт у Sui може мутувати власний стан об'єкта, але він повинен робити це через об'єкти, явно передані в його функції. В об'єктній моделі Суї немає внутрішнього сховища контрактів, як в Ethereum; натомість стан підтримується за допомогою змінних об'єктів. Ці об'єкти можуть належати користувачам або ділитися ними по мережі. Щоб змінити стан, ви визначаєте структуру зі здатністю has key, а потім записуєте функції введення, які приймають посилання &mut на об'єкт. Спільні об'єкти дозволяють отримати глобальний доступ і потрібні, коли кілька користувачів повинні взаємодіяти з одним станом. Мутація спільних об'єктів вимагає позначення функції як загальнодоступного запису та передачі правильного ідентифікатора об'єкта під час викликів. Контракти не «володіють» державою безпосередньо; скоріше, вони оперують даними, переданими їм за допомогою аргументів. Ви можете примусити контроль доступу за допомогою можливостей або перевіряючи адреси відправників. Ця конструкція підтримує високу паралельність, кращу масштабованість та дрібнозернисті дозволи. Загалом, смарт-контракти в Sui змінюють стан, змінюючи визначені рухом об'єкти за суворими правилами власності та доступу.
Так, смарт-контракт Sui (модуль Move) може володіти та мутувати власні об'єкти за допомогою:
1.Власні об'єкти— Створено під час ініціації модуля (зберігається під ідентифікатором пакета).
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 забезпечує автономні контракти - не потрібні проксі-гаманці. ) *
###1. Основна концепція: Об'єктно-орієнтоване володіння На відміну від змінних зберігання EVM, смарт-контракти 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) |
---|---|
Одноразове оновлення | 2500 |
Пакетне оновлення (10 елементів) | 3,800 |
###Ключові диференціатори від EVM
1.Явне володіння: Об'єкти повинні бути навмисно передані
2. key + store``copy + drop
Дрібнозерниста змінність: проти здібностей
3.Паралельна обробка: Незалежні об'єкти мутують одночасно
Для виробництва використовують:
- Зберігати критичний стан якспільні об'єкти
- Використовуватиможливостідля привілейованих операцій
- Реалізуйте шляхиміграціїштату заздалегідь
Ви знаєте відповідь?
Будь ласка, увійдіть та поділіться нею.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Зароби свою частку з 1000 Sui
Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.
- Чому BCS вимагає точного порядку полів для десеріалізації, коли структури Move мають названі поля?65
- Як максимізувати прибуток від SUI: Sui Staking проти Liquid Staking514
- Помилки перевірки кількох джерел» у публікаціях модуля Sui Move - автоматичне вирішення помилок55
- Помилка Sui Move - Неможливо обробити транзакцію Не знайдено дійсних газових монет для транзакції416
- Невдала операція Sui: об'єкти, зарезервовані для іншої транзакції49