solidity язык программирования обучение
Хочу всё знать. Язык Solidity
Эфир и смарт-контракт
Эфириум — децентрализованная платформа, виртуальная машина для размещения онлайн-сервисов. Базируется она на технологии блокчейна, её преимущество в замене стандартных юридических сделок смарт-контрактами.
Смарт-контракт — договор, описанный математическими методами, не предполагающий двоякой трактовки. Таким образом, неисполнение одной из сторон условий контракта неизбежно приводит к штрафным санкциям без возможности перевести дело в правовое поле.
Теперь перейдем непосредственно к языку.
Краткая справка
Solidity — JavaScript-подобный объектно-ориентированный язык для разработки смарт-контрактов. Является кроссплатформенным, но на практике используется преимущественно на Ethereum.
Был создан в 2014 году командой программистов под руководством Кристиана Райтвизнера на основе идеи Гевина Вуда. Похожесть синтаксиса на JavaScript — расчет на быструю адаптацию разработчиков, которые до этого на нем разрабатывали подобные протоколы. Solidity поддерживает наследование, в том числе множественное, в том числе с С3 линеаризацией.
В рейтинге TIOBE язык появился лишь в прошлом месяце, стартовав со 167 места.
Синтаксис
В сравнении с JS есть пара существенных отличий:
Однако с поставленными задачами Solidity справляется, а визуально это все тот же ECMAScript:
contract GavCoin
<
mapping(address=>uint) balances;
uint constant totalCoins = 100000000000;
/// Endows creator of contract with 1m GAV.
function GavCoin() <
balances[msg.sender] = totalCoins;
>
/// getter function for the balance
function balance(address who) constant returns (uint256 balanceInmGAV) <
balanceInmGAV = balances[who];
>
>
Среды разработки и редакторы
Несмотря на узкий профиль применения, Solidity доступен для большого числа IDE и редакторов. Вот список:
Некоторые поддерживают язык из коробки, к другим надо прикрутить его в виде плагина.
Как изучать
Официальных книг по Solidity пока не выходило, поэтому обучаться языку лучше всего по официальному релизу. Также есть платный образовательный 3-часовой курс на Udemy.
Для тех, кто пока не силен в английском, но очень хочет быть в теме, дорога одна — на Хабрахабр (1, 2, 3). Также есть подробный туториал на проекте Голос, правда, пока только один урок.
Кроме того, тема привлекает всё новых авторов, вебинары и статьи в личных блогах появляются достаточно часто. Периодически проверяйте популярные платформы и будете в курсе развития и применения языка.
Перспективы
Solidity — один из четырех языков для EVM (три других: Serpent, LLL и Mutan) и, пожалуй, самый проработанный. Капитализация Ethereum достигла 4 миллиардов долларов США всего за 2 года. Исходя из этих фактов, Solidity ждёт светлое будущее, как для самого языка, так и для разработчиков, которые его изучат.
Эфир и смарт-контракт
Эфириум — децентрализованная платформа, виртуальная машина для размещения онлайн-сервисов. Базируется она на технологии блокчейна, её преимущество в замене стандартных юридических сделок смарт-контрактами.
Смарт-контракт — договор, описанный математическими методами, не предполагающий двоякой трактовки. Таким образом, неисполнение одной из сторон условий контракта неизбежно приводит к штрафным санкциям без возможности перевести дело в правовое поле.
Теперь перейдем непосредственно к языку.
Краткая справка
Solidity — JavaScript-подобный объектно-ориентированный язык для разработки смарт-контрактов. Является кроссплатформенным, но на практике используется преимущественно на Ethereum.
Был создан в 2014 году командой программистов под руководством Кристиана Райтвизнера на основе идеи Гевина Вуда. Похожесть синтаксиса на JavaScript — расчет на быструю адаптацию разработчиков, которые до этого на нем разрабатывали подобные протоколы. Solidity поддерживает наследование, в том числе множественное, в том числе с С3 линеаризацией.
В рейтинге TIOBE язык появился лишь в прошлом месяце, стартовав со 167 места.
Синтаксис
В сравнении с JS есть пара существенных отличий:
Однако с поставленными задачами Solidity справляется, а визуально это все тот же ECMAScript:
contract GavCoin
<
mapping(address=>uint) balances;
uint constant totalCoins = 100000000000;
/// Endows creator of contract with 1m GAV.
function GavCoin() <
balances[msg.sender] = totalCoins;
>
/// getter function for the balance
function balance(address who) constant returns (uint256 balanceInmGAV) <
balanceInmGAV = balances[who];
>
>
Среды разработки и редакторы
Несмотря на узкий профиль применения, Solidity доступен для большого числа IDE и редакторов. Вот список:
Некоторые поддерживают язык из коробки, к другим надо прикрутить его в виде плагина.
Как изучать
Официальных книг по Solidity пока не выходило, поэтому обучаться языку лучше всего по официальному релизу. Также есть платный образовательный 3-часовой курс на Udemy.
Для тех, кто пока не силен в английском, но очень хочет быть в теме, дорога одна — на Хабрахабр (1, 2, 3). Также есть подробный туториал на проекте Голос, правда, пока только один урок.
Кроме того, тема привлекает всё новых авторов, вебинары и статьи в личных блогах появляются достаточно часто. Периодически проверяйте популярные платформы и будете в курсе развития и применения языка.
Перспективы
Solidity — один из четырех языков для EVM (три других: Serpent, LLL и Mutan) и, пожалуй, самый проработанный. Капитализация Ethereum достигла 4 миллиардов долларов США всего за 2 года. Исходя из этих фактов, Solidity ждёт светлое будущее, как для самого языка, так и для разработчиков, которые его изучат.
Язык Solidity для Ethereum: в чем его специфика и как его учить
Когда мы вспоминаем Ethereum, вероятно, на ум приходит его мощная система смарт-контрактов, которая как раз и использует Solidity как основной инструмент разработки.
Для тех, кто не знает, умные контракты — это, что-то типа программ, которые существуют в блокчейне Ethereum. Они выполняют различные задачи, например, отправка или получение токенов Ether или других ERC-20.
Как и все компьютерные программы, контракты Ethereum написаны на языке программирования. Язык для блокчейна Эфириум называется Solidity. Но также есть и другие языки, совместимые со смарт-контрактами Ethereum.
Мы рассмотрим основы Solidity и расскажем, где найти ресурсы для более глубокого знакомства с языком смарт-контрактов.
Solidity как язык программирования
Большинство профессиональных программистов сегодня используют один или несколько популярных современных языков программирования. Это C (си) (и C ++, C # и т. д.), Python, Java (и JavaScript), Perl или другие. Solidity был разработан так, чтобы ему могли легко учиться программисты, которые уже знакомы с одним или несколькими современными языками.
Если вы владеете только чем-то вроде Visual Basic, то при освоении Solidity могут возникнуть трудности. Но если вы знакомы с Python или C, язык смарт-контрактов Ethereum покажется относительно знакомым.
Solidity не изобретает ничего нового: также содержит переменные, функции, классы, арифметические операции и прочее. Solidity работает с «контрактом», который создается из этих конструкций.
Наиболее всего синтаксис похож на JavaScript.
Попробовать язык можно прямо из браузера, например на remix.ethereum.org, который представляет собой онлайн редактор с возможностью отладки и запуска вашего кода. Также вы можете использовать реализацию протокола на других языках например Go https://geth.ethereum.org/.
Вот несколько рандомных примеров кода:
Solidity трудно учить?
Этот язык по-прежнему довольно молод и имеет ограниченные учебные ресурсы. Обычно достаточно купить учебник или курсы. По Solidity небольшое количество учебных книг. Разработчики стараются компенсировать это обширной документацией, но перевод на русский пока сделан только для общего руководства.
Тем не менее, для тех, кто совершенно не знаком с языком и не является программистом, погружение прямо в документацию может быть сложной задачей, если не невозможной. В идеале, документация должна использоваться так же, как если бы словарь использовался, чтобы найти словарный случай. Но никто же не читал словарь с яслей, чтобы научиться разговорной речи?
Тем не менее, если у вас есть база в других языках программирования, вы можете потенциально использовать имеющуюся документацию, чтобы изучить Solidity.
Вот некоторые образовательные ресурсы:
Стоит ли учиться Solidity?
Если вы думаете об изучении Solidity для работы, вы можете подумать о том, какие другие навыки вам понадобятся. Вакансии требуют, обычно, знать один из дополнительных языков NodeJS, GoLang или Phyton, которые будут для вас базой. Изучать связанные с блокчейном навыки может быть очень ценным, потому что конкуренция пока низкая, серьезных экспертов не хватает.
Дальше вопрос веры в Ethereum и будущее блокчейна. Нужно понимать, что если вы освоите работу со смарт-контрактами на одной платформе, другие для вас будут гораздо проще и как специалист вы будете очень ценны, так как кадров с опытом сейчас найти очень сложно, а это отличная прибавка к вашей зарплате. Тем более, что платформ со смарт-контрактми уже очень много (EOS, ETC, NEO и т.д), так что без работы вы точно не останетесь.
Также советуем почитать, какие уязвимости есть в смарт-контрактах и почему не стоит писать сразу серьезный проект после пары статей с примерами кода.
Основы Solidity и разработки смарт-контрактов
Переведем начало курса от Block Geeks, общие моменты про Solidity, а примеры кода, этапы написания и тестирование вы можете посмотреть в оригинале.
Сам язык Solidity — это инструмент, который мы используется для создания кода машинного уровня, чтобы он мог выполняться на EVM. Это язык с компилятором, который берет наш высокоуровневый читаемый код и разбивает его на простые инструкции, типа «перейти к инструкции в точке памяти xxxxx» и прочее.
Данный язык является одним из нескольких языков, которые могут быть скомпилированы в байт-код EVM. Другой язык, который делает то же самое, называется Serpent, только он основан на Pyton.
Solidity свободно типизированный язык с синтаксисом, очень похожим на ECMAScript (Javascript). Есть несколько ключевых моментов — работаем по модели stack-and-memory с 32-байтным размером инструкции. EVM дает:
EVM требует полного детерминизма в рамках смарт-контрактов.
Детерминизм является причиной того, что вы не увидите функцию «random()» в языке Solidity. Когда блок «ethereum» «майнится», развертывается смарт-контракт и вызываются функции внутри этого блока. И новое состояние меняет пространство хранилища или транзакции, так что смарт-контракт фактически выполняется в майнинг-ноде.
Затем новый блок переходит на все остальные ноды, и каждый узел пытается самостоятельно проверить блок, который включает в себя те же изменения состояния, что и локальная копия блокчейна. И если смарт-контракт действует недетерминированно, то другие узлы не смогут прийти к консенсусу относительно состояния блокчейна.
Другим ограничением, которое вы найдете в смарт-контрактах EVM, является невозможность доступа к данным за пределами «памяти» и «хранения». Плюс, невозможно запросить внешние ресурсы. Нет доступа ко многим функциям из библиотек.
Также в разработке смарт-контракта нужно учитывать, что любое изменение состояние или вычисления (вообще любые действия, кроме просто чтения блокчейна) оплачиваются в газе. Стоимость газа исчисляется по объему работы. Про эту систему мы писали отдельно (с ценами за действия). Отсюда важно то, что смарт-контракт должен быть оптимизирован, чтобы не тратить много эфира.
У смарт-контрактов есть собственный адрес, из которого они могут получать и отправлять Эфир. Смарт-контракты могут отслеживать, кто их вызывает, и определять, является этот адрес владельце или администратором. Такие учетные записи могут выводить средства из смарт-контракта.
Чтобы смарт-контракт знал, что происходит на блокчейне, используются «оракулы». К нему обращается смарт-контракт, получает информацию о внешнем мире и действует согласно этим данным.
В остальном, сам код использует традиционные типы данных, операторы и команды.
Дальше примеры кода и тестирование можно посмотреть в The Ultimate Ethereum Coding Guide (ссылка не спонсирована).
Также на русском языке есть серия статей на Хабре, листайте к первой части в серии «Погружение в разработку на Ethereum».
Учебник по Solidity. Всё про библиотеки
Что такое библиотеки в Solidity?
“Библиотеки можно рассматривать, как неявные базовые смарт-контракты для смарт-контрактов, которые их используют” из документации языка Solidity
Они позволяют вести разработку более модульным способом. Иногда полезно думать о библиотеке как о куске кода, который можно вызвать из любого смарт-контракта без необходимости его повторного развертывания.
Преимущества
Однако библиотеки в Solidity не ограничиваются только одной возможностью по повторному использованию. Вот некоторые другие преимущества:
Удобство использования: функции в библиотеке могут использоваться многими смарт-контрактами. Если у вас много смарт-контрактов, которые содержат некоторый общий для каждого смарт-контракта код, то вы можете вынести этот общий код в библиотеку.
Экономично: использование кода в виде библиотеки сэкономит вам gas, так как расход gas’а также зависит от размера смарт-контракта. Использование базового смарт-контракта вместо библиотеки для разделения общего кода не сэкономит gas, потому что в Solidity наследование работает путем копирования кода.
Дополнения: библиотеки в Solidity можно использовать для добавления функций к типам данных. Например, подумайте о библиотеках как о стандартных библиотеках или пакетах, которые вы можете использовать в других языках программирования для выполнения сложных математических операций над числами.
Ограничения
В Solidity библиотеки не имеют своего состояния и, следовательно, имеют следующие ограничения:
Они не имеют хранилища (поэтому не могут иметь изменяемых переменных состояния)
Они не могут хранить ether (поэтому не могут иметь функцию отката ( fallback ))
Не позволяет использовать payable функции (так как они не могут хранить ether)
Не могут ни наследовать, ни быть наследуемыми
Не могут быть уничтоженными (нет функции selfdestruct() с версии 0.4.20)
«Библиотеки не предназначены для изменения состояния смарт-контракта, они должны использоваться только для выполнения простых операций на основе входных данных и возврата результата».
Однако библиотеки позволяют сэкономить значительное количество газа (и, следовательно, не загрязнять блокчейн повторяющимся кодом), поскольку один и тот же код не нужно развертывать снова и снова. Различные смарт-контракты на Ethereum могут просто полагаться на одну и ту же уже развернутую библиотеку.
Тот факт, что несколько смарт-контрактов зависят от одного и того же фрагмента кода, может сделать среду более безопасной. Представьте себе, что у вас есть не только хорошо проверенный код для ваших проектов (как например заготовки кодов OpenZeppelin), но и возможность полагаться на уже развернутый в блокчейне библиотечный код, который уже используют другие смарт-контракты. Это, безусловно, помогло бы в данном случае.
2. Как создать библиотечный смарт-контракт?
Определите библиотеку и допустимые переменные
Как мы уже видели, библиотечные смарт-контракты не имеют хранилища. Поэтому они не могут хранить переменные состояния (переменные состояния, которые не являются константами). Однако библиотеки все же могут реализовать некоторые типы данных:
struct и enum : это переменные, определяемые пользователем.
любая другая переменная, определенная как constant (неизменяемая), поскольку неизменяемые переменные хранятся в байткоде смарт-контракта, а не в памяти.
Начнем с простого примера: библиотека для математических операций.
Ниже мы создали простую математическую библиотеку MathLib, которая содержит базовую арифметическую операцию, принимающую на вход 2 беззнаковых целых числа и возвращающую результат арифметической операции.
3. Как развернуть библиотеки?
Развертывание библиотеки немного отличается от развертывания обычного смарт-контракта. Вот два сценария:
Встроенная библиотека: если смарт-контракт использует библиотеку, которая имеет только внутренние ( internal ) функции, то EVM просто встраивает библиотеку в смарт-контракт. Вместо того чтобы использовать delegatecall для вызова функции, он просто использует оператор JUMP (обычный вызов метода). В этом сценарии нет необходимости в отдельном развертывании библиотеки.
Связанная библиотека: с другой стороны, если библиотека содержит публичные ( public ) или внешние ( external ) функции, то ее необходимо развернуть как отдельный смарт-контракт. При развертывании библиотеки генерируется уникальный адрес в блокчейне. Этот адрес должен быть связан с вызывающим смарт-контрактом.
4. Как использовать библиотеку в смарт-контракте?
Шаг 1: Импорт библиотеки
Под pragma просто укажите следующее утверждение:
import «./libfile.sol» as LibraryName;
Файл library-file может содержать несколько библиотек. Используя фигурные скобки <> в операторе import, вы можете указать, какую библиотеку вы хотите импортировать. Представьте, что у вас есть файл libfile.sol следующего вида :
Вы можете указать, какую библиотеку вы хотите использовать в вашем основном смарт-контракте, следующим образом:
Шаг 2: Использование библиотеки
Чтобы использовать библиотеку в смарт-контракте, мы используем синтаксис
using LibraryName for Type.
Эта указание используется для присоединения библиотечных функций (из библиотеки LibraryName ) к любому типу ( Type ).
В этих случаях к смарт-контракту присоединяются все функции из библиотеки, включая те, где тип первого параметра не совпадает с типом объекта. Тип проверяется в момент вызова функции, и выполняется перегрузка функции.
При добавлении библиотеки её типы данных, включая библиотечные функции, становятся доступными в контакте без необходимости добавления дополнительного кода. Когда вы вызываете библиотечную функцию, библиотечные функции получают объект, на котором они вызываются, в качестве первого параметра, подобно переменной self в Python.
using MathLib for MathLib.MathConstant;
5. Как взаимодействовать с библиотеками?
Немного теории
Если вызываются библиотечные функции, их код выполняется в контексте вызывающего смарт-контракта.
Давайте немного углубимся в документацию Solidity. В которой говорится следующее: «Библиотеки можно рассматривать как неявные базовые смарт-контракты для смарт-контрактов, которые их используют»:
Они не будут явно видны в иерархии наследования
Вызов функции из библиотеки использует специальную инструкцию в EVM: опкод DELEGATECALL. Это приведет к тому, что контекст вызова будет передан библиотеке, как если бы это был код, выполняемый в самом смарт-контракте. Рассмотрим пример кода:
Исключение: библиотечные функции можно вызывать напрямую (без использования DELEGATECALL), только если они не изменяют состояние ( view или pure функции).
Более того, внутренние функции библиотек видны во всех смарт-контрактах, как если бы библиотека была базовым смарт-контрактом.
Давайте изучим процесс вызова внутренней ( internal ) библиотечной функции, чтобы понять, что именно происходит:
Контракт A вызывает внутреннюю функцию B из библиотеки L.
Во время компиляции EVM подтягивает внутреннюю функцию B в смарт-контракт A. Это было бы похоже на то, как если бы функция B была жестко закодирована в смарт-контракте A.
Вместо DELEGATECALL будет использоваться обычный вызов JUMP.
Вызовы внутренних функций используют ту же конвенцию внутреннего вызова:
могут быть переданы все внутренние типы.
типы, хранящиеся в памяти, будут передаваться по ссылке и не копироваться.
Несмотря на то, что у библиотек нет хранилища, они могут модифицировать хранилище своего связанного смарт-контракта, передавая аргумент хранилища в параметры своей функции. Таким образом, любое изменение, сделанное библиотекой через свою функцию, будет сохранено в собственном хранилище смарт-контракта.
Поэтому ключевое слово this будет указывать на смарт-контракт вызова, а точнее, ссылаться на хранилище вызывающего смарт-контракта.
Как использовать библиотечную функцию
Type variable = variable.libraryFunction(Type argument);
Ниже приведен пример.
6. Понимание функций в библиотеках
В библиотеке могут быть нереализованные функции (как в интерфейсах). В результате, функции такого типа должны быть объявлены как публичные или внешние. Нереализованные фукнции не могут быть приватными или внутренними.
Вот внутренняя функция, реализованная в функции testConnection() :
Примером нереализованных функций в нашей ситуации могут быть функции обратного вызова при подключении и отключении. При этом вы можете реализовать свой собственный код в теле функции основного смарт-контракта.
function onConnect() public;
function onDisconnect() public;
7. События и библиотеки
Точно так же, как у библиотек нет своего хранилища, у них нет и журнала событий. Однако библиотеки могут отправлять события.
Любое событие, созданное библиотекой, будет сохранено в журнале событий того смарт-контракта, который вызывает функцию, создающую событие в библиотеке.
Единственная проблема заключается в том, что на данный момент ABI смарт-контракта не отражает события, которые могут создавать используемые им библиотеки. Это сбивает с толку клиентов, таких как web3, которые не могут декодировать вызванное событие или понять, как декодировать его аргументы.
8. Отображения в библиотеках
Использование типа отображения ( mapping ) внутри библиотек отличается от использования этого типа в традиционных смарт-контрактах Solidity. Здесь мы поговорим об использовании этого типа в качестве параметра функции.
Вы можете использовать отображение в качестве параметра функции с любой видимостью: публичной ( public ), частной ( private ), внешней ( internal ) и внутренней ( external ).
Для сравнения, отображения можно передавать в качестве параметра только для internal или private функций внутри смарт-контрактов.
Предупреждение: местоположение данных может быть только в хранилище, если отображение передается в качестве параметров функции.
Поскольку мы используем отображение внутри библиотеки, мы не можем создать его внутри библиотеки (помните, что библиотеки не могут хранить переменные состояния). Давайте рассмотрим «возможный» пример того, как это может выглядеть:
9. Использование структур внутри библиотек
Обратите внимание, как функция subUint получает struct в качестве аргумента. В Solidity v0.4.24 это невозможно в смарт-контрактах, но возможно в Solidity библиотеках.
11. Использование модификаторов внутри библиотек
В библиотеках можно использовать модификаторы. Однако мы не можем экспортировать их в наш смарт-контракт, поскольку модификаторы являются функциями времени компиляции (своего рода макросами).
Поэтому модификаторы применяются только к функциям самой библиотеки и не могут быть использованы внешним смарт-контрактом библиотеки.
12. Что нельзя делать с библиотеками в Solidity?
Библиотеки не могут содержать изменяемые переменные. Если вы попытаетесь добавить переменную, которую можно изменить, вы получите следующую ошибку в Remix: TypeError: library can’t have non-constant state variable
Библиотеки не имеют журналов событий.
Уничтожить библиотеку невозможно.
Библиотека не может наследоваться.
13. Некоторые популярные существующие библиотеки
Вот список некоторых библиотек, написанных на Solidity, и их авторов:
Dapp-bin от Ethereum: включает такие интересные библиотеки, как IterableMapping, DoublyLinkedList, и еще одну StringUtils