Solidity — это язык написания умных контрактов (smart contracts) для EVM (Ethereum Virtual Machine). Solidity не был первым ЯП и не является единственным. Существуют также:
- Serpent. Похож на Python. Морально устарел.
- Mutan. Для любителей языка C. Репозиторий не обновлялся уже 2 года.
- LLL (Low-Level-Lisp). Низкоуровневый на уровне ассемблера, документации почти нет.
- Viper. Новый и пока экспериментальный ЯП, снова Python.
Есть мнение, что выбор такого легкомысленного ЯП, как Javascript в качестве прототипа для языка Solidity был не слишком удачен. Главное, на что пеняют противники Ethereum это то, что к Solidity невозможно применить аппарат атоматической проверки теорем, а значит ошибки в умных контрактах будут всегда стоить очень дорого.
Официальный сайт Ethereum содержит достаточно хорошую документацию по Solidity. Есть также попытки перевести ее на русский (спасибо Денису Солдатову), однако чтобы начать что-то разрабатывать на новом ЯП иногда не хватает ободряющего пинка под зад. Эта статья призвана понизить порог вхождения и служит цели помочь написать свой первый контракт на языке Solidity.
Выбираем фреймворк
Хотя программирование умных контрактов как жанр появилось сравнительно недавно, разработчики тут же стали писать инструменты для более удобной и быстрой разработки. Появились даже фреймворки. Вот небольшой обзор:
Embark
Вебсайт: https://github.com/iurimatias/embark-framework
Язык: Javascript
Тесты: Javascript/Mocha
Embark поддерживает не только Ethereum, но и IPFS, Swarm, Whisper и Orbit. В комплекте удобная консоль. Пока нет поддержки пакетов ERC190.
Dapp (ранее dapple)
Вебсайт: https://github.com/iurimatias/embark-framework
Язык: Bash
Тесты: Solidity
Это даже не фреймворк, а набор утилит для работы с проектом. С помощью менеджера пакетов nix инсталлируются все необходимые зависимости. Неудобно, что утилиту ethrun нужно ставить вручную и прописывать в PATH.
Populous
Вебсайт: http://populus.readthedocs.io/en/latest/quickstart.html
Язык: Python
Тесты: py.tests
Написан на Питоне и тесты контрактов приходится писать также на нем. Находится в Alpha.
Truffle
Вебсайт: https://github.com/trufflesuite/truffle
Язык: Javascript
Тесты: Javascript/Mocha/Chai либо Solidity
Трюфель разработан и поддерживается компанией ConsenSys, стоящей за Виталиком Бутериным. Имеется поддержка миграций. Есть консоль.
OpenZeppelin
Вебсайт: https://github.com/OpenZeppelin/zeppelin-solidity
Язык: Solidity
OpenZeppelin не фреймворк, а библиотека часто используемых классов и интерфейсов, проверенных аудиторами безопасности. Интегрируется с Truffle.
Обзор утилит
Создатели фреймворков стараются не изобретать велосипеды. Коротко познакомимся с общеупотребимыми инструментами:
- ethereumjs: набор утилит и Javascript-библиотек для работы с Ethereum. Утилита ethereumjs-vm, входящая в набор является эмулятором EVM (Ethereum Virtual Machine).
- geth: официальный клиент Ethereum для командной строки. Также является нодой и может майнить в основном блокчейне, тестовом или приватном. С ним можно коммуницировать через интерфейс RPC.
- testrpc: также из набора ethereumjs. Запускает эмуляцию EVM с помощью ethereumjs-vm и предоставляет RPC-интерфейс аналогичный geth.
- solc: компиллятор скриптов на Solidity.
Инсталлируем инструменты
Для нашего игрушечного проекта я выбрал Truffle, т.к. разрабатывая на Solidity тесты логично писать также на нем. На компьютере должен быть установлен node.js и пакетный менеджер npm. Сначала поставим testrpc:
npm install -g ethereumjs-testrpc
Теперь пришла очередь поставить Truffle:
npm install -g truffle
Теперь создадим пустую папку и проинициализируем проект:
mkdir try-solidity && cd try-solidity && truffle init
Пишем свой ERC20 токен
Дальнейшее есть краткий пересказ туториала. Наш игрушечный проект — это обычный умный контракт для токенов стандарта ERC20. OpenZeppelin уже содержит весь необходимый код, нам понадобится его только отконфигурировать под себя. Сперва поставим OpenZeppelin:
npm install zeppelin-solidity
Наш контракт будет унаследован от цеппелиновского StandardToken, создадим файл contracts/TutorialToken.sol и заполним его следующим содержимым:
pragma solidity ^0.4.18;
import 'zeppelin-solidity/contracts/token/StandardToken.sol';
contract TutorialToken is StandardToken {
string public name = 'TutorialToken';
string public symbol = 'TT';
uint public decimals = 2;
uint public INITIAL_SUPPLY = 12000;
function TutorialToken() {
totalSupply = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
}
}
Теперь следует создать скрипт миграции migrations/2_deploy_contracts.js:
var TutorialToken = artifacts.require("TutorialToken");
module.exports = function(deployer) {
deployer.deploy(TutorialToken);
};
Конечно наш токен никаких методов оригинального StandardToken не переписывает, а следовательно ошибок в себе содержать не должен и цеппелиновским тестам мы можем доверять, мы все равно напишем пару тестов. Truffle поддерживает как тесты на Javascript, так и на Solidity, однако последний довольно убог (в силу своего предназначения), так что лучше сразу на первом. Создадим файл tests/tutorial_token.js:
var TutorialToken = artifacts.require("TutorialToken");
contract('TutorialToken', function(accounts) {
let owner = accounts[0];
let second_account = accounts[1];
let token;
beforeEach(async function() {
token = await TutorialToken.deployed();
});
it('should return the correct totalSupply after construction', async function() {
let totalSupply = await token.totalSupply();
assert.equal(totalSupply, 12000);
});
it('transfer updates balance of counterparties', async function() {
await token.transfer(second_account, 100);
let owner_balance = await token.balanceOf(owner);
let second_account_balance = await token.balanceOf(second_account);
assert.equal(owner_balance, 12000 - 100);
assert.equal(second_account_balance, 100);
});
});
Теперь можно проверить, что тесты работают следующей командой:
truffle test
За фасадом трюфель сам запустит testrpc, задеплоит контракт и прогонит тесты. И вот наш собственный токен с блекджеком и тестами готов, можно деплоить в основную сеть и собирать бабло.