У Solana кожен стан — від балансу гаманця до даних смарт-контракту — зберігається в акаунті. Акаунт є єдиною одиницею зберігання в мережі, і розуміння його структури необхідне для будь-якої розробки, навіть найпростішої.

Цей матеріал дасть вам точну ментальну модель: з чого складається акаунт, хто ним володіє, як створювати та читати акаунти на Devnet і які помилки найчастіше зустрічаються у новачків.

Чому Solana не використовує модель балансів Ethereum

У Ethereum кожна адреса має баланс, а смарт-контракт додатково містить власне сховище (storage). Це два різні механізми для двох типів сутностей. Solana уніфікувала підхід: усе — акаунт, і кожен акаунт має однакову структуру незалежно від свого призначення.

Акаунт як одиниця зберігання: rent-exempt, owner, data

Кожен акаунт у Solana містить чотири ключові поля:

  • lamports — баланс акаунта в lamports (1 SOL = 1 000 000 000 lamports).
  • owner — публічний ключ програми, яка має право змінювати дані цього акаунта.
  • data — байтовий масив довільних даних (від 0 до 10 МБ).
  • executable — прапорець, що вказує, чи містить акаунт скомпільований код програми.

Крім того, акаунт має поле rent_epoch, яке фіксує епоху, коли акаунт став rent-exempt (звільненим від оренди). Щоб створити акаунт із даними, ви повинні покласти на нього мінімальну суму lamports, що залежить від розміру data. Ця сума називається rent-exempt мінімумом. Перевірити її для конкретного розміру можна командою:

solana rent 100

Ця команда поверне rent-exempt мінімум для акаунта з 100 байтами даних на поточному кластері. Значення може відрізнятися між Devnet, Testnet і Mainnet-Beta, тому завжди перевіряйте на тому кластері, де працюєте.

Відмінність між системними та програмними акаунтами

Системний акаунт — це акаунт, власником якого є System Program (її адреса — 11111111111111111111111111111111). Типовий приклад: гаманець користувача. Такий акаунт зазвичай не містить даних (data порожній) і не є executable. Його єдина мета — зберігати lamports.

Програмний акаунт — це акаунт, власником якого є конкретна програма (смарт-контракт). Саме в таких акаунтах програми зберігають свій стан: лічильники, списки, конфігурації. Програма може читати й записувати дані лише в акаунти, де вона вказана як owner.

Існує також третій тип — executable-акаунт. Це акаунт, який містить скомпільований код програми (BPF-байткод). Він позначений прапорцем executable: true, а його owner — завжди BPF Loader. Цей тип відрізняється від програмних акаунтів із даними, і детальний розбір executable-акаунтів належить до окремого матеріалу про те, що таке Solana program.

Структура акаунта

Ліміт розміру, lamports, owner, executable

Максимальний розмір поля data — 10 485 760 байтів (10 МБ). На практиці більшість акаунтів займають від кількох десятків до кількох тисяч байтів. Розмір фіксується при створенні акаунта і не може бути змінений пізніше. Якщо програмі потрібно більше місця, доведеться створити новий акаунт і перенести туди дані.

Поле lamports може змінюватися в будь-який момент: інші акаунти можуть переказувати lamports на цей акаунт, а програма-власник може переказувати lamports з нього (за умови, що після переказу акаунт залишається rent-exempt, якщо він містить дані).

Поле owner встановлюється один раз при створенні акаунта. Змінити owner може лише поточний власник. System Program може передати власність іншій програмі, а програма — іншій програмі через спеціальну інструкцію. Але акаунт не може стати власним власником.

Прапорець executable також встановлюється при створенні (через BPF Loader) і не може бути змінений після.

Як rent-exempt працює на практиці

Коли ви створюєте акаунт із даними, Solana вимагає депозиту rent-exempt мінімуму. Ця сума розраховується за формулою, що враховує розмір data та параметри оренди в мережі. Суть проста: чим більше даних — тим більше lamports потрібно заблокувати.

Перевірте актуальне значення для потрібного розміру:

  • solana rent 0 — мінімум для акаунта без даних.
  • solana rent 100 — мінімум для 100 байтів даних.
  • solana rent 10000 — мінімум для 10 КБ даних.

Виконуйте ці команди на тому кластері, де плануєте працювати. Значення на Devnet і Mainnet-Beta відрізняються. У цьому матеріалі всі приклади використовують Devnet.

Власник акаунта та програма

Що означає owner, чому це важливо для безпеки

Поле owner — це публічний ключ програми, яка має ексклюзивне право змінювати поле data цього акаунта. Solana Runtime перевіряє це правило на рівні виконання: якщо транзакція намагається записати дані в акаунт, а програма, що виконується, не є owner цього акаунта — транзакція відхиляється.

Це фундаментальна модель безпеки. Програма не може прочитати або змінити дані акаунта, який їй не належить. Навіть якщо програма отримала акаунт у транзакції, вона може лише читати його дані (якщо це дозволено), але не записувати.

Важливий нюанс: будь-яка програма може переказувати lamports з акаунта, якщо ця програма є його owner. Тому довіра до програми означає довіру до того, що вона не витратить ваші lamports.

Приклад: як програма записує дані в акаунт

Уявіть програму, яка зберігає лічильник. Логіка виглядає так:

  1. Користувач відправляє транзакцію, що містить інструкцію для програми та посилання на акаунт із даними.
  2. Solana Runtime перевіряє: чи є ця програма owner вказаного акаунта? Якщо ні — транзакція відхиляється.
  3. Якщо так — програма отримує контроль і може змінити байти в полі data цього акаунта.
  4. Програма зчитує поточне значення лічильника з data, збільшує його на 1 і записує назад.

Програма не може виконати цю логіку для акаунта, owner якого — інша програма. Runtime це заблокує на етапі валідації транзакції, ще до фактичного виконання.

Практичний приклад

Середовище: Devnet.
Інструмент: Solana CLI (перевірте версію командою solana --version).
Передумова: встановлений Solana CLI і налаштований Devnet.

Налаштування кластера:

solana config set --url devnet

Створення акаунта через CLI та перевірка стану

Крок 1. Створіть нову пару ключів для акаунта:

solana-keygen new --outfile ~/my-account.json --no-bip39-passphrase

Крок 2. Отримайте публічний ключ нового акаунта:

solana-keygen pubkey ~/my-account.json

Крок 3. Отримайте тестові SOL на Devnet для оплати створення акаунта. Замініть <YOUR_MAIN_KEYPAIR> на шлях до вашого основного гаманця:

solana airdrop 2 <YOUR_MAIN_KEYPAIR>

Крок 4. Перед створенням акаунта перевірте rent-exempt мінімум для 100 байтів:

solana rent 100

Запам'ятайте або скопіюйте значення, що повернеться.

Крок 5. Створіть акаунт із даними. У цьому прикладі ми створюємо акаунт розміром 100 байтів, власником якого буде System Program. Це концептуальний приклад для демонстрації механізму — у реальній розробці owner буде вашою програмою:

solana create-account 11111111111111111111111111111111 ~/my-account.json 0.001 100

Параметри по порядку: адреса програми-власника, файл ключів нового акаунта, кількість SOL для депозиту, розмір data в байтах.

Якщо депонована сума менша за rent-exempt мінімум для 100 байтів, команда поверне помилку. У такому разі збільште суму депозиту відповідно до значення з кроку 4 і повторіть спробу.

Читання даних акаунта через solana account

Перевірте стан створеного акаунта (замініть <PUBLIC_KEY> на значення з кроку 2):

solana account <PUBLIC_KEY>

Очікувана структура відповіді (формат може незначно відрізнятися залежно від версії CLI):

Поле Очікуване значення Пояснення
Public Key ваш публічний ключ Адреса акаунта в мережі
Balance відповідає депозиту Сума lamports, яку ви вказали при створенні
Owner 11111111111111111111111111111111 System Program — власник цього акаунта
Executable false Акаунт не містить код програми
Rent Epoch 18446744073709551615 Максимальне значення u64 — маркер rent-exempt стану
Data Length 100 bytes Розмір виділеного простору для даних

Зверніть увагу на Rent Epoch. Значення 18446744073709551615 (максимальне значення для 64-бітного беззнакового цілого) — це стандартний маркер rent-exempt стану. Акаунт у цьому стані не буде видалений через нестачу балансу.

Тепер порівняйте це з системним акаунтом без даних. Створіть ще одну пару ключів і виконайте airdrop без створення акаунта з data:

solana-keygen new --outfile ~/wallet-only.json --no-bip39-passphrase

solana airdrop 1 $(solana-keygen pubkey ~/wallet-only.json)

solana account $(solana-keygen pubkey ~/wallet-only.json)

Ви побачите: Balance має значення, Owner — System Program, Executable — false, але Data Length — 0 bytes. Це типовий системний акаунт-гаманець.

Типові помилки

Недостатньо lamports для rent-exempt

Найчастіша помилка при створенні акаунта — депонувати суму, меншу за rent-exempt мінімум. Наприклад, ви намагаєтеся створити акаунт із 10 000 байтами даних і депонуєте 0.001 SOL, але rent-exempt мінімум для цього розміру виявляється більшим.

Результат: транзакція відхиляється з помилкою типу InsufficientFundsForRent.

Рішення: завжди викликайте solana rent <BYTES> перед створенням акаунта і депонуйте суму не меншу за повернене значення. У production-коді (наприклад, з Anchor) rent-exempt мінімум обчислюється автоматично, але на етапі навчання та ручного тестування це потрібно робити самостійно.

Невірний owner акаунта

Інша поширена помилка — спроба передати акаунт у транзакцію програмі, яка не є його owner. Наприклад, ви створили акаунт із owner = Program A, але відправляєте інструкцію для Program B і очікуєте, що Program B запише туди дані.

Результат: транзакція відхиляється з помилкою типу InvalidAccountOwner або схожою, залежно від контексту виклику.

Рішення: переконайтеся, що при створенні акаунта ви вказали правильну програму як owner. У CLI це перший параметр команди solana create-account. У програмному коді — адреса програми в інструкції створення акаунта.

Ще один варіант цієї помилки: ви намагаєтеся змінити owner акаунта без участі поточного власника. Наприклад, хочете передати акаунт від System Program до вашої програми, але не використовуєте інструкцію System Program для цього. Змінити owner може лише поточний owner — це правило не має винятків.

Модель акаунтів у Solana може здаватися незвичною, якщо ви приходите з Ethereum або інших блокчейнів. Але після кількох практичних спроб на Devnet — створити акаунт, перевірити його стан, побачити, як поля відображаються в CLI — механізм стає інтуїтивно зрозумілим. Наступний логічний крок — зрозуміти, що таке Solana program і як програма взаємодіє з акаунтами, якими вона володіє.

Джерела