Ми — команда блокчейн-інженерів з 7-річним досвідом у Web3. За останні три роки ми розгорнули понад 15 смарт-контрактів у parachain Astar та Kusama. Коли клієнт приходить з задачею перенести свій DeFi-протокол з Ethereum у Polkadot, перше, що ми пояснюємо: Polkadot — це не ще один L2. Тут немає єдиної VM для всіх мереж. Смарт-контракти деплояться не в Relay Chain, а в парачейни з включеним модулем pallet-contracts. Kusama — це канаркова мережа Polkadot з більш швидким governance та менш суворими вимогами до слотів. Для тестування production-логіки ми використовуємо Kusama, для фінального деплою — Polkadot або спеціалізований парачейн (Astar, Phala, Aleph Zero).
Нещодавно ми розгорнули vault-контракт для стейкінгу на Astar. Клієнт заощадив 40% на gas порівняно з EVM-версією — ink! контракти в середньому в 1.8 рази ефективніші за газом, ніж аналогічні Solidity на Moonbeam. Це досягається за рахунок компіляції в Wasm та більш точної моделі газу WeightV2.
Чому ink! а не Solidity для Polkadot?
Контракти для pallet-contracts пишуться на ink! — це нативний Rust з макросами, які генерують метадані контракту та ABI-сумісний інтерфейс. На відміну від Solidity, ink! дає прямий доступ до низькорівневих оптимізацій Rust і компілюється в Wasm.
#[ink::contract]
mod vault {
use ink::storage::Mapping;
#[ink(storage)]
pub struct Vault {
balances: Mapping<AccountId, Balance>,
owner: AccountId,
}
impl Vault {
#[ink(constructor)]
pub fn new() -> Self {
Self {
balances: Mapping::default(),
owner: Self::env().caller(),
}
}
#[ink(message, payable)]
pub fn deposit(&mut self) {
let caller = self.env().caller();
let value = self.env().transferred_value();
let current = self.balances.get(caller).unwrap_or(0);
self.balances.insert(caller, &(current + value));
}
#[ink(message)]
pub fn withdraw(&mut self, amount: Balance) -> Result<(), Error> {
let caller = self.env().caller();
let balance = self.balances.get(caller).unwrap_or(0);
if balance < amount {
return Err(Error::InsufficientBalance);
}
self.balances.insert(caller, &(balance - amount));
self.env().transfer(caller, amount)
.map_err(|_| Error::TransferFailed)
}
}
}Кілька ключових відмінностей від Solidity, які ламають інтуїцію EVM-розробника:
- Немає
msg.valueу звичайних функціях — тільки в#[ink(message, payable)]. Виклик payable-функції без прапорця поверне помилку. - Storage через
Mappingбез ітерації — немаєmapping.keys(). Якщо потрібні списки — зберігайте окремоVec<AccountId>. -
AccountIdзамістьaddress— 32 байти, не 20. Адреси у форматі SS58, не hex. -
Balanceцеu128, неuint256. Але практично різниці немає.
Як вибрати парачейн для деплою?
Не всі парачейни Polkadot підтримують смарт-контракти безпосередньо. Для ink! контрактів потрібні парачейни з включеним pallet-contracts. Нижче — порівняння популярних варіантів:
| Парачейн | Тип | Підтримка ink! | Особливості |
|---|---|---|---|
| Astar | Wasm+EVM | Так | Найбільша екосистема, cross-VM виклики через XVM |
| Phala | Wasm | Так | Конфіденційні контракти через TEE |
| Aleph Zero | Wasm+EVM | Так | Висока пропускна здатність, NFT-маркетплейси |
| Rococo (testnet) | testnet | Так | Безкоштовний faucet, ідеально для тестування |
Для production-деплою ми рекомендуємо Astar — він найбільш зрілий, має підтримку як Wasm, так і EVM, та багату інфраструктуру.
Інструментарій: cargo-contract
cargo install cargo-contract --force
cargo contract new my_contract
cd my_contract
# Збірка: генерує .contract, .wasm, .json (ABI)
cargo contract build --release
# Запуск тестів
cargo test
Файл .contract — це архів з WASM bytecode та метаданими. Саме його деплоїмо.
Середовища деплою та тестування
Локальне тестування: substrate-contracts-node
substrate-contracts-node --dev --tmp Запускає однонодову мережу з попередньо фінансованими акаунтами (Alice, Bob, Charlie — як Hardhat accounts[0]). Contracts UI на contracts-ui.substrate.io або programmatic через @polkadot/api.
Тестнет: Contracts on Rococo
Rococo — тестнет Polkadot з парачейном contracts спеціально для тестування ink!. Faucet: paritytech.github.io/polkadot-testnet-faucet.
Production: Astar Network
Astar — найбільш зрілий парачейн з pallet-contracts у Polkadot ecosystem. Підтримує і ink! (Wasm), і EVM (Solidity) контракти в одній мережі, cross-VM виклики через XVM. Для більшості production use cases на Polkadot — деплоїмо на Astar.
Деплой через polkadot.js
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api';
import { CodePromise } from '@polkadot/api-contract';
import * as fs from 'fs';
async function deploy() {
const provider = new WsProvider('wss://rpc.astar.network');
const api = await ApiPromise.create({ provider });
const keyring = new Keyring({ type: 'sr25519' });
const deployer = keyring.addFromUri(process.env.MNEMONIC!);
const wasm = fs.readFileSync('./target/ink/vault.wasm');
const abi = JSON.parse(fs.readFileSync('./target/ink/vault.json', 'utf8'));
const code = new CodePromise(api, abi, wasm);
const gasLimit = api.registry.createType('WeightV2', {
refTime: 30_000_000_000n,
proofSize: 1_000_000n,
});
const storageDepositLimit = null; // автоматично
const tx = code.tx.new({ gasLimit, storageDepositLimit });
await new Promise<void>((resolve, reject) => {
tx.signAndSend(deployer, ({ contract, status }) => {
if (status.isInBlock) {
console.log('Contract address:', contract?.address.toString());
resolve();
}
}).catch(reject);
});
await api.disconnect();
} Модель газу: WeightV2
На відміну від EVM де gas — одне число, Substrate використовує двовимірний weight:
-
refTime— час обчислень (пікосекунди) -
proofSize— розмір storage proof для light clients
При деплої потрібно оцінити обидва параметри. Спосіб: сухий прогін (contracts.instantiate з estimateGas: true) або використовуємо cargo-contract:
cargo contract instantiate --dry-run \ --constructor new \ --args \ --suri //Alice \ --url ws://127.0.0.1:9944 Storage deposit
pallet-contracts вимагає депозит за зайнятий storage — аналог EIP-1153 transient storage, але постійний. Вартість пропорційна байтам у storage контракту. При видаленні storage (через ink::env::set_contract_storage::<K, ()>(&key, &())) депозит повертається. Це важливо для long-lived контрактів з великим state. На практиці storage deposit для типового контракту становить 0.1–0.5% від вартості деплою, що значно нижче, ніж на EVM-парачейнах.
Типові помилки при міграції з EVM
| EVM паттерн | ink! рішення |
|---|---|
mapping.length() |
Окремий лічильник або Vec |
block.timestamp |
self.env().block_timestamp() (u64, мілісекунди) |
msg.sender |
self.env().caller() |
payable за замовчуванням |
Явний атрибут #[ink(message, payable)] |
Events з indexed |
#[ink(topic)] на полі події |
require(cond, "msg") |
assert! або Result<_, Error> |
Cross-contract виклики в ink! вимагають імпорту ABI викликаного контракту та явного вказання gas ліміту — немає автоматичного forwarding як в Solidity {gas: gasleft()}.
Етапи деплою
- Аналіз вимог — вивчаємо логіку контракту, вибираємо парачейн.
- Написання контракту — реалізація на ink! з урахуванням безпеки та оптимізації газу.
- Тестування — локальне (substrate-contracts-node) та на Rococo.
- Аудит безпеки — зв'язка Slither для ink! та ручний аудит.
- Деплой у production — розгортання в Astar або іншому парачейні.
- Підтримка — моніторинг, оновлення, допомога користувачам.
Що входить у роботу
- Повний цикл від ідеї до деплою.
- Вихідний код з детальними коментарями.
- Документація по контракту (white paper, технічна специфікація).
- Тестовий звіт (результати unit-тестів та фаззингу).
- Доступи до контракту та інструкція по взаємодії.
- Місяць технічної підтримки після деплою.
Детальний чек-лист перед деплоєм
- Парачейн обрано (Astar/Phala/Aleph Zero)
- Контракт зібрано (
cargo contract build --release) - Пройдено unit-тести (
cargo test) - Пройдено фаззинг (Echidna або custom)
- Оцінено weight:
cargo contract instantiate --dry-run - Storage deposit розраховано та поповнено
- Тест на Rococo пройдено
- Акаунт deployer має достатньо коштів для деплою
Наша команда — сертифіковані спеціалісти Parity Substrate з 5+ роками досвіду в Rust та блокчейн-розробці. Ми гарантуємо результат: 15+ успішних деплоїв у Kusama та Polkadot. Докладніше про Substrate smart contracts читайте в офіційній документації.
Зв'яжіться з нами для оцінки вашого проекту. Замовте деплой під ключ — ми проведемо весь цикл від аналізу до підтримки. Оцінимо проект і назвемо точні терміни (від 2 тижнів до 2 місяців залежно від складності).







