Перейти к основному содержанию
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

  • Язык программирования, похожий на Python
  • Сильная типизация
  • Маленький и понятный код компилятора
  • Эффективная генерация байткода
  • Специально содержит меньше функционала, чем 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.
  • Первоначально был разработан для контракта оптимистического ролл-апа.
  • Yul+ можно рассматривать как экспериментальное предложение по обновлению Yul, добавляющее в него новые функции.

Пример контракта

На этом простом примере реализуем функцию power. Его можно скомпилировать с помощью 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 (EVM).
  • Вдохновлен Python и Rust.
  • Стремится быть простым в освоении — даже для разработчиков, которые плохо знакомы с экосистемой Ethereum.
  • Разработка Fe все еще находится на ранней стадии, альфа-версия языка была выпущена в январе 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 разработчиков, которые хотят писать смарт контракты.
  • У Vyper меньшее количество функционала, что делает его превосходным инструментом для быстрой проверки идей.
  • Цель Vyper быть легким для аудитов и максимально читабельным для людей.

Какие преимущества у Yul и Yul+?

  • Простой и функциональный низкоуровневый язык.
  • Позволяет максимально приблизиться к функциям EVM, что может помочь оптимизировать затраты газа в ваших контрактах.

Сравнение языков

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

Дополнительные материалы

Была ли эта статья полезной?