Алексей Боровков
Криптовалюта с нуля: От идеи до запуска вашего блокчейн проекта. Часть 2

Часть 2: Техническая реализация (Практическое руководство)

Введение: Эта часть содержит технические инструкции. Код приведен в образовательных целях.

Глава 5: Создание токена на Ethereum (стандарт ERC-20)

5.1 Настройка среды: Node.js, npm, Truffle/Ganache, MetaMask.

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

1. Установка Node.js и npm

Что это?

· Node.js – среда выполнения JavaScript вне браузера. Блокчейн-разработка heavily relies на JavaScript/TypeScript.

· npm (Node Package Manager) – менеджер пакетов, который поставляется с Node.js. Через него мы будем устанавливать все необходимые библиотеки и инструменты.

Зачем нужно?

Большинство инструментов для разработки в Ethereum (Truffle, Hardhat) являются npm-пакетами и требуют Node.js для работы.

Как установить?

1. Перейдите на официальный сайт Node.js.

2. Скачайте LTS-версию (Long-Term Support – стабильная версия с долгосрочной поддержкой).

3. Запустите установщик и следуйте инструкциям (можно оставлять настройки по умолчанию).

Проверка установки:

Откройте терминал (Command Prompt на Windows, Terminal на Mac/Linux) и выполните команды:

bash

node –version

npm –version

Если вы видите номера версий (например, v18.17.0 и 9.6.7), установка прошла успешно.

2. Установка Truffle Suite

Что это?

Truffle— это самый популярный фреймворк для разработки смарт-контрактов на Ethereum. Он предоставляет:

· Шаблоны проектов

· Инструменты для компиляции

· Систему миграций (деплоя) в разные сети

· Консоль для взаимодействия с контрактами

· Интеграцию с тестовыми сетями

Зачем нужно?

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

Как установить?

В терминале выполните команду:

bash

npm install -g truffle

Флаг -g означает глобальную установку, чтобы использовать truffle в любой папке.

Проверка установки:

bash

truffle version

3. Установка Ganache

Что это?

Ganache— это персональный блокчейн для локальной разработки. Он создает на вашем компьютере собственную Ethereum-подобную сеть с предварительно финансированными счетами.

Зачем нужно?

· Бесплатное тестирование: Не нужно тратить реальные ETH на комиссии.

· Мгновенные транзакции: Блоки создаются мгновенно.

· Предсказуемая среда: Идеально для отладки.

· Приватность: Вы работаете в изолированной среде.

Как установить?

Есть два варианта:

Вариант А: Ganache CLI (командная строка)

bash

npm install -g ganache-cli

Вариант Б: Ganache UI (графический интерфейс)

1. Скачайте с официального сайта.

2. Установите, как обычное приложение.

Рекомендуется начать с Ganache UI, так как он более нагляден для новичков.

Запуск Ganache UI:

1. Запустите приложение.

2. Нажмите "Quickstart Ethereum".

3. Вы увидите список из 10 счетов с балансом по 1000 ETH каждый. Запомните мнемоническую фразу (12 слов) – она понадобится для подключения MetaMask.

4. Установка и настройка MetaMask

Что это?

MetaMask— это криптокошелек в виде браузерного расширения. Это ваш "ключ" к взаимодействию с блокчейном.

Зачем нужно?

· Управление счетами и приватными ключами.

· Взаимодействие с dApps (децентрализованными приложениями).

· Подписание транзакций.

· Подключение к разным сетям (Ethereum Mainnet, тестовые сети, Ganache).

Как установить?

1. Перейдите на официальный сайт MetaMask.

2. Нажмите "Download" и выберите ваш браузер (Chrome, Firefox, Brave и т.д.).

3. Установите расширение.

4. Создайте новый кошелек, следуя инструкциям. Обязательно сохраните Seed-фразу (12 слов) в безопасном месте!

Настройка подключения к Ganache:

1. Откройте MetaMask и создайте/импортируйте кошелек.

2. Нажмите на сеть вверху (по умолчанию "Ethereum Mainnet") и выберите "Add network".

3. Нажмите "Add a network manually".

4. Заполните форму:

· Network Name: Ganache Local

· New RPC URL: http://127.0.0.1:7545 (стандартный порт для Ganache UI)

· Chain ID: 1337

· Currency Symbol: ETH

· Block Explorer: (оставьте пустым)

5. Сохраните настройки.

Импорт счета из Ganache в MetaMask:

1. В Ganache UI вы увидите список счетов. Нажмите на значок ключа справа от первого счета.

2. Скопируйте приватный ключ.

3. В MetaMask нажмите на круглый значок профиля → "Import account".

4. Вставьте приватный ключ и нажмите "Import".

Теперь у вас в MetaMask есть счет с 1000 ETH для тестирования!

Проверка готовности среды

Убедитесь, что все компоненты работают корректно:

1. Запустите Ganache UI – вы должны видеть 10 счетов с балансом.

2. В MetaMask переключитесь на сеть "Ganache Local" – баланс должен отображаться корректно.

3. В терминале проверьте версии:

bash

node –version

npm –version

truffle version

Если все шаги выполнены успешно, ваша среда разработки готова! В следующем разделе мы создадим новый проект Truffle и напишем наш первый смарт-контракт токена.

Важные примечания:

· Весь этот процесс происходит на вашем локальном компьютере и не затрагивает основные сети Ethereum.

· ETH в Ganache – виртуальные и не имеют реальной ценности.

· Никогда не используйте seed-фразу или приватные ключи от основного кошелька в тестовых средах.

5.2 Написание смарт-контракта на Solidity.

Теперь, когда среда настроена, мы переходим к самому важному – созданию смарт-контракта нашего токена. Мы будем использовать язык Solidity и библиотеку OpenZeppelin – золотой стандарт безопасности в разработке смарт-контрактов.

1. Создание проекта и структуры папок

Откройте терминал и выполните:

bash

# Создаем папку для проекта

mkdir my-erc20-token

cd my-erc20-token

# Инициализируем новый проект Truffle

truffle init

# Устанавливаем OpenZeppelin Contracts

npm install @openzeppelin/contracts

После выполнения команд структура папок будет выглядеть так:

my-erc20-token/

├── contracts/

│ └── Migrations.sol

├── migrations/

│ └── 1_initial_migration.js

├── test/

├── node_modules/

├── truffle-config.js

└── package.json

2. Создание контракта токена

В папке contracts/ создайте новый файл BookCoin.sol:

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// Импортируем стандарт ERC-20 из OpenZeppelin

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract BookCoin is ERC20 {

/**

* @dev Конструктор, который вызывается при деплое контракта

* @param initialSupply – начальное предложение токенов

*

* – Наследуем от ERC20 и передаем имя и символ токена

* – Вызываем _mint чтобы создать начальное предложение

* – Умножаем на 10^decimals() чтобы учесть десятичные разряды

*/

constructor(uint256 initialSupply) ERC20("BookCoin", "BOOK") {

_mint(msg.sender, initialSupply * 10 ** decimals());

}

}

3. Детальное объяснение кода

Строка 1: Лицензия

solidity

// SPDX-License-Identifier: MIT

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

Строка 2: Версия компилятора

solidity

pragma solidity ^0.8.0;

Указывает, что код должен компилироваться компилятором версии 0.8.0 или выше, но ниже 0.9.0. Версия 0.8.0 ввела важные улучшения безопасности.

Строка 5: Импорт библиотеки

solidity

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Импортируем готовую, проаудитированную реализацию стандарта ERC-20 из OpenZeppelin. Это избавляет нас от написания сотен строк кода и предотвращает множество уязвимостей.

Строка 7: Объявление контракта

solidity

contract BookCoin is ERC20 {

Создаем наш контракт BookCoin, который наследует все функции от ERC20.

Строки 8-16: Конструктор

solidity

constructor(uint256 initialSupply) ERC20("BookCoin", "BOOK") {

_mint(msg.sender, initialSupply * 10 ** decimals());

}

· constructor – специальная функция, которая выполняется один раз при деплое контракта.

· uint256 initialSupply – параметр, который мы передадим при деплое (например, 1000000 для 1 миллиона токенов).

· ERC20("BookCoin", "BOOK") – вызов конструктора родительского класса с именем и символом токена.

· _mint(msg.sender, initialSupply * 10 ** decimals()) – создание токенов:

· _mint – внутренняя функция ERC-20 для создания новых токенов.

· msg.sender – адрес, который разворачивает контракт (получает все токены).

· initialSupply * 10 ** decimals() – преобразуем целое число в значение с десятичными разрядами. По умолчанию decimals() возвращает 18, так что 1000 токенов станут 1000 × 10¹⁸ = 1000000000000000000000.

4. Что мы получаем "из коробки"?

Наследуя от OpenZeppelin ERC-20, наш токен автоматически получает:

· Базовый функционал ERC-20:

· totalSupply() – общее предложение токенов

· balanceOf(account) – баланс конкретного адреса

· transfer(recipient, amount) – перевод токенов на другой адрес

· allowance(owner, spender) – проверка разрешенной суммы

· approve(spender, amount) – разрешение другому адресу тратить ваши токены

· transferFrom(sender, recipient, amount) – перевод токенов от имени владельца

· События (Events):

· Transfer(from, to, value) – при переводе токенов

· Approval(owner, spender, value) – при выдаче разрешения

· Безопасность:

· Проверка на переполнение (overflow/underflow)

· Валидация адресов

· Защита от front-running атак

5. Компиляция контракта

Убедитесь, что Ganache запущен, затем в терминале выполните:

bash

truffle compile

При успешной компиляции вы увидите:

Compiling your contracts…

===========================

> Compiling ./contracts/BookCoin.sol

> Compiling ./contracts/Migrations.sol

> Compiling @openzeppelin/contracts/token/ERC20/ERC20.sol

# … другие файлы OpenZeppelin

> Artifacts written to /Users/…/build/contracts

> Compiled successfully using:

– solc: 0.8.19+commit.7dd6d404.Emscripten.clang

6. Расширенная версия с дополнительными функциями.

Если вы хотите добавить больше функциональности, вот улучшенная версия:

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "@openzeppelin/contracts/access/Ownable.sol";

contract BookCoin is ERC20, Ownable {

uint8 private _decimals;

constructor(

uint256 initialSupply,

string memory name,

string memory symbol,

uint8 decimalUnits

) ERC20(name, symbol) {

_decimals = decimalUnits;

_mint(msg.sender, initialSupply * 10 ** decimalUnits);

_transferOwnership(msg.sender);

}

function decimals() public view virtual override returns (uint8) {

return _decimals;

}

function mint(address to, uint256 amount) public onlyOwner {

_mint(to, amount);

}

function burn(uint256 amount) public {

_burn(msg.sender, amount);

}

}

Что добавилось:

· Ownable – добавляет модификатор onlyOwner для функций, которые могут вызываться только владельцем контракта.

· Настраиваемые decimals – возможность установить другое количество десятичных знаков (например, 6 как в USDC).

· Функция mint – создание дополнительных токенов (только владельцем).

· Функция burn – сжигание токенов.

Проверка безопасности

Никогда не делайте так:

solidity

// ОПАСНО! Не используйте устаревшие версии

pragma solidity ^0.4.0;

// ОПАСНО! Не пишите ERC-20 с нуля

contract MyToken {

mapping(address => uint256) balances;

// … сотни строк ненадежного кода

}

Всегда делайте так:

· Используйте Solidity ≥ 0.8.0

· Наследуйтесь от OpenZeppelin

· Проводите аудит перед запуском в mainnet

Вывод: Мы создали безопасный, полностью функциональный токен ERC-20 всего в 10 строках кода, благодаря использованию OpenZeppelin. В следующем разделе мы развернем этот контракт в нашей тестовой сети и начнем с ним взаимодействовать.

5.3 Пример простейшего контракта ERC-20.

Здесь я покажу минимальную, но полнофункциональную реализацию токена ERC-20. Этот пример идеально подходит для понимания основ и быстрого старта.

Минимальная версия (8-строк кода)

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract SimpleToken is ERC20 {

constructor(uint256 initialSupply) ERC20("Simple Token", "SIM") {

_mint(msg.sender, initialSupply * 10 ** decimals());

}

}

Что делает этот код:

1. Устанавливает лицензию и версию компилятора

2. Импортирует стандарт ERC-20 из OpenZeppelin

3. Создает контракт с именем "Simple Token" и символом "SIM"

4. При деплое создает указанное количество токенов и отправляет их создателю контракта

Более практичная версия с комментариями

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**

* @title BookCoin

* @dev Простой пример токена ERC-20 для книги

*/

contract BookCoin is ERC20 {

/**

* @dev Конструктор создает все токены и отправляет создателю

* @param totalSupply Общее количество токенов (в целых единицах)

*

* Пример: если передать 1000000, будет создано 1 000 000 * 10^18 токенов

* Это стандартная практика – использовать 18 десятичных знаков

*/

constructor(uint256 totalSupply) ERC20("BookCoin", "BOOK") {

_mint(msg.sender, totalSupply * 10 ** decimals());

}

}

Как использовать этот контракт

После деплоя вы можете взаимодействовать с токеном через следующие функции:

Базовые операции:

javascript

// Проверить общее предложение

const totalSupply = await token.totalSupply();

// Проверить баланс аккаунта

const balance = await token.balanceOf("0x123…");

// Перевести токены

await token.transfer("0x456…", 1000000000000000000); // 1.0 токен

Пример в тестовой сети:

javascript

// Предположим, мы деплоили с initialSupply = 1000000

// Создатель получит: 1,000,000 * 10^18 = 1,000,000,000,000,000,000,000,000 токенов

// Перевод 1 токена (с учетом decimals)

await token.transfer("0x742d35Cc6634C0532925a3b8D…", "1000000000000000000");

Полная версия с дополнительными возможностями

Для реального проекта рекомендуется использовать расширенную версию:

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "@openzeppelin/contracts/access/Ownable.sol";

contract AdvancedToken is ERC20, Ownable {

uint8 private _customDecimals;

constructor(

uint256 initialSupply,

string memory name,

string memory symbol,

uint8 decimalUnits

) ERC20(name, symbol) {

_customDecimals = decimalUnits;

_mint(msg.sender, initialSupply * 10 ** decimalUnits);

_transferOwnership(msg.sender);

}

// Переопределяем decimals для кастомного значения

function decimals() public view virtual override returns (uint8) {

return _customDecimals;

}

// Функция для создания дополнительных токенов (только владельцем)

function mint(address to, uint256 amount) public onlyOwner {

_mint(to, amount);

}

// Функция для сжигания токенов

function burn(uint256 amount) public {

_burn(msg.sender, amount);

}

// Функция для сжигания токенов с другого адреса (с разрешения)

function burnFrom(address account, uint256 amount) public {

_spendAllowance(account, msg.sender, amount);

_burn(account, amount);

}

}

Особенности расширенной версии:

· Кастомное количество decimals (можно установить 6, как в USDC)

· Контроль владельца через модификатор onlyOwner

· Функция mint для дополнительной эмиссии

· Функции burn для сжигания токенов

· Безопасное управление разрешениями

Пример деплоя с разными параметрами

javascript

// Деплой простого токена (18 decimals)

const SimpleToken = await ethers.getContractFactory("SimpleToken");

const simpleToken = await SimpleToken.deploy("1000000"); // 1 млн токенов

// Деплой продвинутого токена (6 decimals)

const AdvancedToken = await ethers.getContractFactory("AdvancedToken");

const advancedToken = await AdvancedToken.deploy(

"1000000", // 1 млн токенов

"USD Coin", // имя

"USDC", // символ

6 // 6 decimal places

);

Важные замечания для новичков

1. Всегда используйте OpenZeppelin – не пишите стандартные функции самостоятельно

2. Тестируйте в testnet перед запуском в mainnet

3. Проводите аудит для любого контракта с реальными средствами

4. Используйте последние версии Solidity (≥ 0.8.0)

5. Никогда не делитесь приватными ключами или мнемонической фразой

Что дальше?

Этот простой контракт уже полностью функционален и готов к использованию. В следующих разделах мы:

1. Скомпилируем и проверим контракт

2. Развернем в тестовой сети

3. Протестируем основные функции

4. Верифицируем код в блок-эксплорере

Поздравляю! Вы только что создали свой первый ERC-20 токен. Несмотря на простоту, этот код лежит в основе тысяч реальных криптопроектов.

5.4 Компиляция, деплой в тестовую сеть (Goerli/Sepolia)

Теперь, когда у нас есть готовый смарт-контракт, пришло время оживить его, развернув в реальной тестовой сети Ethereum. Это критически важный шаг перед запуском в основной сети.

1. Подготовка к работе с тестовыми сетями

Важное обновление: Сеть Rinkeby устарела. Вместо нее используйте:

· Goerli (пока еще работает, но планируется отключение)

· Sepolia (рекомендуемая новая тестовая сеть)

Что понадобится:

1. Тестовые ETH для оплаты комиссий

2. RPC Endpoint для подключения к сети

3. Настроенный MetaMask

2. Получение тестовых ETH

Для Sepolia:

1. Перейдите на sepoliafaucet.com (требуется аккаунт Alchemy)

2. Или используйте poinfrastructure.com/faucet

Для Goerli:

1. Перейдите на goerlifaucet.com (требуется аккаунт Alchemy)

2. Или используйте chainlink faucet

Шаги:

1. Скопируйте ваш адрес из MetaMask

2. Вставьте на сайте крана

3. Получите 0.1-0.5 test ETH

3. Настройка Truffle для тестовых сетей

Обновите truffle-config.js:

javascript

const HDWalletProvider = require('@truffle/hdwallet-provider');

require('dotenv').config();

module.exports = {

networks: {

// Локальная разработка

development: {

host: "127.0.0.1",

port: 7545,

network_id: "*"

},

// Sepolia testnet

sepolia: {

provider: () => new HDWalletProvider({

privateKeys: [process.env.PRIVATE_KEY],

providerOrUrl: `https://sepolia.infura.io/v3/${process.env.INFURA_PROJECT_ID}`

}),

network_id: 11155111,

gas: 5500000,

confirmations: 2,

timeoutBlocks: 200,

skipDryRun: true

},

// Goerli testnet

goerli: {

provider: () => new HDWalletProvider({

privateKeys: [process.env.PRIVATE_KEY],

providerOrUrl: `https://goerli.infura.io/v3/${process.env.INFURA_PROJECT_ID}`

}),

network_id: 5,

gas: 5500000,

confirmations: 2,

timeoutBlocks: 200,

skipDryRun: true

}

},

compilers: {

solc: {

version: "0.8.19",

settings: {

optimizer: {

enabled: true,

runs: 200

}

}

}

}

};

4. Настройка переменных окружения

Создайте файл .env в корне проекта:

env

MNEMONIC="ваша мнемоническая фраза из 12 слов"

PRIVATE_KEY="ваш приватный ключ"

INFURA_PROJECT_ID=ваш_infura_project_id

Как получить Infura Project ID:

1. Зарегистрируйтесь на infura.io

2. Создайте новый проект

3. Скопируйте Project ID

Внимание! Никогда не коммитьте .env файл в Git!

5. Установка зависимостей

bash

npm install @truffle/hdwallet-provider dotenv

6. Создание миграционного файла

В папке migrations/ создайте файл 2_deploy_tokens.js:

javascript

const BookCoin = artifacts.require("BookCoin");

module.exports = async function (deployer) {

const initialSupply = web3.utils.toWei("1000000", "ether"); // 1,000,000 токенов

await deployer.deploy(BookCoin, initialSupply);

const bookCoin = await BookCoin.deployed();

console.log("BookCoin адрес:", bookCoin.address);

console.log("Общее предложение:", await bookCoin.totalSupply());

};

7. Компиляция контракта

bash

truffle compile

Ожидаемый результат:

Compiling your contracts…

===========================

> Compiling ./contracts/BookCoin.sol

> Compiling @openzeppelin/contracts/token/ERC20/ERC20.sol

> Artifacts written to /path/to/build/contracts

> Compiled successfully using:

– solc: 0.8.19

8. Деплой в тестовую сеть

В Sepolia:

bash

truffle migrate –network sepolia

В Goerli:

bash

truffle migrate –network goerli

Ожидаемый результат:

Starting migrations…

======================

> Network name: 'sepolia'

> Network id: 11155111

> Block gas limit: 30000000 (0x1c9c380)

1_initial_migration.js

======================

Deploying 'Migrations'

––

> transaction hash: 0x1234…5678

> Blocks: 1 Seconds: 12

> contract address: 0xABCD…1234

> block number: 4000000

> block timestamp: 1681234567

> account: 0xYourAddress

> balance: 0.45

> gas used: 250000

> gas price: 20 gwei

> value sent: 0 ETH

> total cost: 0.005 ETH

2_deploy_tokens.js

==================

Deploying 'BookCoin'

––

> transaction hash: 0x5678…9012

> Blocks: 1 Seconds: 15

> contract address: 0xEFGH…5678

> block number: 4000001

> block timestamp: 1681234582

> account: 0xYourAddress

> balance: 0.42

> gas used: 1500000

> gas price: 20 gwei

> value sent: 0 ETH

> total cost: 0.03 ETH

> BookCoin адрес: 0xEFGH…5678

> Общее предложение: BigNumber { value: "1000000000000000000000000" }

Summary

=======

> Total deployments: 2

> Final cost: 0.035 ETH

9. Проверка в блок-эксплорере

Скопируйте адрес контракта из логов и откройте в соответствующем блок-эксплорере:

Для Sepolia:

https://sepolia.etherscan.io/address/ВАШ_АДРЕС_КОНТРАКТА

Для Goerli:

https://goerli.etherscan.io/address/ВАШ_АДРЕС_КОНТРАКТА

Вы должны увидеть:

· Подтвержденную транзакцию создания

· Контракт с кодом (пока не верифицированным)

· Баланс токенов у вашего адреса

10. Взаимодействие с контрактом через консоль

bash

truffle console –network sepolia

В консоли выполните:

javascript

// Получить экземпляр контракта

const bookCoin = await BookCoin.deployed()

// Проверить общее предложение

const totalSupply = await bookCoin.totalSupply()

console.log("Total Supply:", totalSupply.toString())

// Проверить ваш баланс

const accounts = await web3.eth.getAccounts()

const myBalance = await bookCoin.balanceOf(accounts[0])

console.log("My Balance:", web3.utils.fromWei(myBalance, 'ether'))

// Перевести токены (1 BOOK)

await bookCoin.transfer("0xReceiverAddress", web3.utils.toWei("1", "ether"))

11. Добавление токена в MetaMask

1. Откройте MetaMask

2. Нажмите "Import tokens"

3. Вставьте адрес контракта

4. Символ и decimals подтянутся автоматически

5. Нажмите "Add"

Теперь вы видите свои BOOK токены в кошельке!

Возможные ошибки и решения:

Ошибка: insufficient funds

· Решение: Получите больше test ETH из крана

Ошибка: gas required exceeds allowance

· Решение: Увеличьте значение gas в truffle-config.js

Ошибка: nonce too low

· Решение: Сбросьте nonce в настройках аккаунта MetaMask

Транзакция висит в pending

· Решение: Увеличьте gas price или отмените транзакцию

Проверка успешного деплоя

Контракт появился в блок-эксплорере

Баланс токенов отображается в MetaMask

Можно выполнять transfer транзакции

Комиссии списываются в test ETH

Поздравляю! Вы успешно развернули свой ERC-20 токен в тестовой сети Ethereum. В следующем разделе мы верифицируем исходный код, чтобы любой мог проверить логику вашего контракта.

5.5 Верификация контракта на Etherscan.

Верификация контракта – это процесс публикации исходного кода вашего смарт-контракта в блок-эксплорере (Etherscan). Это критически важный шаг для построения доверия к вашему проекту.

Зачем верифицировать контракт?

1. Прозрачность: Пользователи могут убедиться, что код соответствует заявленной функциональности

2. Доверие: Верифицированные контракты вызывают больше доверия у инвесторов

3. Взаимодействие: Позволяет напрямую вызывать функции контракта через Etherscan

4. Отслеживание: Пользователи могут отслеживать транзакции и балансы

Без верификации:

Contract Source Code Not Verified

Click to Verify and Publish

После верификации:

Contract Source Code Verified

Read Contract | Write Contract

Способ 1: Автоматическая верификация с помощью Truffle Plugin

Шаг 1: Установка плагина

bash

npm install -D truffle-plugin-verify

Шаг 2: Настройка truffle-config.js

Добавьте в truffle-config.js:

javascript

module.exports = {

// … остальная конфигурация

plugins: ['truffle-plugin-verify'],

api_keys: {

etherscan: process.env.ETHERSCAN_API_KEY

}

};

Шаг 3: Получение API-ключа Etherscan

1. Зарегистрируйтесь на etherscan.io

2. Перейдите в API Keys

3. Создайте новый API Key

4. Добавьте в .env файл:

env

ETHERSCAN_API_KEY=YourApiKeyToken

Шаг 4: Верификация контракта

bash

truffle run verify BookCoin –network sepolia

Ожидаемый результат:

Verifying BookCoin

Pass – Verified: https://sepolia.etherscan.io/address/0x1234…5678#code

Successfully verified 1 contract(s).

Способ 2: Ручная верификация через веб-интерфейс

Шаг 1: Найдите ваш контракт в Etherscan

Перейдите по адресу:

https://sepolia.etherscan.io/address/ВАШ_АДРЕС_КОНТРАКТА

Нажмите "Verify and Publish"

Шаг 2: Заполните форму верификации

Contract Address: 0xYourContractAddress

Compiler Type: Solidity (Single file)

Compiler Version: v0.8.19+commit.7dd6d404

Open Source License Type: MIT License

Шаг 3: Вставьте код контракта

Скопируйте содержимое вашего BookCoin.sol:

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract BookCoin is ERC20 {

constructor(uint256 initialSupply) ERC20("BookCoin", "BOOK") {

_mint(msg.sender, initialSupply * 10 ** decimals());

}

}

Шаг 4: Настройка конструктора

В разделе "Constructor Arguments" введите ABI-encoded параметры:

00000000000000000000000000000000000000000000000000000000000f4240

Это hex-представление 1000000 (1 миллион токенов).

Способ 3: Верификация с помощью Hardhat

Если вы используете Hardhat вместо Truffle:

Установка плагина:

bash

npm install –save-dev @nomiclabs/hardhat-etherscan

Добавьте в hardhat.config.js:

javascript

require("@nomiclabs/hardhat-etherscan");

module.exports = {

etherscan: {

apiKey: process.env.ETHERSCAN_API_KEY

}

};

Верификация:

bash

npx hardhat verify –network sepolia DEPLOYED_CONTRACT_ADDRESS "1000000"

Решение распространенных проблем:

Проблема 1: "Already Verified"

Contract source code already verified

Решение: Контракт уже верифицирован – это успех!

Проблема 2: "Bytecode doesn't match"

Sorry! The compiled result does not match the deployed bytecode

Решение:

· Убедитесь, что версия компилятора совпадает

· Проверьте настройки оптимизатора

· Убедитесь, что вы верифицируете правильный контракт

Проблема 3: "Unable to detect constructor arguments"

Failed to detect constructor arguments

Решение: Вручную укажите ABI-encoded параметры конструктора

Как получить ABI-encoded параметры конструктора

Способ 1: Использование Truffle

javascript

// В консоли Truffle

const contract = await BookCoin.deployed();

const transaction = await web3.eth.getTransaction(contract.transactionHash);

console.log(transaction.input);

Способ 2: Онлайн-энкодер

Используйтеabi.hashex.org для кодирования параметров.

Способ 3: Использование ethers.js

javascript

const { ethers } = require("ethers");

const coder = new ethers.utils.AbiCoder();

const encoded = coder.encode(["uint256"], [1000000]);

console.log(encoded);

Что вы получите после верификации

Read Contract Tab – просмотр состояния контракта

· totalSupply()

· balanceOf()

· allowance()

Write Contract Tab – взаимодействие с контрактом

· transfer()

· approve()

· transferFrom()

Источник транзакций – отслеживание всех операций

Аналитика – графики и статистика

Комментарии – обратная связь от сообщества

Пример успешной верификации

После успешной верификации ваш контракт будет выглядеть так:

Contract Source Code Verified (Exact Match)

Contract Name: BookCoin

Compiler Version: v0.8.19+commit.7dd6d404

Optimization Enabled: Yes with 200 runs

Other Settings: default evmVersion, MIT license

Read Contract | Write Contract

+ [X] Contract created with 0x123… at block 4000001

+ [X] Verified 2 days ago

+ [X] 15 transactions

Дополнительные возможности

Верификация через flattening:

bash

npx truffle-flattener contracts/BookCoin.sol > flattened.sol

Затем загрузите flattened.sol в Etherscan.

Верификация прокси-контрактов:

Для контрактов, использующих паттерн прокси, требуется дополнительная настройка.

Верификация библиотек:

Если ваш контракт использует внешние библиотеки, их нужно верифицировать отдельно.

Проверка результатов

1. Перейдите на страницу контракта в Etherscan

2. Убедитесь, что появились вкладки "Read Contract" и "Write Contract"

3. Проверьте, что код отображается корректно

4. Протестируйте функции через веб-интерфейс

javascript

// Пример чтения через Etherscan

totalSupply() → 1000000000000000000000000

balanceOf(0xYourAddress) → 1000000000000000000000000

name() → "BookCoin"

symbol() → "BOOK"

decimals() → 18

Поздравляю! Ваш контракт теперь полностью прозрачен и доступен для проверки всем желающим. Это важный шаг на пути к созданию доверия к вашему проекту в криптосообществе.

В следующем разделе мы создадим практическое упражнение по развертыванию и верификации вашего собственного токена.

5.6 Практикум: Шаг за шагом создаем токен "BookCoin".

Это пошаговое руководство, которое проведет вас через весь процесс создания, тестирования и развертывания вашего первого ERC-20 токена.

Предварительные требования

Установленное ПО:

· Node.js (v16 или выше)

· npm

· Git

· MetaMask (браузерное расширение)

Аккаунты:

· Infura (бесплатный аккаунт)

· Etherscan (бесплатная регистрация)

· Alchemy (для получения тестовых ETH)

Шаг 1: Инициализация проекта

bash

# Создаем папку проекта

mkdir bookcoin-token

cd bookcoin-token

# Инициализируем npm проект

npm init -y

# Устанавливаем Truffle глобально

npm install -g truffle

# Инициализируем Truffle проект

truffle init

# Устанавливаем необходимые зависимости

npm install @openzeppelin/contracts @truffle/hdwallet-provider dotenv

Проверка структуры проекта:

bookcoin-token/

├── contracts/

│ └── Migrations.sol

├── migrations/

│ └── 1_initial_migration.js

├── test/

├── node_modules/

├── truffle-config.js

└── package.json

Шаг 2: Создание контракта BookCoin

В папке contracts/ создайте файл BookCoin.sol:

solidity

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "@openzeppelin/contracts/access/Ownable.sol";

/**

* @title BookCoin

* @dev ERC-20 токен для книги о создании криптовалют

*/

contract BookCoin is ERC20, Ownable {

/**

* @dev Конструктор создает все токены и отправляет создателю

* @param initialSupply Начальное предложение токенов (в целых единицах)

*/

constructor(uint256 initialSupply) ERC20("BookCoin", "BOOK") {

_mint(msg.sender, initialSupply * 10 ** decimals());

_transferOwnership(msg.sender);

}

/**

* @dev Функция для создания дополнительных токенов (только владельцем)

* @param to Адрес получателя

* @param amount Количество токенов для создания

*/

function mint(address to, uint256 amount) public onlyOwner {

_mint(to, amount);

}

/**

* @dev Функция для сжигания токенов

* @param amount Количество токенов для сжигания

*/

function burn(uint256 amount) public {

_burn(msg.sender, amount);

}

}

Шаг 3: Настройка конфигурации

Замените содержимое truffle-config.js:

javascript

const HDWalletProvider = require('@truffle/hdwallet-provider');

require('dotenv').config();

module.exports = {

networks: {

// Локальная разработка с Ganache

development: {

host: "127.0.0.1",

port: 7545,

network_id: "*"

},

// Sepolia testnet (рекомендуемая)

sepolia: {

provider: () => new HDWalletProvider({

privateKeys: [process.env.PRIVATE_KEY],

providerOrUrl: `https://sepolia.infura.io/v3/${process.env.INFURA_PROJECT_ID}`

}),

network_id: 11155111,

gas: 5500000,

gasPrice: 20000000000,

confirmations: 2,

timeoutBlocks: 200,

skipDryRun: true

}

},

compilers: {

solc: {

version: "0.8.19",

settings: {

optimizer: {

enabled: true,

runs: 200

}

}

}

},

// Для верификации на Etherscan

plugins: ['truffle-plugin-verify'],

api_keys: {

etherscan: process.env.ETHERSCAN_API_KEY

}

};

Шаг 4: Настройка переменных окружения

Создайте файл .env в корне проекта:

env

# Ваш приватный ключ из MetaMask (НИКОМУ НЕ ПОКАЗЫВАЙТЕ!)

PRIVATE_KEY=ваш_приватный_ключ_без_0x

# Infura Project ID

INFURA_PROJECT_ID=ваш_infura_project_id

# Etherscan API Key

ETHERSCAN_API_KEY=ваш_etherscan_api_key

Как получить приватный ключ:

1. Откройте MetaMask

2. Выберите аккаунт → "Account details" → "Export Private Key"

Внимание! Добавьте .env в .gitignore!

Шаг 5: Создание миграционного файла

В папке migrations/ создайте 2_deploy_bookcoin.js:

javascript

const BookCoin = artifacts.require("BookCoin");

module.exports = async function (deployer) {

// 1,000,000 токенов с 18 десятичными знаками

const initialSupply = "1000000";

console.log("Деплой BookCoin с начальным предложением:", initialSupply);

await deployer.deploy(BookCoin, initialSupply);

const bookCoin = await BookCoin.deployed();

console.log(" BookCoin успешно развернут!");

console.log(" Адрес контракта:", bookCoin.address);

console.log(" Владелец:", await bookCoin.owner());

console.log(" Общее предложение:", (await bookCoin.totalSupply()).toString());

console.log(" Символ:", await bookCoin.symbol());

console.log(" Название:", await bookCoin.name());

};

Шаг 6: Компиляция контракта

bash

truffle compile

Ожидаемый результат:

Compiling your contracts…

===========================

> Compiling ./contracts/BookCoin.sol

> Compiling ./contracts/Migrations.sol

> Compiling @openzeppelin/contracts/access/Ownable.sol

> Compiling @openzeppelin/contracts/token/ERC20/ERC20.sol

> Artifacts written to /path/to/build/contracts

> Compiled successfully using:

– solc: 0.8.19

Шаг 7: Получение тестовых ETH

1. Перейдите на sepoliafaucet.com

2. Войдите через аккаунт Alchemy (бесплатная регистрация)

3. Вставьте ваш адрес MetaMask

4. Получите 0.5 Sepolia ETH

Альтернативные краны:

· poinfrastructure.com/faucet

· faucet.quicknode.com/ethereum/sepolia

Шаг 8: Деплой в сеть Sepolia

bash

truffle migrate –network sepolia

Ожидаемый вывод:

Starting migrations…

> Network name: 'sepolia'

> Network id: 11155111

1_initial_migration.js

======================

Deploying 'Migrations'

Transactions: 0x1234…5678

2_deploy_bookcoin.js

====================

Deploying 'BookCoin'

Transactions: 0x5678…9012

BookCoin успешно развернут!

Адрес контракта: 0xAbC…123

Владелец: 0xYourAddress

Общее предложение: 1000000000000000000000000

Символ: BOOK

Название: BookCoin

Summary

=======

> Total deployments: 2

> Final cost: 0.035 ETH

Шаг 9: Проверка в блок-эксплорере

Откройте в браузере (замените YOUR_CONTRACT_ADDRESS):

https://sepolia.etherscan.io/address/YOUR_CONTRACT_ADDRESS

Вы должны увидеть:

· Подтвержденную транзакцию

· Контракт с состоянием "Contract Source Code Not Verified"

Шаг 10: Верификация контракта

Установите плагин для верификации:

bash

npm install -D truffle-plugin-verify

Выполните верификацию:

bash

truffle run verify BookCoin –network sepolia

Ожидаемый результат:

Verifying BookCoin

Pass – Verified: https://sepolia.etherscan.io/address/0xYOUR_CONTRACT#code

Successfully verified 1 contract(s).

Шаг 11: Взаимодействие с контрактом

Через Truffle Console:

bash

truffle console –network sepolia

javascript

// Получить экземпляр контракта

const bookCoin = await BookCoin.deployed()

// Проверить общее предложение

const totalSupply = await bookCoin.totalSupply()

console.log("Total Supply:", totalSupply.toString())

// Проверить баланс владельца

const accounts = await web3.eth.getAccounts()

const ownerBalance = await bookCoin.balanceOf(accounts[0])

console.log("Owner Balance:", web3.utils.fromWei(ownerBalance, 'ether'))

// Перевести 10 BOOK другому адресу

const recipient = "0x742d35Cc6634C0532925a3b8Dc9F1a…"

await bookCoin.transfer(recipient, web3.utils.toWei("10", "ether"))

// Проверить баланс получателя

const recipientBalance = await bookCoin.balanceOf(recipient)

console.log("Recipient Balance:", web3.utils.fromWei(recipientBalance, 'ether'))

Шаг 12: Добавление токена в MetaMask

1. Откройте MetaMask

2. Нажмите "Import tokens"

3. Введите адрес контракта (остальное подтянется автоматически)

4. Нажмите "Add Custom Token"

Теперь вы видите свои BOOK токены!

Шаг 13: Тестирование основных функций

Через Etherscan:

1. Перейдите на страницу вашего контракта

2. Откройте вкладку "Write Contract"

3. Подключите MetaMask

4. Протестируйте функции:

· transfer – перевод токенов

· approve – разрешение на расходование

· burn – сжигание токенов

Шаг 14: Создание простого теста

В папке test/ создайте bookcoin.test.js:

javascript

const BookCoin = artifacts.require("BookCoin");

contract("BookCoin", (accounts) => {

const [owner, user1, user2] = accounts;

const initialSupply = web3.utils.toWei("1000000", "ether");

it("должен развернуть контракт с правильным начальным предложением", async () => {

const instance = await BookCoin.deployed();

const totalSupply = await instance.totalSupply();

assert.equal(totalSupply.toString(), initialSupply, "Неправильное начальное предложение");

});

it("должен отправлять все токены владельцу", async () => {

const instance = await BookCoin.deployed();

const ownerBalance = await instance.balanceOf(owner);

assert.equal(ownerBalance.toString(), initialSupply, "Владелец должен получить все токены");

});

it("должен позволять перевод токенов", async () => {

const instance = await BookCoin.deployed();

const transferAmount = web3.utils.toWei("100", "ether");

await instance.transfer(user1, transferAmount, { from: owner });

const user1Balance = await instance.balanceOf(user1);

assert.equal(user1Balance.toString(), transferAmount, "Получатель должен получить токены");

});

});

Запуск тестов:

bash

truffle test

Итоги практикума

Вы создали:

· Полнофункциональный ERC-20 токен

· Безопасный контракт с использованием OpenZeppelin

· Настроенную среду разработки

Вы развернули:

· В тестовой сети Sepolia

· С верификацией исходного кода

· С возможностью взаимодействия через Etherscan

Вы получили:

· Практический опыт работы с Truffle

· Навыки работы с тестовыми сетями

· Понимание процесса деплоя смарт-контрактов

Дополнительные задания

1. Добавьте кастомные функции в контракт:

· Функцию паузы

· Механизм сжигания комиссий

· Whitelist для определенных операций

2. Создайте простой dApp для взаимодействия с токеном:

· Веб-интерфейс для перевода токенов

· Отображение балансов

· История транзакций

3. Настройте CI/CD для автоматического деплоя:

· Используйте GitHub Actions

· Автоматизируйте тестирование и деплой

Поздравляю! Вы успешно создали и развернули свой первый ERC-20 токен. Этот фундаментальный навык открывает дорогу к созданию более сложных DeFi-проектов и dApp.

Глава 6: Создание токена на Binance Smart Chain (BEP-20)

6.1 Почему BSC? Низкие комиссии.

Binance Smart Chain (BSC) стал популярной альтернативой Ethereum, особенно для проектов, где стоимость транзакций играет ключевую роль. Давайте разберемся, почему низкие комиссии так важны и как BSC их обеспечивает.

Проблема: "Комиссионный кризис" Ethereum

Реальные цифры комиссий в Ethereum (2021-2023):

· Простой перевод ETH: $5-20

· Взаимодействие с DeFi-протоколом: $50-200

· Минтинг NFT: $100-500

· Сложные операции: до $1000+

Последствия для проектов:

· Пользователи отказываются от использования dApp из-за высоких комиссий

· Невозможность микроплатежей и игровых механик

· Ограниченная доступность для пользователей из развивающихся стран

Решение: Binance Smart Chain и его экономика комиссий

Сравнительная таблица комиссий:

Операция

Ethereum Mainnet

BSC Mainnet

Простой перевод

$5-20

$0.05-0.15

Swap на DEX

$30-100

$0.20-0.50

Деплой контракта

$100-500

$5-15

Ежедневное использование

Экономически нецелесообразно

Доступно обычным пользователям

Реальные примеры стоимости (в BNB):

· Перевод токена: 0.000075 BNB (~$0.02)

· Свап на PancakeSwap: 0.000225 BNB (~$0.06)

· Стейкинг: 0.0003 BNB (~$0.08)

Технические причины низких комиссий BSC

1. Алгоритм консенсуса: Proof of Staked Authority (PoSA)

Ethereum (PoW → PoS):

· Децентрализованная валидация

· Высокие вычислительные затраты

· Ограниченная пропускная способность

BSC (PoSA):

· 21 активный валидатор

· Быстрое время блока (3 секунды vs 12 секунд в Ethereum)

· Оптимизированная для производительности архитектура

2. Экономическая модель газа

Ethereum:

· Динамическая цена газа

· Аукционная система

· Частые перегрузки сети

BSC:

· Стабильная цена газа

· Предсказуемые комиссии

· Постоянно высокая пропускная способность

3. Архитектура двойной цепи

BSC работает параллельно с Binance Chain:

· Binance Chain: Быстрые торговые операции

· Binance Smart Chain: Смарт-контракты и dApps

· Синхронизация между цепями

Практические преимущества для разработчиков

1. Быстрая итерация и тестирование

javascript

// Стоимость деплоя контракта

const deploymentCost = {

ethereum: "0.05 – 0.2 ETH", // $75 – $300

bsc: "0.01 – 0.05 BNB" // $3 – $15

};

2. Пользовательский опыт

Для конечных пользователей:

· Возможность пробовать dApp без значительных затрат

· Микроплатежи и игровые механики

· Частые взаимодействия с контрактами

3. Экономическая эффективность

Бюджет проекта на комиссии:

· Ethereum: Тысячи долларов в месяц

· BSC: Сотни долларов в месяц

Сравнение экосистем

Параметр

Ethereum

BSC

Ежедневные транзакции

1-1.5 млн

3-5 млн

Средняя комиссия

$5-20

$0.05-0.20

Время блока

12 сек

3 сек

TVL в DeFi

$25-50 млрд

$3-6 млрд

Активные dApps

3000+

1000+

Когда выбирать BSC для вашего токена?

Идеальные сценарии для BSC:

1. GameFi и Play-to-Earn проекты

solidity

// Частые внутриигровые транзакции

function buyItem(uint256 itemId) public {

// Стоимость: $0.05 вместо $5.00

items[msg.sender][itemId] = true;

}

2. Микроплатежи и социальные dApps

solidity

// Ежедневные награды пользователям

function claimDailyReward() public {

// Экономически целесообразно даже для наград в $0.10

_mint(msg.sender, dailyReward);

}

3. MVP и тестовые запуски

solidity

// Быстрое прототипирование без больших затрат

contract MVPToken {

// Деплой: $10 вместо $300

// Тестирование: $5 вместо $500

}

4. Массовая адопция в развивающихся странах

· Пользователи с меньшими доходами

· Низкие барьеры для входа

· Частые транзакции небольшими суммами

Компромиссы и ограничения BSC

Централизация

· 21 валидатор vs тысячи в Ethereum

· Значительное влияние Binance

· Теоретически более уязвима для регуляторного давления

Безопасность

· Меньшая децентрализация → потенциально меньшая безопасность

· Зависимость от репутации Binance

Восприятие сообществом

· Некоторые рассматривают BSC как "централизованную" альтернативу

· Меньше "элитных" проектов в сравнении с Ethereum

Реальные примеры успеха на BSC

PancakeSwap (CAKE):

· Объем торгов: $1-3 млрд ежедневно

· Комиссия за свап: $0.10-0.30

· Активные пользователи: 500,000+ ежедневно

Venus Protocol (XVS):

· Кредитные займы с комиссиями < $0.50

· TVL: $1+ млрд

BakerySwap (BAKE):

· NFT + AMM с доступными комиссиями

· Идеально для микроплатежей

Практический вывод: Экономика комиссий

javascript

// Расчет экономии для проекта

const calculateSavings = (dailyUsers, avgTransactions) => {

const ethCost = 15; // $ за транзакцию

const bscCost = 0.1; // $ за транзакцию

const monthlyEth = dailyUsers * avgTransactions * 30 * ethCost;

const monthlyBsc = dailyUsers * avgTransactions * 30 * bscCost;

return {

ethereum: `$${monthlyEth.toLocaleString()}`,

bsc: `$${monthlyBsc.toLocaleString()}`,

savings: `$${(monthlyEth – monthlyBsc).toLocaleString()}`

};

};

// Пример для проекта с 1000 пользователей

console.log(calculateSavings(1000, 3));

// { ethereum: "$1,350,000", bsc: "$9,000", savings: "$1,341,000" }

Миграция с Ethereum на BSC

Простота переноса:

· Совместимость с EVM

· Один и тот же код Solidity

· Похожие инструменты разработки

· Аналогичные стандарты (BEP-20 ≈ ERC-20)

Процесс миграции:

1. Изменение конфигурации сети

2. Обновление адресов оракулов и контрактов

3. Тестирование в testnet BSC

4. Деплой в mainnet BSC

Заключение: Стратегический выбор

Выбирайте BSC если:

· Ваш проект требует низких комиссий для массовой адопции

· Вы создаете GameFi, SocialFi или микроплатежное приложение

· Ваша целевая аудитория чувствительна к стоимости транзакций

· Вы хотите быстро протестировать гипотезу с минимальными затратами

Оставайтесь на Ethereum если:

· Максимальная децентрализация и безопасность – приоритет

· Ваш проект ориентирован на институциональных инвесторов

· Вам нужен максимальный престиж и признание в сообществе

· Бюджет на комиссии не является ограничивающим фактором

BSC предоставляет уникальное ценностное предложение: все возможности Ethereum с комиссиями, которые делают блокчейн-технологии доступными для миллиардов пользователей по всему миру.

В следующем разделе мы перейдем к практической реализации – созданию токена BEP-20, используя полученные знания о преимуществах Binance Smart Chain.

6.2 Настройка кошелька (MetaMask) для работы с BSC.

Перед созданием токена на BSC необходимо правильно настроить кошелек для работы с сетью Binance Smart Chain. MetaMask изначально настроен только на Ethereum, поэтому требуется добавить сеть BSC вручную.

Зачем нужно настраивать сеть BSC?

· Доступ к экосистеме BSC: DEX, лендинг-протоколы, NFT-маркетплейсы

· Низкие комиссии: Оплата транзакций в BNB вместо ETH

· Быстрые транзакции: Время блока 3 секунды vs 12 секунд в Ethereum

· Тестирование: Доступ к тестовой сети BSC Testnet

Шаг 1: Получение тестовых BNB

Для тестовой сети (Testnet):

1. Перейдите на BNB Chain Faucet

2. Войдите через GitHub или Google

3. Вставьте ваш адрес MetaMask

4. Получите 0.2 tBNB (тестовых BNB)

Альтернативные краны:

· BSC Testnet Faucet

Конец ознакомительного фрагмента.

Текст предоставлен ООО «Литрес».

Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.

Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.