Перейти до основного контенту
Change page

Мови розумних контрактів

Останні оновлення сторінки: 26 лютого 2026 р.

Величезний аспект Ethereum в тому, що розумні контракти можна програмувати, використовуючи відносно зручні для розробників мови. Якщо у вас є досвід роботи з Python або будь-якою мовою з фігурними дужками (opens in a new tab), ви можете знайти мову зі знайомим синтаксисом.

Дві найбільш активні та спільні мови є:

  • Мова програмування Solidity
  • Vyper

Remix IDE надає комплексне середовище розробки для створення та тестування контрактів як на Solidity, так і на Vyper. Спробуйте браузерний Remix IDE (opens in a new tab), щоб почати кодувати.

Більш досвідчені розробники також можуть захотіти використовувати Yul, проміжну мову для віртуальної машини Ethereum, або Yul+, розширення для Yul.

Якщо вам цікаво і ви любите допомагати тестувати нові мови, які досі знаходяться під тяжким розвитком, ви можете поекспериментувати з Fe, новою мовою смарт-контрактів, яка наразі ще тільки зароджується.

Передумови

Попередні знання мов програмування, особливо JavaScript або Python, можуть допомогти вам зрозуміти різницю мовах смарт-контракту. Ми також рекомендуємо вам розуміти смарт-контракти як поняття до того, як занурюватись надто глибоко в мовні порівняння. Вступ до смарт-контрактів.

Solidity

  • Об'єктно-орієнтована мова високого рівня для впровадження смарт-контрактів.
  • Мова з фігурними дужками, на яку найбільше вплинув C++.
  • Статично введений (тип змінної, відомий під час компіляції).
  • Підтримки:
    • Спадковість (ви можете розширити інші контракти).
    • Бібліотеки (ви можете створити код багаторазового використання, який можна викликати з різних контрактів, наприклад: статичні функції в статичному класі в інших об'єктно-орієнтованих мовах програмування).
    • Читання користувацьких типів.

Приклад контракту

1// SPDX-License-Identifier: GPL-3.0
2pragma solidity >= 0.7.0;
3
4contract Coin {
5 // Ключове слово "public" робить змінні
6 // доступними для інших контрактів
7 address public minter;
8 mapping (address => uint) public balances;
9
10 // Події дають змогу клієнтам реагувати на певні
11 // зміни в контракті, які ви оголошуєте
12 event Sent(address from, address to, uint amount);
13
14 // Код конструктора виконується лише під час
15 // створення контракту
16 constructor() {
17 minter = msg.sender;
18 }
19
20 // Надсилає певну кількість щойно створених монет на адресу
21 // Може бути викликана лише творцем контракту
22 function mint(address receiver, uint amount) public {
23 require(msg.sender == minter);
24 require(amount < 1e60);
25 balances[receiver] += amount;
26 }
27
28 // Надсилає певну кількість існуючих монет
29 // від будь-якого абонента на адресу
30 function send(address receiver, uint amount) public {
31 require(amount <= balances[msg.sender], "Недостатній баланс.");
32 balances[msg.sender] -= amount;
33 balances[receiver] += amount;
34 emit Sent(msg.sender, receiver, amount);
35 }
36}
Показати все

Цей приклад повинен дати вам уявлення про те, як виглядає синтаксис контракту Solidity. Більш детальний опис функцій і змінних дивіться в документації (opens in a new tab).

Vyper

  • Мова програмування Pythonic
  • Strong typing
  • Невеликий і зрозумілий код компілятора
  • Ефективна генерація байт-коду
  • Навмисно має менше функцій, ніж Solidity, з метою зробити контракти більш безпечними та легшими для перевірки. Vyper не підтримує:
    • Модифікатори
    • Наслідування
    • Вбудовану збірку
    • Перевантаження функцій
    • Перевантаження оператора
    • Рекурсивні виклики
    • Петлі нескінченної довжини
    • Двійкові нерухомі точки

Щоб отримати додаткову інформацію, прочитайте обґрунтування Vyper (opens in a new tab).

Приклад

1# Відкритий аукціон
2
3# Параметри аукціону
4
5# Бенефіціар отримує гроші від учасника, який запропонував найвищу ціну
6
7beneficiary: public(address)
8auctionStart: public(uint256)
9auctionEnd: public(uint256)
10
11# Поточний стан аукціону
12
13highestBidder: public(address)
14highestBid: public(uint256)
15
16# Установлюється на true в кінці, забороняє будь-які зміни
17
18ended: public(bool)
19
20# Відстежуйте відшкодовані ставки, щоб ми могли дотримуватися шаблону виведення
21
22pendingReturns: public(HashMap[address, uint256])
23
24# Створіть простий аукціон із часом торгів `_bidding_time`
25
26# секунд від імені
27
28# адреси бенефіціара `_beneficiary`.
29
30@external
31def __init__(_beneficiary: address, _bidding_time: uint256):
32 self.beneficiary = _beneficiary
33 self.auctionStart = block.timestamp
34 self.auctionEnd = self.auctionStart + _bidding_time
35
36# Зробіть ставку на аукціоні на суму, надіслану
37
38# разом із цією транзакцією.
39
40# Сума буде повернута, лише якщо
41
42# аукціон не буде виграно.
43
44@external
45@payable
46def bid():
47 # Перевірте, чи закінчився період торгів.
48 assert block.timestamp < self.auctionEnd
49 # Перевірте, чи достатньо висока ставка
50 assert msg.value > self.highestBid
51 # Відстежуйте відшкодування для попереднього учасника з найвищою ставкою
52 self.pendingReturns[self.highestBidder] += self.highestBid
53 # Відстежуйте нову високу ставку
54 self.highestBidder = msg.sender
55 self.highestBid = msg.value
56
57# Виведіть раніше повернуту ставку. Шаблон виведення
58
59# використовується тут, щоб уникнути проблеми з безпекою. Якби повернення надсилалися безпосередньо
60
61# як частина bid(), зловмисний контракт торгів міг би заблокувати
62
63# ці повернення і таким чином заблокувати надходження нових вищих ставок.
64
65@external
66def withdraw():
67 pending_amount: uint256 = self.pendingReturns[msg.sender]
68 self.pendingReturns[msg.sender] = 0
69 send(msg.sender, pending_amount)
70
71# Завершіть аукціон і надішліть найвищу ставку
72
73# бенефіціару.
74
75@external
76def endAuction():
77 # Рекомендується структурувати функції, які взаємодіють
78 # з іншими контрактами (тобто викликають функції або надсилають ефір)
79 # у три етапи:
80 # 1. перевірка умов
81 # 2. виконання дій (потенційно змінюючи умови)
82 # 3. взаємодія з іншими контрактами
83 # Якщо ці етапи переплутані, інший контракт може викликати
84 # назад поточний контракт і змінити стан або спричинити
85 # багаторазове виконання ефектів (виплата ефіру).
86 # Якщо функції, що викликаються внутрішньо, включають взаємодію із зовнішніми
87 # контрактами, їх також слід розглядати як взаємодію із
88 # зовнішніми контрактами.
89
90 # 1. Умови
91 # Перевірте, чи досягнуто часу завершення аукціону
92 assert block.timestamp >= self.auctionEnd
93 # Перевірте, чи цю функцію вже було викликано
94 assert not self.ended
95
96 # 2. Ефекти
97 self.ended = True
98
99 # 3. Взаємодія
100 send(self.beneficiary, self.highestBid)
Показати все

Цей приклад повинен дати вам уявлення про те, як виглядає синтаксис контракту Vyper. Більш детальний опис функцій і змінних дивіться в документації (opens in a new tab).

Yul та Yul+

Якщо ви новачок в Ethereum і ще не робили кодування смарт-контрактними мовами, ми радимо розпочати роботу з Solidity чи Vyper. Подивіться на Yul або Yul+ лише після того, як ви ознайомитесь із найкращими практиками безпеки смарт-контрактів та особливостями роботи з EVM.

Yul

  • Проміжна мова для Ethereum.
  • Підтримує EVM та Ewasm (opens in a new tab), версію WebAssembly для Ethereum, і розроблена як придатний спільний знаменник для обох платформ.
  • Гарна мета для стадій оптимізації високого рівня, які можуть отримати користь від EVM та Ewasm платформ однаково.

Yul+

  • Низький рівень високоефективного розширення Yul.
  • Спочатку розроблена для контракту optimistic rollup.
  • Yul+ можна розглядати як експериментальну пропозицію оновлення в Yul, додавши до нього нові властивості.

Приклад контракту

Наступний простий приклад реалізує функцію живлення. Його можна скомпілювати за допомогою solc --strict-assembly --bin input.yul. Приклад повинен зберігатись у файлі input.yul.

1{
2 function power(base, exponent) -> result
3 {
4 switch exponent
5 case 0 { result := 1 }
6 case 1 { result := base }
7 default
8 {
9 result := power(mul(base, base), div(exponent, 2))
10 if mod(exponent, 2) { result := mul(base, result) }
11 }
12 }
13 let res := power(calldataload(0), calldataload(32))
14 mstore(0, res)
15 return(0, 32)
16}
Показати все

Якщо ви вже маєте значний досвід роботи зі смарт-контрактами, повну реалізацію ERC20 на Yul можна знайти тут (opens in a new tab).

Fe

  • Статично типізована мова для Ethereum Virtual Machine (EVM).
  • Натхненна Python та Rust.
  • Прагне бути легкою для навчання - навіть для розробників, які є новачками в екосистемі Ethereum.
  • Альфа-версія мови була випущена у січні 2021 року, коли розвиток Fe був ще на ранніх стадіях.

Приклад контракту

Нижче наведено простий договір, реалізований у Фа.

1type BookMsg = bytes[100]
2
3contract GuestBook:
4 pub guest_book: map<address, BookMsg>
5
6 event Signed:
7 book_msg: BookMsg
8
9 pub def sign(book_msg: BookMsg):
10 self.guest_book[msg.sender] = book_msg
11
12 emit Signed(book_msg=book_msg)
13
14 pub def get_msg(addr: address) -> BookMsg:
15 return self.guest_book[addr].to_mem()
16
Показати все

Як вибрати

Як і у випадку з будь-якою іншою мовою програмування, головним чином йдеться про вибір відповідного інструменту для відповідної роботи, а також про особисті уподобання.

Ось декілька речей, які слід врахувати, якщо ви ще не спробували якісь з мов:

Що хорошого в Solidity?

  • Якщо ви початківець, існує багато уроків та засобів навчання. Більше про це можна дізнатися в розділі Вивчайте за допомогою кодування.
  • Доступні хороші інструменти для розробників.
  • Solidity має велике співтовариство розробників, що означає, що ви, швидше за все, знайдете відповіді на ваші запитання досить швидко.

Що хорошого в Vyper?

  • Чудовий шлях для розробників для створення Python, які хочуть написати смарт-контракти на Python.
  • Vyper має меншу кількість функцій, що робить його чудовим для швидкого прототипу ідей.
  • Випер має на меті бути легким для аудиторії та максимально читабельним для людей.

Що хорошого в Yul та Yul+?

  • Спрощена і функціональна мова низького рівня.
  • Дозволяє наблизитися до необробленого EVM, що може допомогти оптимізувати використання газу за вашими контрактами.

Порівняння мов

Для порівняння основного синтаксису, життєвого циклу контракту, інтерфейсів, операторів, структур даних, функцій, потоку керування та іншого, перегляньте цю шпаргалку від Auditless (opens in a new tab)

Для подальшого читання

Чи була ця стаття корисною?