Блокчейн — это основа криптовалюты, которая переопределяет способ нашего общения через интернет. Он создает децентрализованную систему, основанную на токенах, где вкладчики становятся владельцами актива, а не гостями.
Смарт-контракты играют важную роль в популярности блокчейна, поскольку делают транзакции более безопасными и организованными.
Ethereum — это платформа с открытым исходным кодом, которая позволяет любому желающему создавать и запускать dapps на блокчейне. Она позволяет пользователям создавать смарт-контракты, которые могут быть развернуты и выполнены виртуальной машиной Ethereum (EVM). Solidity — это язык, используемый для создания таких смарт-контрактов.
В этой статье мы научимся создавать смарт-контракт с помощью Solidity.
- Начало работы
- Блокчейн
- Криптовалюта
- Ethereum
- Умные контракты
- Виртуальная машина Ethereum (EVM)
- Solidity
- Настройка среды
- Автономный режим
- Онлайн-режим
- Основы Solidity
- Прагма версии
- Контракт
- Переменные
- Типы Solidity
- Функция
- Модификаторы
- Конструкторы
- События
- Обработка ошибок
- Первый смарт-контракт
- 1. Напишите контракт
- 2. Настройка миграции
- 3. Компиляция и развертывание
- 4. Протестируйте контракты
- 5. Работа с IDE Remix
Начало работы
Давайте начнем с основных терминов.
Блокчейн
Блокчейн — это проверяемая и необратимая база данных, в которую можно только добавлять данные. В блокчейн данные могут быть добавлены в виде блоков, в которых каждый блок имеет адрес предыдущего, отсюда и название блокчейн.
Криптовалюта
Криптовалюта — это цифровая валюта, в которой все транзакции используют криптографию для добавления блока в блокчейн в децентрализованной системе. Блокчейн — это совокупность узлов, отвечающих за проверку криптовалюты. Хотя Bitcoin является самой популярной криптовалютой, Ethereum (эфир) также может использоваться для транзакций на основе блокчейна.
Ethereum
Ethereum — это децентрализованная платформа с открытым исходным кодом, построенная на блокчейне и используемая для запуска наших смарт-контрактов. Это не только криптовалюта, но и сложное приложение, которое выполняет смарт-контракты на блокчейне, чтобы избежать попыток мошенничества в транзакциях. Мы используем Ethereum Virtual Machine (EVM) в качестве среды выполнения для запуска смарт-контрактов.
Умные контракты
Умные контракты — это фрагменты программы, скомпилированные и исполняемые EVM и хранящиеся в блокчейне. Они выполняются автоматически при соблюдении заданных условий. Это помогает совершать безопасные транзакции без участия третьей стороны. Положительной стороной транзакций на основе смарт-контрактов является то, что эти транзакции необратимы, но отслеживаемы.
Solidity — наиболее широко используемый язык программирования для создания и написания смарт-контрактов, хотя на рынке доступны и другие языки, такие как Mutan, Serpent и LLL.
Виртуальная машина Ethereum (EVM)
Виртуальная машина Ethereum — это вычислительный механизм, используемый для выполнения смарт-контрактов. Она выступает в качестве программной платформы для создания и развертывания децентрализованных приложений.
Давайте рассмотрим работу EVM.
Смарт-контракт (код Solidity) компилируется компилятором Ethereum и создает байткод EVM. Эти байткоды являются промежуточными кодами, выполняемыми EVM. После выполнения байткода он создает различные блоки. Наконец, развернутые контракты привязываются к соответствующим блокам.
Мы можем найти несколько автономных реализаций EVM, таких как
- Py-EVM — Python
- evmone — C++
- ethereumjs-vm — JavaScript
- eEVM — C++
- Hyperledger Burrow — Go
Solidity
Solidity — это широко используемый высокоуровневый объектно-ориентированный язык для реализации смарт-контрактов. Это язык, основанный на фигурных скобках и похожий на ECMAScript, синтаксис которого почти аналогичен синтаксису C++, JavaScript и Python. Он статически типизирован и поддерживает сложные переменные-члены для контрактов. С помощью Solidity вы можете создавать контракты для таких приложений, как голосование, краудфандинг и кошельки с несколькими подписями.
Настройка среды
Вы можете выполнять смарт-контракт двумя способами
- В автономном режиме
- Онлайн-режим
Автономный режим
Начнем с требований к программному обеспечению.
- Node.js — среда выполнения JavaScript с открытым исходным кодом, используемая для выполнения кода JavaScript вне веб-браузера.
- Truffle — Самая популярная среда разработки для Ethereum.
-
Ganache — Предоставляет локальную сеть, которая показывает различные тестовые / реальные счета блокчейна и транзакции на IDE/консоли. Является частью пакета Truffle.
-
Скачайте и установите node.js.
-
Установите Truffle глобально.
npm install -g truffle
- Скачайте и установите ganache-cli.
Онлайн-режим
Remix Ethereum IDE — это онлайн-платформа, используемая для создания смарт-контрактов с помощью Solidity с нулевым временем настройки. Для локального запуска есть автономная программа установки. Ознакомьтесь с автономной программой установки здесь Remix desktop
Теперь, когда все инструменты установлены, давайте изучим некоторые фундаментальные концепции Solidity.
Основы Solidity
Прагма версии
Директива Pragma определяет версию компилятора для выполнения исходного кода. Все программы Solidity должны начинаться с pragma . Обратите внимание, что это утверждение является локальным для программы solidity, то есть вы должны указать эту строку для всех программ solidity.
pragma solidity >=0.7.0 <0.9.0;
Контракт
Это ключевое слово используется для создания смарт-контракта. По соглашению, имя контракта обычно является именем файла solidity. Все объявления функций и переменных в файле будут инкапсулированы в смарт-контракте.
contract Test{
// Functions and Data
}
Переменные
Переменные — это зарезервированные области памяти для хранения значений. Вы можете хранить информацию о различных типах данных, таких как символ, широкий символ, целое число, плавающая точка, двойная плавающая точка, булевы и т.д.
Типы Solidity
Solidity — статически типизированный язык, поэтому мы должны указывать тип каждой переменной при ее объявлении. Как и в других языках, в Solidity есть типы значений и ссылочные типы.
Типы значений — переменные типа значения хранят свои собственные данные. Это основные типы данных, предоставляемые Solidity. Данные типа значения в Solidity перечислены ниже:
- Boolean: Этот тип данных используется для хранения значений True или False.
- Integer: Этот тип данных используется для хранения целых чисел. Мы можем использовать int и uint для объявления знаковых и беззнаковых целых чисел соответственно.
- Числа с фиксированной точкой: Этот тип данных используется для хранения чисел с плавающей точкой. Мы можем использовать fixed и unfixed для объявления знаковых и беззнаковых чисел с фиксированной точкой соответственно.
- Адрес: Адрес хранит 20-байтовое значение, которое представляет собой размер адреса Ethereum. Адрес можно использовать для получения баланса счета в блокчейне или для перевода баланса с помощью метода getbalance() или settransfer() соответственно.
- Байты и строки: Байты используются для хранения набора символов фиксированного размера, в то время как строка используется для хранения набора символов, равного или большего, чем байт.
- Перечисления: Используются для создания определяемых пользователем типов данных, а также для присвоения имени целочисленной константе, что делает контракт более читаемым и удобным для сопровождения.
// Solidity program to demonstrate value types
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
// Creating a contract
contract Types {
// Initializing Bool variable
bool public boolean = false;
// Initializing Integer variable
int32 public int_var = -12345;
// Initializing String variable
string public str = "Codemaker";
// Initializing Byte variable
bytes1 public b = "v";
// Defining an enumerator
enum week { sunday, monday, tuesday, wednesday, thursday, friday, saturday }
}
Ссылочные типы — переменные ссылочного типа хранят местоположение данных. Они не передают данные напрямую. Ниже перечислены ссылочные типы в Solidity:
- Массивы: Массив — это коллекция одинаковых данных с именем, каждый элемент которой идентифицируется с помощью индекса.
- Структура: Структура — это группа различных типов данных. Она помогает пользователю создать и определить свой собственный тип данных.
- Mapping (отображение): Mapping — это наиболее используемый ссылочный тип, который хранит данные в виде пары ключ-значение, где ключ может быть любым типом значения.
// Solidity program to demonstrate Reference Types
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
// Creating a contract
contract Types {
// Defining an array
uint[5] public array = [uint(1), 2, 3, 4, 5] ;
// Defining a Structure
struct student {
string name;
string subject;
uint8 marks;
}
// Creating a structure object
student public std1;
// Creating a mapping
mapping (address => student) result;
address[] student_result;
}
Функция
Функция — это группа многократно используемых кодов, которые могут быть использованы в любом месте вашего приложения. Мы можем определить функцию с помощью ключевого слова function, уникального имени функции, списка параметров и блока утверждений, окруженного фигурными скобками. Она может быть задана как частная, внутренняя, внешняя или публичная (по умолчанию).
- Private: Функции и переменные состояния видны только для определенного контракта.
- Публичный: Функции и переменные состояния могут быть доступны в любом месте программы.
- Внутренний: Аналогично private, но доступ к функциям и переменным состояния возможен только в рамках контрактов, производных от определенных контрактов.
- Просмотр: Это функции только для чтения, которые гарантируют состояние переменной.Синтаксис
function function-name(parameter-list) scope returns() {
//statements
}
Пример
// Solidity program to demonstrate Functions
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract MathOperations {
function addNumbers() public pure returns(uint){
uint a = 100; // local variable
uint b = 200;
uint result = a + b;
return result;
}
}
Модификаторы
Модификатор позволяет управлять поведением функции. Они могут использоваться в различных сценариях. Например, проверка того, кто имеет доступ к функции, перед выполнением этой функции.
// Solidity program to demonstrate Modifiers
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract ModifierTest {
address testAddress;
constructor() {
testAddress = msg.sender;
}
// Check if the function is called by the owner of the contract
modifier onlyOwner() {
if (msg.sender == testAddress) {
_;
}
}
// Can only be called by the owner - using onlyOwner modifier
function test() public onlyOwner {
}
}
Если при вызове функции выполняется условие модификатора, тело функции вставляется туда, где в определении модификатора стоит специальный символ "_;"
. Затем код выполняется, в противном случае возникает исключение.
Конструкторы
Конструктор — это необязательная функция, которая автоматически выполняется во время создания контракта. Мы можем определить конструктор, используя ключевое слово constructor. Он может быть публичным или внутренним. Контракт создаст конструктор по умолчанию, если конструктор не указан.
contructor() public {}
contract ConstructorTest {
uint regNo;
constructor() public {
regNo = 10;
}
}
События
Событие сохраняет аргументы, переданные в журнале транзакций. Оно полезно для получения текущего состояния контракта при вызове функции. Его можно использовать для уведомления приложения об изменениях, внесенных в контракты.
Синтаксис
event Transfer(address indexed from, address indexed to, uint _value);
Пример
emit Transfer(msg.sender, receiverAddress, msg.value);
Обработка ошибок
Solidity предоставляет различные функции для обработки ошибок. Однако при возникновении ошибки состояние блокчейна возвращается в исходное. Также существует возможность предотвращения несанкционированного доступа к коду. Ниже перечислены некоторые из важных методов, используемых при обработке ошибок.
-
assert(bool condition) — Если условие не выполнено, вызов метода вызывает недопустимый опкод, и все изменения, сделанные в состоянии, будут отменены. Это можно использовать для внутренних ошибок.
-
require(bool condition) — Если условие не выполняется, вызов метода возвращает к исходному состоянию. Это может быть использовано для внешних компонентов.
-
require(bool condition, string memory message) — Метод используется для ошибок во входах или внешних компонентах. В нем есть возможность задать пользовательское сообщение.
-
revert() — Метод прерывает выполнение и возвращает все изменения, внесенные в состояние.
revert(string memory reason) — Имеет опцию для пользовательского сообщения.
// Solidity program to demonstrate Error handling
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract ErrorHandling {
address public seller;
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function sell(uint amount) public payable onlySeller {
if (amount > msg.value / 2 ether)
revert("Not enough Ether provided.");
// Perform the sell operation.
}
}
Первый смарт-контракт
Основы Solidity рассмотрены выше. Давайте попробуем создать и развернуть наш первый смарт-контракт.
Начнем с создания папки проекта. Затем инициализируем проект с помощью Truffle следующей командой.
truffle init
truffle init
создаст необходимые файлы проекта, которые включают Migrations.sol
, 1_initial_migration.js
и truffle-config.js
. Аналогичным образом будут созданы три папки — contracts, migrations и test. Папка contracts содержит смарт-контракты, папка migration содержит коды для развертывания, а папка test содержит коды для тестирования смарт-контрактов.
Начальная структура проекта будет выглядеть следующим образом,
Давайте посмотрим на структуру проекта.
-
Контракты — Здесь вы можете создать все ваши смарт-контракты в формате .sol.
Migrations.sol
— это смарт-контракт, созданный Truffle для хранения истории миграций. Не вносите никаких изменений в файлMigrations.sol
. -
Migrations — содержит файлы, которые помогут вам развернуть ваши смарт-контракты.
Файл1_initial_migartion.js
развертывает контрактMigrations.sol
. Вы также можете создавать файлы миграции для своих контрактов. Truffle запускает миграцию в порядке возрастания префикса, поэтому разработчики должны назначать префиксы в порядке возрастания (например:2_name_file.js
). -
Test — Здесь вы можете создать свои тестовые файлы. Truffle предоставляет фреймворк автоматизированного тестирования для тестирования ваших контрактов с использованием Solidity и Javascript.
-
Build — Папка build будет автоматически создана после компиляции и будет содержать низкоуровневые детали каждого из ваших контрактов, такие как ABI и байткод. Эта информация полезна, когда вы обращаетесь к контракту вне среды truffle. Мы можем найти адрес развернутых контрактов в файлах сборки.
-
Truffle Config — Содержит конфигурации проекта, такие как сеть и компиляторы. Вы можете настроить сеть либо на локальный блокчейн Ganache, либо на mainnet, либо на тестовую сеть, например Ropsten.
1. Напишите контракт
Теперь мы можем создать смарт-контракт HelloWorld.sol
. В этом примере конструктор принимает строковый параметр и присваивает его глобальной переменной name. Имя может быть изменено с помощью функции changeName(string)
, которая действует как сеттер, а getName()
— как геттер.
Создайте файл с именем 1_HelloWorld.sol и поместите его в папку contracts, а затем добавьте в него следующий код.
// Solidity program to demonstrate Hello World
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract HelloWorld {
string public name;
constructor(string memory yourName) public{
name = yourName;
}
function changeName(string memory yourName) public{
name = yourName;
}
function getName() public view returns(string memory){
return name;
}
}
2. Настройка миграции
Создайте новый файл миграции с префиксом больше 1 ( 2_hello_migartion.js
) внутри папки migration для развертывания контракта HelloWorld.sol
.
Вставьте следующий фрагмент кода,
const HelloWorld = artifacts.require("HelloWorld");
module.exports = function (deployer) {
const yourName = "Codemaker";
deployer.deploy(HelloWorld, yourName);
};
Функция artifacts.require()
сообщает трюфелю, с каким контрактом вы хотите взаимодействовать, а функция deployer.deploy()
указывает на параметр, который нам нужно передать конструктору.
3. Компиляция и развертывание
Скомпилируйте ваш проект с помощью следующей команды
truffle compile
Если компиляция прошла успешно, мы можем увидеть папку build внутри папки проекта. Нам нужно использовать Turffle и Ganache для развертывания и тестирования контрактов.
Давайте начнем с Ganache. Откройте Ganache IDE и выберите в окне «QuickStart».
Далее перейдите к файлу truffle-config.js и измените сетевые детали, откомментировав раздел development.
Убедитесь, что порт RPC-сервера из Ganache отображен в значении
networks.port
.
Разверните контракт с помощью следующей команды.
truffle deploy --network development
После успешного развертывания вы получите сведения о контракте, такие как адрес контракта и информация о блоке.
4. Протестируйте контракты
Создайте тестовый файлtest.js с префиксом .js в папке test и добавьте следующий код.
// to interact with the contract
const HelloWorld = artifacts.require("HelloWorld");
contract('HelloWorld', () => {
// initialise the contract instance before running tests
let contractInstance = null;
before(async () => {
contractInstance = await HelloWorld.deployed();
});
// TEST 1
it('initial name should be Codemaker', async () => {
// call contract's function
const currentName = await contractInstance.getName.call();
// check condition
assert.equal(currentName, "Codemaker", "the name is not Codemaker");
});
// TEST 2
it('should change name in Vishnu', async () => {
// change name in contract
await contractInstance.changeName("Vishnu");
// get the current name
const currentName = await contractInstance.getName.call();
// check condition
assert.equal(currentName, "Vishnu", "the name is not Vishnu");
});
});
Давайте разберемся в коде,
Функция before()
выполняется перед выполнением тестов, чтобы мы могли инициализировать экземпляр контракта. Функция call()
используется, когда метод не изменяет переменные состояния контракта. Мы использовали call() в функции getName()
, иначе она вернула бы чек транзакции.
Здесь мы определили два тестовых случая. Первый тест проверяет параметры в конструкторе, получает значение с помощью метода getter и использует assert для проверки равенства. Второй тест пытается изменить имя с помощью changeName()
.
Запустите тест с помощью следующей команды
truffle test
Вот и все! Ваш собственный смарт-контракт, развернутый на блокчейне 🙂
5. Работа с IDE Remix
Remix — это онлайн IDE, используемая для разработки смарт-контрактов на языке Solidity.
Давайте попробуем создать смарт-контракт HelloWorld.sol
в онлайн-режиме Remix Ethereum IDE.
- Откройте Remix IDE в своем браузере.
- Выберите
New File
и выберите средуSolidity
.
- Теперь у вас появится раздел кода. Напишите логику вашего контракта в окне кода и нажмите кнопку Compile, чтобы скомпилировать его.
- Нажмите на кнопку Deploy, чтобы выполнить код.
- Щелкните на вызовах методов под развернутыми контрактами, чтобы запустить программу.
- Щелкните на консоли, чтобы увидеть результат.
- Нажмите на кнопку Debug, чтобы отладить контракт. Он показывает каждый вызов функции и назначения переменных.
Спасибо, что прочитали эту статью.
Если вам понравилась эта статья, пожалуйста, нажмите на кнопку с сердечком ♥ и поделитесь, чтобы помочь другим найти ее!
Полный исходный код этого руководства доступен на сайте https://github.com/codemaker2015/solidity-smart-contract-examples.
Вот несколько полезных ссылок,
- https://docs.soliditylang.org/en/v0.8.11
- https://remix-project.org/
- https://github.com/ethereum/remix-desktop/releases
Первоначально опубликовано на Medium —
Создайте и разверните свой первый смарт-контракт с помощью Solidity