truffle solidity что это
Coinside.ru
Сайт, который призывал вас купить Bitcoin еще в 2013 году
Пишем свой токен ERC20 на Solidity с помощью Truffle
Solidity — это язык написания умных контрактов (smart contracts) для EVM (Ethereum Virtual Machine). Solidity не был первым ЯП и не является единственным. Существуют также:
Есть мнение, что выбор такого легкомысленного ЯП, как Javascript в качестве прототипа для языка Solidity был не слишком удачен. Главное, на что пеняют противники Ethereum это то, что к Solidity невозможно применить аппарат атоматической проверки теорем, а значит ошибки в умных контрактах будут всегда стоить очень дорого.
Официальный сайт Ethereum содержит достаточно хорошую документацию по Solidity. Есть также попытки перевести ее на русский (спасибо Денису Солдатову), однако чтобы начать что-то разрабатывать на новом ЯП иногда не хватает ободряющего пинка под зад. Эта статья призвана понизить порог вхождения и служит цели помочь написать свой первый контракт на языке Solidity.
Выбираем фреймворк
Хотя программирование умных контрактов как жанр появилось сравнительно недавно, разработчики тут же стали писать инструменты для более удобной и быстрой разработки. Появились даже фреймворки. Вот небольшой обзор:
Embark
Embark поддерживает не только Ethereum, но и IPFS, Swarm, Whisper и Orbit. В комплекте удобная консоль. Пока нет поддержки пакетов ERC190.
Dapp (ранее dapple)
Это даже не фреймворк, а набор утилит для работы с проектом. С помощью менеджера пакетов nix инсталлируются все необходимые зависимости. Неудобно, что утилиту ethrun нужно ставить вручную и прописывать в PATH.
Populous
Написан на Питоне и тесты контрактов приходится писать также на нем. Находится в Alpha.
Truffle
Вебсайт: https://github.com/trufflesuite/truffle
Язык: Javascript
Тесты: Javascript/Mocha/Chai либо Solidity
Трюфель разработан и поддерживается компанией ConsenSys, стоящей за Виталиком Бутериным. Имеется поддержка миграций. Есть консоль.
OpenZeppelin
OpenZeppelin не фреймворк, а библиотека часто используемых классов и интерфейсов, проверенных аудиторами безопасности. Интегрируется с Truffle.
Обзор утилит
Создатели фреймворков стараются не изобретать велосипеды. Коротко познакомимся с общеупотребимыми инструментами:
Инсталлируем инструменты
Для нашего игрушечного проекта я выбрал Truffle, т.к. разрабатывая на Solidity тесты логично писать также на нем. На компьютере должен быть установлен node.js и пакетный менеджер npm. Сначала поставим testrpc:
Теперь пришла очередь поставить Truffle:
Теперь создадим пустую папку и проинициализируем проект:
mkdir try-solidity && cd try-solidity && truffle init
Пишем свой ERC20 токен
Дальнейшее есть краткий пересказ туториала. Наш игрушечный проект — это обычный умный контракт для токенов стандарта ERC20. OpenZeppelin уже содержит весь необходимый код, нам понадобится его только отконфигурировать под себя. Сперва поставим OpenZeppelin:
npm install zeppelin-solidity
Наш контракт будет унаследован от цеппелиновского StandardToken, создадим файл contracts/TutorialToken.sol и заполним его следующим содержимым:
Теперь следует создать скрипт миграции migrations/2_deploy_contracts.js:
Конечно наш токен никаких методов оригинального StandardToken не переписывает, а следовательно ошибок в себе содержать не должен и цеппелиновским тестам мы можем доверять, мы все равно напишем пару тестов. Truffle поддерживает как тесты на Javascript, так и на Solidity, однако последний довольно убог (в силу своего предназначения), так что лучше сразу на первом. Создадим файл tests/tutorial_token.js:
Теперь можно проверить, что тесты работают следующей командой:
За фасадом трюфель сам запустит testrpc, задеплоит контракт и прогонит тесты. И вот наш собственный токен с блекджеком и тестами готов, можно деплоить в основную сеть и собирать бабло.
Погружение в разработку на Ethereum. Часть 4: деплой и дебаг в truffle, ganache, infura
В прошлой статье мы рассмотрели разработанное приложение на Ethereum. Но обошли стороной вопрос как происходит процесс разработки. Ясно, что это не просто написание кода, который сразу работает. Большую часть времени придется потратить на то, чтобы доводить код, который “почти готов”, до рабочего состояния. Деплой, тестирование, отладка — все это в той или иной мере уже затрагивалось здесь например в этих неплохих статьях: раз, два, три (список не полный). В этой статье мы дадим небольшой обзор и возможно в чем-то повторимся, но постараемся сфокусироваться на тех моментах, которые нам показались важными или недосказанными. Плюс за последнее время некоторые штуки изменились, и огромное количество инструкций оказалось устаревшим. Постараемся немного подправить ситуацию.
Проект в truffle
Для тестирования и деплоя смарт контрактов мы пользуемся Truffle, он скрывает часть низкоуровневой работы за абстракциями, что очень удобно. Описанная версия — 4.0.6. Это не единственный фреймворк, есть еще Embark и Dapple, но по ним ничего сказать не можем, не приходилось работать. Для инициализации проекта надо выполнить команду (выполнится в текущей папке, поэтому предварительно создайте папку проекта и перейдите в нее):
Можете проверить, что у вас создались соответствующие файлы. Но содержимое совсем базовое, поэтому пока в этой фиче нет особого преимущества по сравнению с созданием тех же файлов вручную.
Работа с проектом
В более ранних версиях инициализация truffle init создавала сразу небольшой пример (Metacoin и ConvertLib). Чтобы в последних версиях увидеть этот и другие примеры, можно воспользоваться фичей, называемой Truffle Boxes. Боксы созданы для того, чтобы получить полноценный пример проекта Truffle и его взаимодействия с разными web-средствами, например ReactJS. Здесь перечислен список боксов, как официальных, так и созданных сообществом. Создайте директорию для нового проекта и перейдите в нее. Затем выполним команду:
Увидите подобный текст:
Что делает эта команда? Она поднимает тестовое окружение и дает доступ к нему через консоль. Тестовое окружение — это то, что вы могли видеть в более старых руководствах под названием TestRPC. На самом деле это оно и есть, просто команда Truffle взяла его под свое управление и переименовала в Ganache. Но об этом напишем далее, а пока перейдем к консоли. Выполним полный цикл команд для компиляции, миграции и тестирования:
Тестирование смарт контрактов Ethereum на примере DAO
При создании смарт контрактов на платформе Ethereum разработчик закладывает определенную логику работы, определяющую как методы должны изменять состояние контракта, какие должны эмитироваться события, когда и кому нужно произвести перевод средств, а когда бросить исключение. Инструменты отладки смарт контрактов еще не очень развиты, поэтому тесты зачастую становятся необходимым инструментом разработки, т.к. запускать контракты после каждого изменения может быть достаточно долгой процедурой. Также, в случае обнаружения ошибок, изменить код развернутого в сети контракта уже невозможно, можно только уничтожить контракт и создать новый, поэтому тестирование стоит проводить максимально подробно, особенно методы связанные с платежами. В статье будут показаны некоторые приемы тестирования, с которыми сталкиваются разработчики при создании и отладке смарт контрактов на Solidity.
Децентрализованная автономная организации (DAO)
Летом 2016 нашумела история с THE DAO, из которого злоумышленник увел значительные средства. DAO — это смарт контракт, который позиционирует себя как организацию, все процессы которой описаны кодом, работающим в блокчейн среде, при этом не является юридическим лицом и управляется коллективно всеми ее инвесторам. Еще в марте разработчики DAO подчеркнули важность тестирования и даже покрыли свой смарт контракт тестами, используя свой фреймворк на смеси Python и Javascript, но к сожалению тесты не закрыли использованную позднее уязвимость.
Код смарт контракта The DAO слишком большой для примера, поэтому в качестве объекта тестирования возьмем смарт контракт Congress, реализующий принципы DAO, который приводится в статье How to build a democracy on the blockchain на сайте http://ethereum.org. В дальнейшем предполагается знакомство с основными принципами разработки смарт контрактов.
Как происходит тестирование смарт контрактов
Общий принцип схож с тестированием любого другого кода — создается набор эталонных вызовов методов в предопределенном окружении, для результатов которых прописываются утверждения. Для тестирования удобно использовать практики BDD – Behavior Driven Development, которые наряду с тестами позволяют создать документацию и примеры использования.
Инструменты тестирования
В настоящее время разработаны ряд фреймворков и библиотек тестирования смарт контрактов Ethereum:
Truffle
В Truffle v.2 тесты разрабатываются на JavaScript, используются фреймворк Mocha и библиотека Chai. В версии 3 добавилась возможность писать тесты на Solidity.
DApple
В DApple тесты реализуются на Solidity, с использованием методов специально разработанных базовых смарт контрактов.
EmbarkJS
В EmbarkJS подход похож на Truffle, тесты пишутся на Javascript, используется фреймворк Mocha.
Разработка тестов на Solidity достаточно ограничена возможностями этого языка, поэтому будем использовать Javascript, все примеры будут с использованием Тruffle Framework. Также компоненты Truffle Framework, такие как truffle-contract или truffle-artifactor можно использовать для создания своих кастомных решений для взаимодействия со смарт контрактами.
Тестовый клиент
С учетом того, что блокчейн системы, в частности Ethereum, работают не очень быстро, для тестирования используются “тестовые” клиенты блокчейн, например, TestRPC, который почти полностью эмулируют работу JSON RPC API клиентов Ethereum. Помимо стандартных методов, TestRPC также реализует ряд дополнительных методов, которые удобно использовать при тестировании, такие как evm_increaseTime, evm_mine и др.
Альтернативный вариант — можно использовать один из стандартных клиентов, например Parity, работающий в dev режиме, при котором транзакции подтверждаются моментально. В дальнейших примерах будет использован TestRPC.
Настройка окружения
Тестовый клиент
Инсталляция через npm:
TestRPC должен быть запущен в отдельном терминале. При каждом запуске тестовый клиент генерирует 10 новых аккаунтов, на каждом из которых уже размещены средства.
Фреймворк Truffle
Инсталляция через npm:
Для создания структуры проекта нужно выполнить команду truffle init
Контракты должны быть расположены в директории contracts/, при компиляции контрактов Truffle Framework ожидает, что каждый контракт размещен в отдельном файле, название контракта равно названию файла. Тесты размещаются в директории test/. При выполнении команды truffle init также создаются тестовые контракты Metacoin и др.
В дальнейших примерах будет использоваться проект https://github.com/vitiko/solidity-test-example, в котором размещены код смарт контракта Congress и тесты для него. Тесты выполняются в среде Truffle v.2, в версии v.3, которая недавно вышла, есть небольшие отличия в части подключения сгенерированного Truffle кода и в формате данных транзакций, который возвращаются после вызова методов, изменяющих состояние.
Разработка тестов на базе Truffle framework
Организация тестов
В тестах используются JavaScript-объекты, представляющие собой абстракции для работы с контрактами, производящие маппинг между операциями над обьектами и вызовами JSON RPC методов клиента Ethereum. Данные объекты создаются автоматически при компиляции исходного кода *.sol файлов. Вызовы всех методов асинхронные и возвращают Promise, это позволяет не заботиться об отслеживании подтверждения транзакций, все реализовано “под капотом” компонент Truffle.
Тестирование изменения состояния смарт контракта
Для начала попробуем протестировать метод addMember изменяющий состояние смарт контракта — метод должен записать информацию об участнике DAO в массив структур members.
В тесте мы, используя массив с тестовыми аккаунтами, добавляем участников в контракт. Затем проверяем что функция members (геттер для массива структур members) возвращает внесенные данные. Нужно заметить, что при каждом вызове метода addMember создается транзакция и изменяется состояние блокчейна, т.е. информация записывается в распределенный реестр.
Тестирование событий
События в Ethereum имеют достаточно универсальное применение, они могут использоваться:
Для этого в тесте сначала создаем участника DAO и от его имени создаем предложение. Затем создаем подписчика на событие ProposalAdded и проверяем, что после вызова метода newProposal событие произошло и его атрибуты соответствуют переданным данным.
Тестирование ошибок и проверка отправителя сообщений
Стандартным методом прерывания работы метода контракта, являются исключения, которые можно создавать с помощью инструкции throw. Исключение может понадобиться, например, если необходимо ограничить доступ к методу. Для этого реализуется модификатор, который проверяет адрес аккаунта, вызвавшего метод, и если он не удовлетворяет условиям создается исключение. Для примера, создадим тест, проверяющий, что если метод addMember вызывает не владелец контракта — создается исключение. В коде ниже контракт Сongress создан от имени accounts[0], затем вызывается метод addMember от имени другой учетной записи.
Тестирование изменения баланса смарт контракта, использование текущего времени в смарт контракте
Возможно, наиболее ответственной функцией смарт контракта Congress, реализующего принципы DAO, является функция executeProposal, которая запускает проверку того, что предложение получило требуемое количество голосов и обсуждение предложения продлилось не менее чем минимальное необходимое время, заданное при создании смарт контракта, после чего перечисляет средства бенефициару обсуждаемого предложения.
Для имитации пройденного времени используем метод evm_increaseTime, который реализован в testrpc — c его помощью можно изменить внутреннее время блокчейн клиента.
Вспомогательные функции
В процессе написания тестов пригодились функции, которые удобно использовать для часто используемых операций при тестировании, таких как проверка на исключение, получение лога событий, изменение времени тестового клиента. Функции размещены в виде пакета https://www.npmjs.com/package/solidity-test-util, код размещен на github. Ниже приведен пример использования функции testUtil.assertThrow для проверки исключения:
Другие примеры с использованием функций solidity-test-util можно увидеть здесь.
Обзор всех аспектов среды Solidity. Среда разработки Ethereum, Web3 и Truffle
Обсудим, какое распределенное приложение нам предстоит создать
Этот раздел полностью посвящен изучению среды программирования Solidity. Однако перед тем, как погрузимся в ее изучение, давайте поговорим о том, какого рода распределенное приложение нам предстоит написать. В ходе этого курса будем создавать распределенный веб-кошелек с высокой степенью надежности. Его надежность обеспечена самой структурой блокчейна. Распределенность же означает, что к кошельку возможен доступ нескольких пользователей, однако распоряжаться хранящимися в кошельке средствами можно только при наличии соответствующего доступа.
Как же работает распределенный кошелек? У такого кошелька есть некоторый баланс, и несколько пользователей могут подключаться к нему и отправлять средства на другие счета. Эти операции отслеживаются через транзакции в блокчейне. Рассмотрим подробнее на примере. В нашем кошельке пять тысяч единиц эфира, и адрес 0xdeadbeef1 отправляет запрос на перевод одной тысячи единиц эфира на другой адрес 0xdeadbeef2. Кошелек должен будет проверить, что отправитель уполномочен распоряжаться хранящимся в кошельке эфиром. Если такие права есть, то на адрес 0xdeadbeef2 отправится перевод тысячи единиц эфира. Кроме того, это событие будет зарегистрировано, о транзакции будет составлен отчет.
Классы контрактов, функций и условий
Обратите внимание, что в этом же файле хранится еще один контракт.
Добавим в наше приложение переменную типа uint. Подробнее о типах переменных будет рассказано в другой лекции.
Если обратить внимание на раздел создания контракта в правой части браузера, можно заметить, что доступ к некоторым переменным по умолчанию ограничен. Чтобы взаимодействовать с этими переменными из других контрактов, необходимо задать ряд функций. Попробуем скомпилировать наш простой контракт и вставить его на вкладке Functions.
Все эти функции относятся к постоянным функциям, которые могут только возвращать значения. Они не могут изменять данные в блокчейне и поэтому для их обсчета не требуется тратить газ.
Посмотрим внимательнее, как работает приложение SimpleDapp. Сейчас функция getSomeVar возвращает наше число. По умолчанию эта переменная равна нулю.
Работа с функциями в Solidity не отличается от других языков программирования. Например, можно задать другую функцию, которая будет умножать нашу переменную на четыре и задавать какое-нибудь значение другой переменной. Теперь функция getSomeVar возвращает шестнадцать.
В среде Solidity содержимое контракта может обращаться к другому контракту. Давайте создадим контракт SomeOtherSimpleDapp, который будет возвращать значение someVar из контракта SimpleDapp.
Скопируем адрес и создадим OtherSimpleDapp.
В контракте OtherSimpleDapp пока нет настоящих функций.
Давайте напишем пару функций для демонстрации работы ссылок. Одна возвращает getSomeVar из контракта SimpleDapp, что является ссылкой на у копию SimpleDapp. Другая возвращает getSomeVar из новой копии SimpleDapp.
Создадим SimpleDapp еще раз. Теперь изменим значение someVar в первом контракте SimpleDapp, пусть это будет шестнадцать. Видно, что функция getSomeVar из первой копии контракта возвращает шестнадцать. Функция GetSimpleDappSomeVar из другого контракта, ссылающегося на контракт выше, тоже возвращает шестнадцать, поскольку является ссылкой на ранее созданный контракт.
Рассмотрим другой пример. Создадим новый контракт и новую переменную.
А теперь применим условие и вернем какое-нибудь значение для случаев, когда значение переменной равно двум, меньше двух или больше двух. Для ввода этого условия пригодится служебное слово if. Создадим еще одну функцию для установки значения переменной. Теперь создадим контракт.
Изначально переменная someVar имеет значение ноль, что, конечно, меньше двух. Изменим значение на четыре.
Теперь функция getMyVariable возвращает «greater than two», как и должно быть.
Изменим значение someVar на два. Теперь getMyVariable возвращает «is exactly two».
Можно задавать функции, которые будут возвращать больше одной переменной. Функция getMyVar возвращает две переменных: строку и переменную someVar.
Как тестировать смарт-контракты
Условия смарт-контракта нельзя изменить. Поэтому всякий раз, когда вы создаёте смарт-контракт, нужно убедиться, что он работает правильно. Тестирование — безопасный способ проверить контракт в разных ситуациях. В этом туториале вы узнаете, какие шаги для этого нужно предпринять.
Я расскажу:
1. Как подготовить тестовую среду
Существует много способов тестирования смарт-контрактов, но Truffle — самый популярный инструмент для написания тестов с использованием JavaScript. На Truffle можно как писать юнит-тесты, так и проводить полноценное интеграционное тестирование с реальными параметрами из продакшн среды.
Для начала нужно установить последнюю версию Node.js с официального сайта.
Затем открыть терминал и установить Truffle, используя следующую команду:
После установки Truffle, не закрывая терминал, создайте каталог Funding:
Далее, переходим в каталог командой:
Для инициализации каталога выполните команду:
После выполнения команды в каталоге Funding будут созданы следующие папки и файлы:
Дальше мы поработаем с каждым каталогом. А пока продолжим подготавливать тестовую среду.
Для запуска тестов понадобятся Javascript-библиотеки.
Mocha — библиотека, которая содержит общие функции для тестирования, включая describe и it.
Chai — библиотека, которая поддерживает разнообразные функции для проверок. Есть разные «стили» проверки результатов, и Chai предоставляет нам эту возможность. В туториале будем использовать Should.
По умолчанию Mocha входит в состав Truffle, мы можем без проблем использовать функции библиотеки. Chai необходимо установить вручную. Для этого используйте терминал и в корневом каталоге проекта выполните команду:
Также я установил библиотеку chai-bignumber для сравнения чисел с произвольной точностью:
На этом тестовая среда готова. Теперь можно приступить к разработке смарт-контракта и тестов для него.
2. Как написать тесты на JavaScript и выполнить их в Truffle
Для разработки тестов понадобится смарт-контракт. Мы разработаем контракт, который позволяет собирать пожертвования, задавать конкретную сумму для достижения сбора и выводить средства. Если кто-то пожертвует больше, то ему будет возвращена разница между суммой, которая набралась, и суммой, которую нужно собрать.
В Funding.sol добавим следующий код:
Контракт готов. Развернем смарт-контракт посредством миграции.
Миграции — это файлы JavaScript, которые помогут вам развернуть контракты в сети Ethereum. Это основной способ развертывания контрактов.
Чтобы запустить тесты, нужно использовать команду truffle test. В терминале переходим в корень каталога Funding, который создали при подготовке тестовой среды и вводим:
Если в терминале появится следующий вывод, то все сделано верно:
Теперь приступим к написанию тестов.
Проверка владельца
В файл test_funding.js нужно добавить следующий код:
В тесте мы проверяем, что контракт Funding хранит адрес владельца, который развернул контракт. В нашем случае account — это первый элемент массива. Truffle позволяет использовать до десяти адресов, в тестах нам понадобится всего три адреса.
Приём пожертвований и проверка окончания сбора средств
В этом разделе мы проверим:
Перед разбором теста, хочу отметить 2 момента:
В этом тесте проверили, что сбор средств ещё не завершился.
В тесте проверили, что не можем выводить средства, пока нужная нам сумма не будет собрана.
В тесте проверили, что если пожертвовать большую сумму, то метод donate() рассчитывает и возвращает средства тому, кто пожертвовал больше, чем нужно. Эта сумма равна разнице между суммой, которая набралась и суммой, которую требуется собрать.
В этих трёх тестах мы проверили:
Вывод средств
В предыдущем разделе туториала, мы собрали нужную нам сумму, теперь её можно вывести:
Вызвав функцию withdraw(), мы вывели средства владельца смарт-контракта, в нашем случае это account. Потом проверили, что действительно вывели нужную нам сумму. Для этого в константу difference записали разницу баланса до и после вывода средств. Полученный результат сравнили с суммой пожертвований минус плата за транзакцию. Как упоминалось выше, для удобства тестирования и расчетов, я установил собственную цену за gas.
Запустим написанные тесты командой truffle test. Если все сделали правильно, результат должен быть следующим:
Результат
Я попытался простым и понятным языком описать шаги тестирования смарт-контрактов: от подготовки тестовой среды до написания самих тестов.
Теперь вы сможете протестировать любой смарт-контракт и убедиться, что он работает правильно.