Розгортання смарт-контрактів у Sui
Sui використовує Move — мову, розроблену в Facebook для Diem. Ключова відмінність від Solidity: в Move ресурси (об'єкти) не можуть бути скопійовані або випадково знищені — це гарантовано системою типів на рівні компілятора. Якщо ви звикли до EVM, перші дні будуть незручними: забудьте про відображення address => uint256, тут усе побудовано навколо об'єктів з явним власником.
Об'єктна модель Sui
У Sui немає глобального стану в класичному розумінні. Усе — об'єкти. Кожен об'єкт має унікальний ID, version та owner:
- Owned objects — належать конкретній адресі, тільки вони можуть їх використовувати в транзакціях
- Shared objects — доступні всім, але створюють конфлікти та потребують консенсусу (повільніше)
- Immutable objects — навічно заморожені, доступні всім для читання
Це важливо при архітектурі: якщо ваш контракт вимагає спільного стану (як AMM зі спільним пулом ліквідності) — shared objects неминучі та транзакції проходять через консенсус. Якщо стан можна розподілити між користувачами — використовуйте owned objects та отримайте паралельну обробку без консенсусу.
Інструментарій та структура проекту
# Встановлення Sui CLI
cargo install --locked --git https://github.com/MystenLabs/sui.git \
--branch mainnet sui
# Створення нового пакету
sui move new my_package
# Зборка
sui move build
# Тести
sui move test
Структура пакету:
my_package/
├── Move.toml # залежності, адреси
├── sources/
│ └── my_module.move
└── tests/
└── my_module_tests.move
Move.toml містить адреси пакетів — в [addresses] ви визначаєте псевдоніми:
[package]
name = "my_package"
version = "0.0.1"
edition = "2024.beta"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet" }
[addresses]
my_package = "0x0"
Патерн Capability — управління доступом
У Move немає msg.sender як у Solidity. Права передаються через об'єкти-capability:
module my_package::admin {
use sui::object::{Self, UID};
use sui::tx_context::TxContext;
/// Адміністративна capability — хто тримає об'єкт, той і адмін
public struct AdminCap has key, store {
id: UID,
}
fun init(ctx: &mut TxContext) {
// Створюється один раз при розгортанні, передається розгортувачу
transfer::transfer(AdminCap { id: object::new(ctx) }, tx_context::sender(ctx))
}
/// Тільки власник AdminCap може викликати
public fun privileged_action(_cap: &AdminCap, /* ... */) {
// logic
}
}
Функція init — точка входу при розгортанні, аналог конструктора. Викликається один раз автоматично.
Розгортання пакету
# Розгортання в mainnet
sui client publish \
--gas-budget 100000000 \
--json
# З конкретним ключем (якщо кілька у keystore)
sui client publish \
--gas-budget 100000000 \
--serialize-unsigned-transaction | \
sui keytool sign --address <ADDRESS> --data -
Після розгортання ви отримуєте packageId — незмінну адресу пакету. У транзакціях ви посилаєтесь на функції як <packageId>::<module>::<function>.
Можливість оновлення
Sui підтримує оновлення пакетів, але з обмеженнями. Оновлення керується через об'єкт UpgradeCap:
| Політика | Опис |
|---|---|
compatible |
Можна додавати функції, не можна змінювати існуючі підписи |
additive |
Тільки додавання нових модулів |
dep_only |
Тільки оновлення залежностей |
sui client upgrade \
--upgrade-capability <UPGRADE_CAP_ID> \
--gas-budget 100000000
Для продакшену: передайте UpgradeCap контракту timelock або multisig (Sui підтримує multisig через схему MultiSig). Якщо оновлення не плануються — зробіть UpgradeCap immutable через package::make_immutable.
Тестування та інспекція
Move має вбудовану тестову платформу:
#[test_only]
module my_package::tests {
use sui::test_scenario;
#[test]
fun test_mint() {
let mut scenario = test_scenario::begin(@admin);
{
// setup
};
test_scenario::next_tx(&mut scenario, @user);
{
// assertions
};
test_scenario::end(scenario);
}
}
Після розгортання перевірте через Sui Explorer або Sui Vision — об'єкти, створені під час init, будуть видні в транзакції розгортання.
Контрольний список перед розгортанням у mainnet
- Тести через
sui move testз покриттям граничних випадків - Перевірка газового бюджету:
sui client dry-runперед фактичним розгортанням -
UpgradeCapпередана в multisig або заморожена -
AdminCapта інші привілейовані об'єкти — на адресі multisig, не на EOA - Перевірте, що shared objects дійсно потрібні (owned — швидше та дешевше)
- Перегляд на типові вразливості Move: відсутність
has keyabilities, неправильне передання власності







