Деплой смарт-контрактов в StarkNet
StarkNet — это ZK Rollup от StarkWare, работающий поверх Ethereum. В отличие от zkSync Era с его EVM-совместимостью, StarkNet использует собственный язык Cairo и собственную виртуальную машину CASM. Перенести Solidity контракт на StarkNet напрямую не получится — нужно переписать с нуля или воспользоваться транспайлером Warp (который работает только с ограниченным подмножеством Solidity). Это обязательно нужно учитывать при оценке трудозатрат.
Cairo: язык контрактов StarkNet
Cairo 1.x vs Cairo 0.x
Исторически Cairo писался в процедурном стиле с явным управлением hints, что было нетривиально. Начиная с Cairo 1.0 (2023) синтаксис переработан в Rust-подобный, контракты теперь пишутся как #[starknet::contract] модули:
#[starknet::contract]
mod Counter {
use starknet::ContractAddress;
#[storage]
struct Storage {
count: u128,
owner: ContractAddress,
}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
Incremented: Incremented,
}
#[derive(Drop, starknet::Event)]
struct Incremented {
new_count: u128,
}
#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress) {
self.owner.write(owner);
self.count.write(0);
}
#[abi(embed_v0)]
fn increment(ref self: ContractState) {
let current = self.count.read();
self.count.write(current + 1);
self.emit(Incremented { new_count: current + 1 });
}
}
Компилятор — scarb (пакетный менеджер и build tool для Cairo, аналог Cargo). Контракт компилируется в Sierra (Safe Intermediate Representation), затем в CASM для исполнения.
Ключевые отличия от Solidity
-
Storage — в Cairo хранилище работает иначе. Нет динамических массивов в storage напрямую: используются
Vec<T>черезStorageVecили маппинги черезMap<K, V>. Структуры раскладываются в отдельные storage слоты автоматически. -
Felt252 — базовый тип данных, 252-битное поле. Привычные
uint256реализованы как структура из двухfelt252. Арифметикаu256дороже по gas, чем работа сfelt252. -
Account Abstraction нативна — в StarkNet нет EOA в Ethereum-смысле. Каждый аккаунт — это контракт, реализующий
IAccountинтерфейс. Это значит, что multicall, session keys, social recovery — всё это "из коробки" на уровне аккаунта.
Инфраструктура деплоя
Scarb и инициализация проекта
# Установка Scarb
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh
# Новый проект
scarb new my_contract
cd my_contract
# Scarb.toml
[package]
name = "my_contract"
version = "0.1.0"
[dependencies]
starknet = ">=2.6.0"
[[target.starknet-contract]]
sierra = true
casm = true
# Компиляция
scarb build
# Результат: target/dev/my_contract_Counter.contract_class.json (Sierra)
# target/dev/my_contract_Counter.compiled_contract_class.json (CASM)
Деплой через starkli
starkli — основной CLI инструмент для взаимодействия со StarkNet:
# Установка
curl https://get.starkli.sh | sh
# Настройка keystore
starkli signer keystore new ~/.starkli-wallets/deployer/keystore.json
# Объявить контракт класс (declare) — это уникально для StarkNet
# Сначала класс регистрируется в сети, потом деплоится инстанс
starkli declare \
target/dev/my_contract_Counter.contract_class.json \
--account ~/.starkli-wallets/deployer/account.json \
--keystore ~/.starkli-wallets/deployer/keystore.json \
--rpc https://starknet-mainnet.public.blastapi.io
# Деплой инстанса с constructor аргументами
starkli deploy \
CLASS_HASH \
OWNER_ADDRESS \
--account ~/.starkli-wallets/deployer/account.json \
--keystore ~/.starkli-wallets/deployer/keystore.json \
--rpc https://starknet-mainnet.public.blastapi.io
Двухшаговая модель declare/deploy — архитектурная особенность StarkNet. Один и тот же class_hash может иметь тысячи инстансов — это экономит место в сети.
Деплой через starknet-rs / starknet.js
Для программного деплоя через TypeScript:
import { RpcProvider, Account, Contract, json, stark } from 'starknet'
import fs from 'fs'
const provider = new RpcProvider({
nodeUrl: 'https://starknet-mainnet.public.blastapi.io',
})
const account = new Account(
provider,
ACCOUNT_ADDRESS,
PRIVATE_KEY,
'1' // Cairo version
)
// Declare
const compiledSierra = json.parse(
fs.readFileSync('./target/dev/my_contract_Counter.contract_class.json').toString('ascii')
)
const compiledCasm = json.parse(
fs.readFileSync('./target/dev/my_contract_Counter.compiled_contract_class.json').toString('ascii')
)
const declareResponse = await account.declare({
contract: compiledSierra,
casm: compiledCasm,
})
await provider.waitForTransaction(declareResponse.transaction_hash)
// Deploy
const deployResponse = await account.deployContract({
classHash: declareResponse.class_hash,
constructorCalldata: [OWNER_ADDRESS],
})
await provider.waitForTransaction(deployResponse.transaction_hash)
Верификация и Voyager
StarkNet explorer — Voyager (voyager.online) и Starkscan. Верификация через Voyager принимает исходники Cairo и Scarb.toml. API для программной верификации:
curl -X POST https://api.voyager.online/beta/contract/verify \
-H "Content-Type: application/json" \
-d '{
"contractAddress": "0x...",
"files": { "src/lib.cairo": "..." },
"scarbVersion": "2.6.0"
}'
Оценка трудозатрат
| Сценарий | Срок |
|---|---|
| Простой контракт (счётчик, хранилище) с нуля | 4–8 ч |
| Миграция ERC-20 / ERC-721 с Solidity | 1 д (OpenZeppelin Cairo уже реализует стандарты) |
| Кастомная DeFi логика (переписать с Solidity) | 1–2 д + тесты |
Если контракт уже написан на Solidity и нет принципиальной необходимости в StarkNet-специфике (native AA, ZK-доказательства custom логики) — рекомендую сначала рассмотреть zkSync Era с его EVM-совместимостью. Переход на Cairo оправдан, когда нужны возможности, которые Cairo дает нативно.







