Деплой смарт-контрактов в Aptos
Aptos — L1 блокчейн на базе Move VM, изначально разработанный командой Diem (Meta). Главное отличие от EVM: язык Move с его resource-ориентированной моделью и linear type system. Ресурс (resource type) нельзя скопировать или уничтожить произвольно — только явно перенести. Это устраняет целый класс уязвимостей, который преследует Solidity: double-spend через reentrancy, токены, созданные из воздуха. Если вы привыкли к EVM, первые дни с Move будут дискомфортны — потом поймёте, почему это правильно.
Структура модуля на Move
В Aptos нет понятия "контракт" — есть modules (код) и resources (данные, хранящиеся в аккаунтах). Модуль публикуется под адресом аккаунта, resources живут в аккаунтах пользователей, а не в аккаунте модуля:
module my_addr::token {
use std::signer;
struct CoinStore has key {
balance: u64,
}
public fun initialize(account: &signer) {
move_to(account, CoinStore { balance: 0 });
}
public fun deposit(account: &signer, amount: u64) acquires CoinStore {
let store = borrow_global_mut<CoinStore>(signer::address_of(account));
store.balance = store.balance + amount;
}
}
has key — ability, позволяющая хранить ресурс в глобальном storage. acquires — явное объявление, что функция обращается к глобальному ресурсу конкретного типа. Компилятор проверяет это статически — нет неявных side effects.
Инструментарий: Aptos CLI
Основной инструмент — aptos CLI. Управление аккаунтами, компиляция, деплой, вызов функций:
# Инициализация аккаунта (генерирует keypair, фондирует devnet)
aptos init --network devnet
# Компиляция
aptos move compile --package-dir . --named-addresses my_addr=0xCAFE
# Публикация модуля
aptos move publish \
--package-dir . \
--named-addresses my_addr=<YOUR_ADDRESS> \
--profile mainnet
Named addresses — механизм Aptos: в Move.toml вы используете символические имена, при деплое подставляете конкретные адреса. Это позволяет один и тот же код деплоить с разных аккаунтов без изменения исходников.
Move.toml и управление зависимостями
[package]
name = "MyProtocol"
version = "1.0.0"
[addresses]
my_addr = "_" # подставляется при деплое
[dependencies.AptosFramework]
git = "https://github.com/aptos-labs/aptos-core.git"
rev = "mainnet"
subdir = "aptos-move/framework/aptos-framework"
Зависимости тянутся из Git — это означает необходимость фиксировать rev конкретным коммитом для воспроизводимых сборок. _ в адресе — плейсхолдер, обязательный при публикации заменить.
Upgradeability: policy при деплое
В отличие от Ethereum proxy-паттернов, апгрейдимость в Aptos управляется на уровне VM через upgrade policy, задаваемую в Move.toml:
[package]
upgrade_policy = "compatible" # или "immutable"
-
compatible— разрешены совместимые обновления: добавление функций и ресурсов, но нельзя изменить существующие сигнатуры или удалить поля -
immutable— модуль заморожен навсегда, никаких обновлений
compatible — правильный выбор для production с живой логикой. После публикации с immutable контракт нельзя изменить — это нужно осознанно. Нет паттернов "прокси + имплементация" как в EVM; апгрейд работает через повторную публикацию под тем же адресом с проверкой совместимости.
Тестирование
Move имеет встроенный тест-фреймворк — тесты пишутся прямо в модулях с атрибутом #[test]:
#[test_only]
module my_addr::token_tests {
use my_addr::token;
use aptos_framework::account;
#[test(alice = @0x1)]
fun test_deposit(alice: signer) acquires token::CoinStore {
token::initialize(&alice);
token::deposit(&alice, 100);
// assert state
}
}
aptos move test --package-dir . --named-addresses my_addr=0x1
Для более сложных сценариев — Aptos Move Prover: формальная верификация инвариантов через SMT-solver (Z3). Это уровень выше обычного тестирования:
spec deposit {
ensures global<CoinStore>(signer::address_of(account)).balance ==
old(global<CoinStore>(signer::address_of(account))).balance + amount;
}
Чеклист перед mainnet-деплоем
- Тесты покрывают все public функции, включая граничные значения (
u64::MAX) - Prover спецификации для критической финансовой логики
-
upgrade_policyосознанно выбрана — immutable только если уверены - Named addresses зафиксированы в deployment скрипте, не хардкодятся вручную
- Аккаунт деплоера — multisig через Aptos native multisig (on-chain, не EOA)
- Версия Aptos Framework в зависимостях соответствует целевой сети (
mainnet/testnet) - После деплоя — верификация через Aptos Explorer (исходник публикуется on-chain)







