Первый смарт-контракт, синтаксис Solidity, SPDX, pragma, структура контракта, ABI и байткод
Solidity — это высокоуровневый статически типизированный язык, компилируемый в байткод EVM
Начнём с классического примера — счётчика. Это простейший контракт, который хранит одно число и позволяет его увеличивать. Откройте Remix IDE (remix.ethereum.org) и создайте новый файл Counter.sol.
Каждый файл Solidity начинается с двух обязательных строк: SPDX-лицензия и директива компилятора.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Counter {
uint256 public count;
function increment() external {
count += 1;
}
function reset() external {
count = 0;
}
}Разберём каждую часть по порядку.
Строка // SPDX-License-Identifier: MIT сообщает компилятору и инструментам верификации (Etherscan), под какой лицензией распространяется код. Это не просто комментарий — без неё компилятор выдаст предупреждение. MIT означает, что код можно свободно использовать, копировать и изменять.
Популярные варианты: MIT, Apache-2.0, GPL-3.0, UNLICENSED (проприетарный код без открытой лицензии).
pragma solidity ^0.8.20; задаёт требования к версии компилятора. Оператор ^ означает «совместимо с 0.8.20 и выше, но ниже 0.9.0». Это важно: разные версии Solidity имеют несовместимые изменения. Например, начиная с 0.8.0 встроена защита от integer overflow, а в 0.8.17 появилась оптимизация через via-ir.
Жёсткая фиксация версии (pragma solidity 0.8.20; без ^) — хорошая практика для контрактов, которые уже прошли аудит.
Ключевое слово contract аналогично class в других языках. Внутри контракта определяются:
uint256 public count; — объявляет переменную состояния типа uint256 (беззнаковое 256-битное целое). Модификатор public автоматически создаёт геттер-функцию с тем же именем, поэтому counter.count() работает без явного определения функции чтения.
Другие варианты видимости переменных: private (только внутри контракта), internal (контракт и наследники). Переменные без явного модификатора по умолчанию internal.
В Solidity функции, которые изменяют состояние блокчейна, требуют транзакции и стоят газ. Функции, которые только читают данные, можно вызывать бесплатно (off-chain вызовы).
Рассмотрим контракт с явным разделением:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Greeter {
string private greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
// Изменяет состояние — требует транзакции
function setGreeting(string memory _greeting) external {
greeting = _greeting;
}
// Только читает — бесплатный вызов
function getGreeting() external view returns (string memory) {
return greeting;
}
}view — функция читает storage, но не изменяет. pure — функция вообще не обращается к storage (чистые вычисления). О видимости и мутабельности подробно говорим в теме про функции и модификаторы.
После компиляции Solidity создаёт два артефакта:
ABI (Application Binary Interface) — JSON-описание публичного интерфейса контракта: какие функции есть, их параметры и возвращаемые типы. Именно ABI использует ethers.js или web3.py для кодирования вызовов.
Bytecode — скомпилированные опкоды EVM, которые записываются в блокчейн. Когда вы вызываете функцию, данные транзакции начинаются с 4-байтного selector — первые 4 байта keccak256-хэша сигнатуры функции. Например, для increment() selector — это keccak256("increment()")[:4].
Понимание ABI критически важно: именно через него фронтенд взаимодействует с контрактом. Если изменить сигнатуру функции в контракте, не обновив ABI в приложении — вызовы упадут с ошибкой.
Адрес контракта предсказуем и вычисляется из адреса деплойера и его nonce:
address = keccak256(rlp([deployer_address, nonce]))[12:]
Это означает, что адрес известен ещё до фактического деплоя — факт, который используется в продвинутых паттернах (CREATE2 для deterministic addresses).
После деплоя контракт живёт на своём адресе бессрочно. Изменить байткод нельзя — это фундаментальное свойство, которое мы обойдём через proxy-паттерн в последней теме курса.
Чтобы задеплоить первый контракт прямо сейчас:
Counter.sol и вставьте код из начала этой темыRemix — отличный инструмент для обучения и прототипирования. Для production-разработки используют Hardhat или Foundry с тестами и скриптами деплоя.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.