Розробка смарт-контрактів на TEAL (Algorand)
Algorand — це не EVM-сумісний чейн, і писати під нього «як для Ethereum» не отримається. AVM (Algorand Virtual Machine) працює за принципом стека, TEAL — ассемблероподібна мова з жорсткими обмеженнями на розмір програми та кількість операцій. Якщо ви прийшли з досвідом Solidity, перша реакція на TEAL — здивування. Друга — повага до того, як багато можна зробити в межах цих обмежень.
Специфіка AVM, яку потрібно зрозуміти одразу
TEAL (Transaction Execution Approval Language) — це stack-based мова для Algorand Smart Contracts (ASC1). Програми бувають двох типів: LogicSig (підписує транзакції без аккаунта) та Application (повноцінний stateful смарт-контракт зі сховищем).
Ключові обмеження AVM 10 (поточна версія):
| Параметр | Ліміт |
|---|---|
| Розмір програми (approval + clear) | 8192 байти кожна |
| Глибина стека | 1000 елементів |
| Scratch space | 256 слотів |
| Global state | 64 ключ-значення пари |
| Local state (per account) | 16 ключ-значення пар |
| Box storage (unlimited key-value) | оплата за байти |
| Opcodes за транзакцію | 20,000 (базовий) |
| Opcodes з групою | до 320,000 |
Ліміт 20,000 opcodes — це не 20,000 рядків коду. Один keccak256 коштує 130 opcodes, ed25519verify — 1900. Розрахунок бюджету opcodes — обов'язкова частина розробки складних контрактів.
PyTeal vs TEAL: коли що використовувати
TEAL напрямку — для LogicSig, простих approval програм, остаточної оптимізації. Читати та дебажити TEAL простіше, ніж здається, якщо розумієш стекову модель.
PyTeal — Python-фреймворк, який компілюється у TEAL. Зручний для складної логіки: умови, цикли (через рекурсію), ABI-сумісні контракти. Версія PyTeal 0.20+ підтримує ARC-4 ABI, що дозволяє генерувати контракти з типізованими інтерфейсами.
Beaker (надбудова над PyTeal) — дає більш високорівневий синтаксис, автоматичну генерацію ABI-схеми, спрощену роботу зі state. Використовуємо Beaker для нових проектів, якщо клієнт не обмежений конкретним фреймворком.
Приклад структури простого approval contract на PyTeal:
from pyteal import *
def approval_program():
handle_creation = Seq([
App.globalPut(Bytes("owner"), Txn.sender()),
Approve()
])
is_owner = Txn.sender() == App.globalGet(Bytes("owner"))
handle_optin = Approve()
handle_closeout = Approve()
program = Cond(
[Txn.application_id() == Int(0), handle_creation],
[Txn.on_completion() == OnComplete.OptIn, handle_optin],
[Txn.on_completion() == OnComplete.CloseOut, handle_closeout],
[is_owner, Approve()],
[Int(1), Reject()]
)
return program
Де зазвичай виникають проблеми
Box storage vs Local/Global state. До AVM 8 розробники втискували дані у global state (64 ключа) або local state (16 ключів на аккаунт). З появою Box storage обмеження зняті — кожен box може зберігати до 32,768 байт, кількість box-ів не обмежена (тільки бюджет ALGO на сховище). Не використовувати Box storage у нових проектах — архітектурна помилка.
Групи транзакцій (atomic group). В Algorand не можна викликати смарт-контракт із іншого в одній транзакції — немає аналога call з EVM. Замість цього використовуються grouped transactions: кілька транзакцій, атомарно обробляємих разом. Це фундаментальна різниця з EVM, яка змінює архітектуру складних протоколів. DeFi-операція «flash loan → swap → repay» у Algorand — це atomic group з трьох Application Call транзакцій, верифікуємих друг через друга через gtxn.
Inner transactions (AVM 6+). Контракт може порождати до 256 inner transactions в одному вивозі — трансфер ALGO, ASA, виклик іншого додатку. Це основний механізм композованості в екосистемі. Помилка — спробувати реалізувати щось через pure stacking, коли задача вимагає токен-трансферу всередині логіки.
ARC-4 та ABI compatibility. Стандарт ARC-4 описує ABI для Algorand контрактів — типи аргументів, повертаємі значення, методи. Контракти без ARC-4 складніше інтегрувати з SDK (AlgoKit Utils, algokit-client-generator). Генеруємо ABI-схему автоматично через algokit.
Інструменти та стек
- AlgoKit — офіційний CLI від Algorand Foundation. Шаблони проектів, локальна devnet через Docker (AlgoKit LocalNet), деплой, взаємодія з контрактами.
- algopy (новий Python-фреймворк) — компілюється у TEAL через AVM-компілятор, статична типізація, більш строгий ABI-контроль, ніж Beaker. Для нових проектів кращий за PyTeal.
- algokit-client-generator — генерує TypeScript-клієнт з ARC-4 JSON-специфікації. Аналог typechain для EVM.
- Algorand Sandbox / AlgoKit LocalNet — локальний нод для розробки.
- Dappflow — веб-інтерфейс для інспекції транзакцій та state контракту, зручніший, ніж raw API.
Тестування пишемо на Python (pytest + algokit-utils) для unit-тестів та на TypeScript (Jest + algosdk) для інтеграційних. Покриття coverage через pytest-cov.
Як виглядає розробка
Аналітика (0.5-1 день). Визначаємо тип контракту (stateful application vs LogicSig), архітектуру state (global/local/box), необхідність inner transactions, сумісність з ARC стандартами (ARC-4, ARC-20 для smart ASA, ARC-200 для ASA-based токенів).
Розробка (2-4 дні). Пишемо approval + clear програми. Паралельно — unit-тесты на AlgoKit LocalNet. Перевіряємо opcode budget на критичних шляхах через debug: true в algod API.
Інтеграція. Генеруємо ABI JSON, клієнт на TypeScript/Python. Тестуємо на Algorand Testnet перед mainnet.
Деплой. Application деплоїться через ApplicationCreateTxn. Обновлюваність — через UpdateApplicationTxn, якщо approval програма це дозволяє. Immutability — через hardcode Int(0) у update/delete хендлерах.
Термін — від 3 до 5 днів для контракту середньої складності. Складні протоколи з кількома пов'язаними додатками та atomic group логікою — до 2 тижнів.
Типові помилки
Не враховувати minimum balance requirement. Кожен аккаунт, який opt-in в application, повинен мати мінімум 0.1 ALGO + 0.025 ALGO за кожен local state ключ. Box storage вимагає 0.0025 ALGO за кожен байт + 0.0025 за ключ. Контракти, які забули про це, ломаються при спробі запису — транзакція откатується з below min balance.
Змішувати Application Call та Asset Transfer в невірному порядку. В atomic group порядок транзакцій важливий. Контракт читає gtxn 0 — це повинна бути саме та транзакція, яку ви очікуєте. Плутанина в індексах — гарантована помилка при тестуванні.
Використовувати LogicSig там, де потрібен Application. LogicSig підписує транзакції, але не зберігає state. Якщо логіка вимагає глобального стану (баланс, лічильник, список адрес) — потрібен stateful Application. LogicSig підходит для делегованої авторизації та escrow.







