Вы находитесь на странице: 1из 25

Смарт-контракты

Смарт-контракты в сети
Ethereum

© geekbrains.ru
На этом уроке
1 Познакомимся со смарт-контрактами. Узнаем, в какой среде они выполняются.
2 Поговорим об ограничениях смарт-контрактов и их обходных путях.
3 Разберём языки программирования для написания смарт-контрактов.
4 Научимся компилировать, тестировать и развёртывать смарт-контракты.

Оглавление
Глоссарий

Введение в смарт-контракты

Что такое смарт-контракты?

Виртуальная машина Ethereum (EVM)

Газ и комиссии

Ограничения

Языки программирования смарт-контрактов

Solidity

Viper

YUL и YUL+

YUL

YUL+

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

Что хорошего в Solidity?

Что хорошего в Vyper?

Что хорошего в YUL и YUL+?

Из каких частей состоят смарт-контракты?

DATA

Storage

Memory

Переменные окружения (Environment variables)

Функции

Функции типа view

Функция Constructor

События и журналы

Библиотеки

© geekbrains.ru 1
Шаблоны и библиотеки

Стандарты

Безопасность и библиотеки

Развёртывание и взаимодействие со смарт-контрактами

Компиляция

Двоичный интерфейс приложения — АBI

Что потребуется для развёртывания контракта?

Процесс развёртывания смарт-контракта в тестовой среде

Практическое задание

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

Используемые источники

Глоссарий
Виртуальная машина — программная и/или аппаратная система, которая:

● эмулирует аппаратное обеспечение некоторой платформы, например, Target — целевая или


гостевая платформа;
● исполняет программы для платформы Target на host-платформе, где host —
платформа-хозяин;
● виртуализирует некоторую платформу и создаёт на ней среды, изолирующие друг от друга
программы и даже операционные системы.

Конечный автомат — математическая абстракция, модель дискретного устройства:

● имеющего один вход и выход;


● в каждый момент времени, находящегося в одном состоянии из множества возможных. Это
частный случай абстрактного дискретного автомата, число возможных внутренних состояний
которого конечно.

Введение в смарт-контракты
Что такое смарт-контракты?
«Умный контракт» — это простая программа, работающая в сети Ethereum. Она находится по
конкретному адресу в блокчейне Ethereum. Смарт-контракт состоит:

● из кода — его функции;


● и данных — его состояние.

© geekbrains.ru 2
Смарт-контракты — это одна из разновидностей учётной записи сети Ethereum. Это означает, что у
смарт-контракта есть баланс, и он отправляет транзакции внутри сети. Такой контракт развёртывается
в сети и работает в соответствии с заложенным алгоритмом. Пользователи взаимодействуют со
смарт-контрактом путём транзакций. Последние вызывают определённые в смарт-контракте функции.

Виртуальная машина Ethereum (EVM)


Физический экземпляр EVM работает как единое целое и поддерживается тысячами подключённых
компьютеров. На этих компьютерах работает клиент Ethereum. Задача протокола Ethereum —
поддержание непрерывной и неизменной работы этого конечного автомата.

EVM — это среда, в которой живут все учётные записи Ethereum, в том числе и смарт-контракты. В
любом блоке сети Ethereum имеется только одно «каноническое» состояние, а EVM — это то, что
определяет правила для вычисления нового допустимого состояния от блока к блоку.

Аналогия с «распределённым реестром» часто используется для описания таких блокчейнов, как
Биткойн. Криптовалюта ведёт себя как «обычная» валюта из-за правил, которые определяют, что
можно или нельзя делать для изменения этого реестра.

Например, биткойн-адрес не тратит больше биткоинов, чем получил ранее. Эти правила лежат в
основе всех транзакций сети и во многих других блокчейнах.

Хотя у Ethereum есть собственная криптовалюта (Ether), которая следует почти таким же интуитивно
понятным правилам, она также обеспечивает гораздо более мощную функцию — смарт-контракты.
Для этой сложной функции требуется и сложная аналогия. Вместо «распределённого реестра»
Ethereum представляет собой «распределённый конечный автомат».

Состояние Ethereum — это большая структура данных, которая содержит не только все счета и
балансы, но и состояние машины. Последнее изменяется от блока к блоку в соответствии с заранее
определённым набором правил и выполняет произвольный машинный код. Конкретные правила
изменения состояния от блока к блоку определяются EVM.

EVM работает как стековая машина с глубиной 1024 элементов. Каждый элемент представляет собой
256-битное слово, которое используется для максимальной совместимости с хеш-схемой SHA-3-256.
Во время выполнения EVM поддерживает временную память в виде массива байтов. Эта память не
сохраняется между транзакциями.

© geekbrains.ru 3
Газ и комиссии
Газ — это единица измерения. Она измеряет объём вычислительных усилий, требуемых для
выполнения конкретных операций в сети Ethereum. Поскольку для выполнения каждой транзакции
Ethereum нужны вычислительные ресурсы, каждая транзакция требует комиссию. Газ — это комиссия
для успешного выполнения транзакции в сети Ethereum.

По сути, сборы за газ оплачиваются в эфире (ETH). Цены на газ указываются в Gwei, который сам по
себе — номинал ETH. Каждый Gwei равен 0,000000001 ETH (10e-9 ETH).

Оплата газа помогает поддерживать безопасность сети Ethereum. Так как требуется плата за каждое
вычисление, выполняемое в сети, мы предотвращаем рассылку спама участниками сети.

Использование газа предотвращает случайные или вредоносные бесконечные циклы, а также другие
вычислительные потери в коде. Для каждой транзакции устанавливается ограничение на количество
используемых вычислительных шагов. При этом газ, не использованный в транзакции, возвращается
пользователю.

© geekbrains.ru 4
Каждый может развернуть смарт-контракт в сети. Но требуется иметь достаточное число ETH для
разворачивания контракта. Разворачивание смарт-контракта — технически транзакция. Поэтому
нужно платить за газ, как и за простой перевод ETH. Однако затраты на газ для развёртывания
смарт-контракта намного выше.

Ограничения
Сами по себе смарт-контракты не получают информации о «реальных» событиях, потому что они не
отправляют HTTP-запросы. Это сделано намеренно, поскольку использование внешней информации
ставит под угрозу консенсус. А это важно для безопасности и децентрализации. Есть способы обойти
это путём использования оракулов.

Размер контрактов ограничивается размером транзакции. Это ограничение обходят благодаря


созданию системы смарт-контрактов.

Языки программирования
смарт-контрактов
Отличный аспект Ethereum — возможность программировать смарт-контракты с использованием
относительно удобных для разработчиков языков. Если имеется опыт работы с Python или JavaScript,
можно найти язык со знакомым синтаксисом.

Два наиболее активных и поддерживаемых языка:


1 Solidity — для любителей JavaScript.
2 Vyper — для любителей Python.

© geekbrains.ru 5
Более опытные разработчики иногда используют Yul, промежуточный язык для виртуальной машины
Ethereum, или Yul +, расширение Yul.

Solidity
Статически типизирован, тип переменной известен во время компиляции.

Поддерживает:
1. Наследование — возможность продлевать другие контракты.
2. Библиотеки — возможность создавать повторно используемый код, чтобы вызывать его из
разных контрактов. Например, статические функции в классе других
объектно-ориентированных языков программирования.
3. Сложные пользовательские типы.
Пример кода контракта:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.7.0;

contract Coin {
// The keyword "public" makes variables
// accessible from other contracts
address public minter;
mapping (address => uint) public balances;

// Events allow clients to react to specific


// contract changes you declare
event Sent(address from, address to, uint amount);

// Constructor code is only run when the contract


// is created
constructor() {
minter = msg.sender;
}

// Sends an amount of newly created coins to an address


// Can only be called by the contract creator
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}

// Sends an amount of existing coins


// from any caller to an address
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}

© geekbrains.ru 6
Viper
Python — язык программирования с сильной типизацией, он имеет небольшой и понятный код
компилятора.

Этот язык имеет меньше функций, чем Solidity, чтобы сделать контракты более безопасными и
простыми для аудита. Vyper не поддерживает некоторую функциональность, например:

1. Модификаторы.

2. Наследование.

3. Перегрузка функций.

4. Перегрузка оператора.

5. Рекурсивный вызов.

Так как языки быстро развиваются, актуальная информация содержится в документации.

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


# Open Auction

# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)

# Current state of auction


highestBidder: public(address)
highestBid: public(uint256)

# Set to true at the end, disallows any change


ended: public(bool)

# Keep track of refunded bids so we can follow the withdraw pattern


pendingReturns: public(HashMap[address, uint256])

# Create a simple auction with `_bidding_time`


# seconds bidding time on behalf of the
# beneficiary address `_beneficiary`.
@external
def __init__(_beneficiary: address, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = block.timestamp
self.auctionEnd = self.auctionStart + _bidding_time

# Bid on the auction with the value sent


# together with this transaction.
# The value will only be refunded if the
# auction is not won.
@external
@payable
def bid():
# Check if bidding period is over.
assert block.timestamp < self.auctionEnd
# Check if bid is high enough

© geekbrains.ru 7
assert msg.value > self.highestBid
# Track the refund for the previous high bidder
self.pendingReturns[self.highestBidder] += self.highestBid
# Track new high bid
self.highestBidder = msg.sender
self.highestBid = msg.value

# Withdraw a previously refunded bid. The withdraw pattern is


# used here to avoid a security issue. If refunds were directly
# sent as part of bid(), a malicious bidding contract could block
# those refunds and thus block new higher bids from coming in.
@external
def withdraw():
pending_amount: uint256 = self.pendingReturns[msg.sender]
self.pendingReturns[msg.sender] = 0
send(msg.sender, pending_amount)

# End the auction and send the highest bid


# to the beneficiary.
@external
def endAuction():
# It is a good guideline to structure functions that interact
# with other contracts (i.e. they call functions or send Ether)
# into three phases:
# 1. checking conditions
# 2. performing actions (potentially changing conditions)
# 3. interacting with other contracts
# If these phases are mixed up, the other contract could call
# back into the current contract and modify the state or cause
# effects (ether payout) to be performed multiple times.
# If functions called internally include interaction with external
# contracts, they also have to be considered interaction with
# external contracts.

# 1. Conditions
# Check if auction endtime has been reached
assert block.timestamp >= self.auctionEnd
# Check if this function has already been called
assert not self.ended

# 2. Effects
self.ended = True

# 3. Interaction
send(self.beneficiary, self.highestBid)

YUL и YUL+
Использовать Yul или Yul + рекомендуется только после ознакомления с лучшими практиками
безопасной разработки смарт-контрактов и особенностями работы с EVM.

© geekbrains.ru 8
YUL
Промежуточный язык для Ethereum. Поддерживает EVM и eWASM (WebAssembly для Ethereum), и
разработан как общий знаменатель для обеих платформ.

YUL+
Низкоуровневое, высокоэффективное расширение для YUL. YUL + рассматривается как
экспериментальное предложение по обновлению 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}

Сравнение языков
Как и в случае с другим языком программирования, в основном речь идёт о выборе подходящего
инструмента для правильной работы, а также личных предпочтений. Вот несколько вещей, которые
следует учитывать, если не применён ни один из языков:

Что хорошего в Solidity?


1 Для новичка есть множество руководств и обучающих инструментов.
2 Доступны продвинутые инструменты разработки.
3 У Solidity большое сообщество разработчиков. Это значит, что пользователь, скорее всего,
быстро найдёт ответы на свои вопросы.

Что хорошего в Vyper?


1 Отличный выбор для разработчиков Python, которые хотят разрабатывать смарт-контракты.
2 Vyper имеет меньшее число функций, что делает его отличным средством для быстрого
прототипирования.
3 Vyper стремится быть лёгким для аудита и максимально удобочитаемым.

Что хорошего в YUL и YUL+?


1 Упрощённый и функциональный язык низкого уровня.

© geekbrains.ru 9
2 Позволяет спуститься на уровень EVM, что может оптимизировать использование газа в
контрактах.

Из каких частей состоят


смарт-контракты?
DATA
Любые данные контракта обязательно назначаются местоположению: к storage или memory.
Модифицировать хранилище в смарт-контракте дорого, поэтому всегда нужно следить за тем, где
находятся данные.

Storage
Постоянные данные называются хранилищем и представляются переменными состояния. Эти
значения постоянно хранятся в блокчейне. Требуется объявить тип, чтобы контракт отслеживал,
сколько памяти в блокчейне ему потребуется при компиляции.

contract SimpleStorage {
uint storedData; // State variable
// ...
}

Если у пользователя есть опыт программирования на объектно-ориентированных языках, то он


знаком с большинством типов. Однако тип address, скорее всего, окажется новым, если юзер —
новичок в разработке Ethereum.

Тип address содержит также адрес сети Ethereum, в котором находятся до 20 байт или 160 бит. При
чтении имеет вид в шестнадцатеричной системе счисления с начальным 0x. Например,
0x607c794cda77efb21f8848b7910ecf27451ae842.

Следующий список типов:


1 Логический.
2 Целочисленный.
3 Число с фиксированной точкой.
4 Байтовый массив фиксированного размера.
5 Байтовый массив динамического размера.
6 Рациональные и целочисленные литералы.
7 Строковые литералы.
8 Шестнадцатеричные литералы.
9 Перечисления.

© geekbrains.ru 10
Memory
Эти переменные появляются только во время выполнения функции. Они имеют тип memory.
Поскольку переменные не хранятся постоянно в блокчейне, их использование намного дешевле.

Переменные окружения (Environment variables)


В дополнение к переменным, которые определяются в контракте, есть некоторые специальные
глобальные переменные. Они в основном используются для предоставления информации о блоке или
текущей транзакции.

Примеры:

Имя Тип переменной Описание

block.timestamp uint256 Метка времени текущего блока

msg.sender адрес Отправитель сообщения

Функции
Функции могут получать (get) данные или сохранять (set) в ответ на входящие транзакции.

Есть два типа вызовов функций:

1 internal — данные функции не создают вызов EVM, доступ к внутренним функциям и


переменным состояния возможен только изнутри. То есть из текущего контракта или
вытекающих из него контрактов.
2 external — создают вызов EVM. Такие внешние функции — часть интерфейса контракта. Это
означает, что их можно вызывать из других контрактов и через транзакции. Внешняя функция
не вызывается изнутри, то есть f() не работает, а this.f() работает.
Функии также имеют следующие модификаторы видимости public или private.

1 public-функции вызываются внутри контракта или извне через сообщения.


2 private-функции видны только для контракта, в котором они определены, а не находятся в
производных контрактах.
И функции, и переменные состояния делятся на два вида: открытые или закрытые.

Функция для обновления переменной состояния в контракте:

1 function update_name(string value) public {


2 dapp_name = value;
3}

1 В функцию update_name передаётся параметр value типа string.


2 Функция объявлена public. Это означает, что любой может получить к ней доступ.
3 Функция не объявлена как view, так как она способна изменять состояние контракта.

© geekbrains.ru 11
Функции типа view
Такие функции не изменяют состояние данных контракта. Это функции getter — они используются,
например, для получения баланса пользователя.

1 function balanceOf(address _owner) public view returns (uint256 _balance) {


2 return ownerPizzaCount[_owner];
3 }

Что считается изменяющим состоянием:


1 Запись в переменные.

2 Генерация событий (event).

3 Создание других контрактов.

4 Использование команды самоуничтожения selfdestruct.

5 Отправка эфира.

6 Вызов любой функции, не отмеченной view или pure.

7 Использование низкоуровневых функций.

8 Использование assembly, содержащей определённые коды операций.

Функция Constructor
Функция constructor выполняется только один раз при первом развёртывании контракта. Эти функции
чаще всего инициализируют переменные.

// Initializes the contract's data, setting the `owner` to the address of the
contract creator.
constructor() public {
// All smart contracts rely on external transactions to trigger its
functions.
// `msg` is a global variable that includes relevant data on the given
transaction,
// such as the address of the sender and the ETH value included in the
transaction.
owner = msg.sender;
}

В дополнение к переменным и функциям, которые определяются в контракте, есть несколько


специальных встроенных функций. Простой пример:

address.send().

Эта функция позволяет контрактам отправлять ETH на другие счета.

События и журналы
События позволяют общаться со смарт-контрактом путём использования внешнего интерфейса или
других приложений-подписчиков. В процессе выполнения транзакции смарт-контракты генерируют
события и записывают их в блокчейн, которые затем может обрабатывать интерфейс. Контракты не
умеют считывать события из другого контракта.

© geekbrains.ru 12
Библиотеки
Не нужно писать каждый смарт-контракт в проекте. Доступно множество библиотек смарт-контрактов
с открытым исходным кодом. Библиотеки избавят от создания смарт-контактов.

Шаблоны и библиотеки
При написании смарт-контрактов есть большая вероятность создания похожих шаблонов. Например,
назначение адреса администратора для выполнения защищённых операций в контракте.

Шаблоны поведения представляются в виде библиотек или через наследование в Solidity. И в


качестве примера ниже приводится упрощённая версия Ownable контракта из библиотеки
OpenZeppelin Contracts. Она определяет адрес как владельца контракта и предоставляет
модификатор для ограничения доступа к методу только для этого пользователя.

contract Ownable {
address public owner;

constructor() {
owner = msg.sender;
}

modifier onlyOwner() {
require(owner == msg.sender, "Ownable: caller is not the owner");
_;
}
}

Чтобы использовать такой строительный блок в контракте, нужно сначала импортировать его, а затем
наследовать в собственных контрактах. Это позволит использовать модификатор, предусмотренный
базовым Ownable контрактом, для защиты своих функций.

import ".../Ownable.sol"; // Path to the imported library

contract MyContract is Ownable {


// The following function can only be called by the owner
function secured() onlyOwner public {
msg.sender.transfer(1 ether);
}
}

Другой популярный пример — SafeMath или DsMath. Это библиотеки, в отличие от базовых
контрактов, которые предоставляют арифметические функции с проверками переполнения.
Последние до версии 0.8.0 не предусмотрены языком Solidity. Раньше рекомендовалось использовать
любую из этих библиотек вместо собственных арифметических операций для защиты контракта от
переполнений.

© geekbrains.ru 13
Стандарты
Чтобы облегчить совместимость, сообщество Ethereum определило несколько стандартов в форме
ERC. При включении ERC в контракты рекомендуется искать стандартные реализации, а не пытаться
развернуть собственные.

Стоит отметить, что некоторые ERC — не автономны. Они считаются дополнением к другим ERC.
Например, ERC2612 добавляет расширение к ERC20 для повышения удобства использования.

Безопасность и библиотеки
Библиотеки смарт-контрактов с открытым исходным кодом также часто подвергаются тщательной
проверке. Поскольку от них зависят многие проекты, у сообщества есть сильный стимул держать их
под постоянным контролем. Гораздо чаще ошибки обнаруживаются в коде приложения, чем в
многократно используемых библиотеках контрактов.

Однако использование библиотек смарт-контрактов сопрягается с риском включения незнакомого


кода в свой проект. Заманчиво импортировать контракт и включить его прямо в собственный проект.
Но без хорошего понимания, что делает этот контракт, можно случайно создать проблему в своей
системе из-за неожиданного поведения. Обязательно нужно читать документацию по импортируемому
коду, а затем просматривать сам код, прежде чем делать его частью своего проекта!

Наконец, при принятии решения о включении библиотеки следует учитывать её общее


использование. Широко распространённый метод имеет преимущество, что у него более широкое
сообщество и больше людей, которые следят за его проблемами. Безопасность — главное при
создании смарт-контрактов.

Развёртывание и взаимодействие со смарт-контрактами

Компиляция
Чтобы EVM выполняла контракт, он должен быть в байт-коде. После компилирования контракт:

pragma solidity 0.4.24;

contract Greeter {

function greet() public constant returns (string) {


return "Hello";
}

Выглядит вот так:

PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0
CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000
SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xCFAE3217 EQ PUSH2 0x46 JUMPI JUMPDEST
PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x52 JUMPI PUSH1 0x0

© geekbrains.ru 14
DUP1 REVERT JUMPDEST POP PUSH2 0x5B PUSH2 0xD6 JUMP JUMPDEST PUSH1 0x40 MLOAD
DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2
MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4
DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x9B JUMPI DUP1 DUP3 ADD MLOAD
DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x80 JUMP JUMPDEST POP
POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xC8
JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB
NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1
0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x40 DUP1 MLOAD
SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32
0x48656C6C6F000000000000000000000000000000000000000000000000000000 DUP2 MSTORE
POP SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 SLT 0xec 0xe
0xf5 0xf8 SLT 0xc7 0x2d STATICCALL ADDRESS SHR 0xdb COINBASE 0xb1 BALANCE 0xe8
0xf8 DUP14 0xda 0xad DUP13 LOG1 0x4c 0xb4 0x26 0xc2 DELEGATECALL PUSH7
0x8994D3E002900

Двоичный интерфейс приложения — АBI


Компилятор также создаёт двоичный интерфейс приложения (ABI) в виде JSON-файла. ABI
описывает функции смарт-контракта.

Ниже приводится часть ABI для контракта токена ERC-20.

[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"

© geekbrains.ru 15
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "from",
"type": "address"
},
{
"indexed": true,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
]

Что потребуется для развёртывания контракта?


1. Байт-код контракта.

2. Эфир для оплаты комиссии. При этом важно понимать, что разворачивание контракта требует
намного больше газа, чем простой перевод ETH.

3. Доступ к узлу Ethereum: запустить свой или подключиться к общедоступному узлу, например, с
использованием сервиса Infura.

Чтобы развернуть смарт-контракт, отправляется транзакция Ethereum. Она содержит код


скомпилированного смарт-контракта без указания каких-либо получателей.

После развёртывания у контракта появляется адрес Ethereum и другие учётные записи.

Процесс развёртывания смарт-контракта в тестовой среде


Для выполнения всех шагов нужно подключиться к интернету.

© geekbrains.ru 16
Первый шаг — зайдём на страницу Remix IDE и создадим новый файл. В верхней левой части
интерфейса Remix добавим новый файл и введём желаемое имя файла.

Второй шаг — в новый файл вставляем следующий код.

pragma solidity 0.5.17;

contract Counter {

// Public variable of type unsigned int to keep the number of counts


uint256 public count = 0;

// Function that increments our counter


function increment() public {
count += 1;
}

// Not necessary getter to get the count value


function getCount() public view returns (uint256) {
return count;
}

Если есть навык программирования, то станет понятно, что делает эта программа. Построчное
объяснение:

1. Строка 3: Определяем контракт с именем Counter.

© geekbrains.ru 17
2. Строка 6: В нашем контракте хранится одно целое число без знака, его имя count, и оно

начинается с 0.

3. Строка 9: Первая функция изменит состояние контракта, increment(), нашу переменную

count.

4. Строка 14: Вторая функция — геттер. Он считывает значение count переменной вне

смарт-контракта. Мы определили переменную сount как общедоступную, но это


необязательно и показано в качестве примера.

Контракт выглядит как класс из языков ООП, таких как Java или C ++.

Шаг третий — скомпилируем контракт, щёлкнув значок компиляции слева:

Затем нажмём кнопку компиляции:

© geekbrains.ru 18
Шаг четвёртый — перейдём к экрану развёртывания и выполнения транзакций:

© geekbrains.ru 19
Когда мы перейдём на экран транзакций Deploy and run, нужно дважды убедиться, что отображается
название контракта. Далее нажмём Deploy. В верхней части страницы текущая среда — Javascript VM.
Это означает, что мы развернём и будем взаимодействовать с нашим смарт-контрактом в локальной
тестовой сети. Так появится возможность проводить тестирование быстрее и без каких-либо
комиссий.

© geekbrains.ru 20
После того как мы нажали кнопку Deploy, наш контракт появится внизу. Щёлкнем стрелку слева, чтобы
развернуть её и увидеть содержание нашего контракта. Это переменная counter, функция
increment() и геттер getCounter().

Если нажать кнопку count или getCount, появится содержимое переменной count контракта, и оно
отобразится на экране. Поскольку мы ещё не вызывали increment-функцию, она покажет 0.

© geekbrains.ru 21
Теперь вызовем increment-функцию, нажав на кнопку. Отобразился журнал выполненных транзакций,
которые появятся в нижней части окна. Мы увидим, что записи в журнале отличаются, когда
нажимаем на кнопку для получения данных вместо increment-кнопки. Это потому, что для чтения
данных в блокчейне не нужны транзакции (запись) или комиссии. Только для изменения состояния
блокчейна требуется совершить транзакцию:

После нажатия кнопки увеличения сгенерируется транзакция для вызова нашей increment()-функции.
Если мы снова кликнем на count или getCount, то прочитаем недавно обновлённое состояние нашего
смарт-контракта с переменной count больше 0.

© geekbrains.ru 22
Практическое задание
Повторите процесс развёртывания контракта, но уже используя код контракта для ERC20-токена с
применением Remix IDE.

1 Возьмите контракт токена ERC20 и разверните его, используя Remix IDE.


2 Сделайте несколько transfer и transferFrom на некоторые тестовые адреса.
3 *(Необязательно) Разверните контракт в сети Ropsten. Для подтверждения транзакций
используйте MetaMask (ссылка).

Дополнительные материалы
1. Документация языка Vyper.
2. Документация языка Solidity.
3. Документация языка YUL.

© geekbrains.ru 23
4. Документация языка YUL+.
5. Рекомендации по созданию безопасных смарт-контрактов.
6. Официальный репозиторий языка eWASM.
7. Сравнение языков разработки смарт-контрактов.
8. Одна из популярнейших библиотек смарт-контрактов.
9. Документация к библиотеке OpenZeppelin.
10. Библиотека смарт-контрактов.
11. Ещё одна библиотека смарт-контрактов.
12. Учебное пособие по стандарту ERC20.
13. Среда разработки.

Используемые источники
1. Ethereum EVM illustrated.
2. Ethereum development documentation.
3. Deploying your first smart contract.

© geekbrains.ru 24

Вам также может понравиться