Следующий день Алекса начался с радостного волнения. Его приключение в мир solidity продолжалось. Он уже научился писать функции, добавлять интерактивность в свои программы. Сегодня Алексу стало интересно, какие данные он может хранить в смарт-контракте.
— «Сундук с данными? Звучит как настоящее приключение! Пора заглянуть внутрь.»
Алекс решил начать с изучения числовых и логических типов данных — основы всех вычислений в смарт-контрактах.
Числовые и логические типы данных
Термины
Uint (unsigned integer) — беззнаковое целое число, которое не может быть отрицательным. Используется для хранения количеств, балансов, счетчиков. Может иметь разные размеры: uint8, uint16, uint32, uint256. Пример: 255, 1000000, 0.
Int (integer) — знаковое целое число, которое может быть как положительным, так и отрицательным. Полезно для математических вычислений, где могут быть отрицательные результаты. Пример: -128, 127, -1000000.
Bool — логический тип данных, который может принимать только два значения: true (истина) или false (ложь). Используется для условий, флагов состояния, проверок.
Слот хранения — единица хранения данных в блокчейне размером 32 байта (256 бит). Solidity автоматически упаковывает переменные в слоты для экономии места и газа.
Public — модификатор видимости, делающий переменную или функцию доступной для всех пользователей. Для переменных автоматически создается функция-геттер, которая позволяет только читать значение переменной. Важно понимать: public не влияет на возможность изменения переменной. Переменные можно изменять только в функциях самого смарт-контракта.
Обзор числовых и логических типов данных
В этом уроке мы изучим основные типы данных для работы с числами и логическими значениями в Solidity. Эти типы являются фундаментом для любых вычислений в смарт-контрактах. Все типы данных имеют начальные значения по умолчанию и занимают определенное количество места в памяти.
Понимание этих характеристик поможет вам писать эффективные и экономичные смарт-контракты, а также правильно выбирать подходящие типы для конкретных задач.
Числовые типы
Числовые типы данных используются для хранения чисел. Они имеют разную вместимость, а также могут быть как только положительными, так и хранить знак. Только положительные числа называются uint (unsigned integer). А числа, которые могут принимать отрицательные значения, называются int (integer). После названия типа указывается размер числа в битах, например uint8, int16, uint256 и т.д.
Целочисленные переменные часто используются для хранения балансов, счетчиков. Например, баланс пользователя в смарт-контракте токена, количество собранной комиссии на счету смарт-контракта или количество инвесторов в ICO и т.д.
Алекс открыл раздел документации с числами. Всё оказалось не так просто — перед ним открылась целая система сейфов с разным объёмом и назначением.
Таблица числовых типов
Тип
Что это?
Пример данных
Размер (байт)
Начальное значение
uint8
Беззнаковое число 8-бит
0; 255; 100
1
0
uint16
Беззнаковое число 16-бит
0; 65535; 1000
2
0
uint32
Беззнаковое число 32-бит
0; 4294967295; 1000000
4
0
uint256
Беззнаковое число 256-бит
0; 1000000000000000000
32
0
int8
Знаковое число 8-бит
-128; 127; 0; -50
1
0
int16
Знаковое число 16-бит
-32768; 32767; -1000
2
0
int32
Знаковое число 32-бит
-2147483648; 2147483647
4
0
int256
Знаковое число 256-бит
-123456789; 1000000000
32
0
Знать размер типа данных важно для оптимизации стоимости разворачивания и использования смарт-контракта. В Solidity переменные упаковываются в слоты по 32 байта, поэтому правильный выбор типа может существенно снизить затраты на газ.
Uint — только положительные богатства
Беззнаковые целые числа (uint) представляют собой фундаментальный тип данных для хранения исключительно неотрицательных значений. Данный тип особенно востребован в контексте финансовых операций и управления ресурсами, где отрицательные значения концептуально неприменимы или нежелательны.
Размерность uint-типов определяет диапазон допустимых значений: от uint8 (0-255) до uint256 (0 до 2^256-1). Выбор подходящего размера влияет на эффективность использования газа и оптимизацию хранения данных в слотах блокчейна.
Рассмотрим практическое использование различных размерностей uint-типов:
Solidity
contractAlexNumberVault{
// Разные размеры сейфов для разных сумм
uint8public tinyNumber =255; // Максимум 255 (от 0 до 255)
uint32public mediumNumber =4294967295; // Около 4 миллиардов
uint256public hugeNumber =1000000000000000000; // Огромное число!
// uint без размера = uint256 (самый большой сейф)
uintpublic defaultNumber =42;
}
— «Uint — это как сейфы для чистого золота. Только положительные значения, никакого долга. И чем больше сейф, тем больше сокровищ в него помещается!»
Int — полная палитра чисел
Знаковые целые числа (int) обеспечивают возможность работы с полным спектром целочисленных значений, включая отрицательные числа. В отличие от беззнаковых типов, int-переменные используют один бит для хранения знака числа, что сокращает диапазон положительных значений вдвое, но расширяет функциональность за счет поддержки отрицательных величин.
Данный тип данных незаменим в сценариях, где требуется моделирование математических операций с потенциально отрицательными результатами.
Практическая демонстрация использования знаковых целых чисел:
Solidity
contractAlexFullNumberVault{
// Сейфы, которые могут хранить и долги, и богатства
int8public tinySignedNumber =-128; // От -128 до 127
int16public smallSignedNumber =-1000; // От -32,768 до 32,767
int256public hugeSignedNumber =-123456789; // Огромный диапазон
int256public hugeSignedNumberPositive =123456789; // Можно хранить и положительные числа
// int без размера = int256
intpublic temperature =-10; // Может быть отрицательной температурой!
}
— «А вот int — это уже как счёт кредитной карты. Можно как копить, так и брать в долг. Главное — правильно рассчитывать риски.»
Алекс сделал функцию расчёта разницы между двумя знаковыми числами:
Solidity
functioncalculateDifference(int256 a, int256 b) publicpurereturns (int256) {
return a - b; // Может быть отрицательным результатом
}
— «Теперь понятно, почему существуют оба типа! Uint экономит место и защищает от случайных отрицательных значений, а int дает полную свободу математических рассчетов!»
Логические решения
Алекс заинтересовался вопросом принятия решений в смарт-контрактах. Для логических операций используется тип данных bool. Он может принимать только два значения: true или false – правда или ложь. Логические переменные часто используются для определения, в каком состоянии находится контракт. Например, открыто ли прохождение уроков на платформе BlockFirst, или является ли пользователь инвестором.
Логический тип данных
Тип
Что это?
Пример данных
Размер (байт)
Начальное значение
bool
Истина или ложь
true; false
1
false
Логические переменные особенно полезны для создания условий и управления поведением смарт-контракта. Они позволяют контракту "принимать решения" на основе текущего состояния. Например, можно проверить, завершён ли урок, есть ли у пользователя доступ, или готов ли контракт к следующему этапу.
Рассмотрим практический пример использования логических переменных в смарт-контракте:
— «Bool — это как выключатель. Либо свет включён, либо нет. Простота и ясность — ключ к надёжным решениям.»
Начальные значения переменных — автоматическая инициализация
Алекс заметил интересную особенность:
— «А что если я объявлю переменную, но не присвою ей значение? Будет ли ошибка?»
Оказалось, что в Solidity все переменные автоматически инициализируются значениями по умолчанию при создании контракта. Это означает, что каждый тип данных имеет своё "нулевое" состояние, которое устанавливается по умолчанию.
Solidity
contractAlexDefaultValues{
// Эти переменные не имеют явно заданных значений
uint256public defaultNumber; // Автоматически = 0
int256public defaultSignedNumber; // Автоматически = 0
boolpublic defaultBool; // Автоматически = false
// А эти переменные явно инициализированы
uint256public explicitNumber =0; // Явно установлено 0
boolpublic explicitBool =false; // Явно установлено false
functionshowDefaultValues() publicviewreturns (
uint256 num,
int256 signedNum,
bool boolean
) {
return (
defaultNumber, // Вернёт 0
defaultSignedNumber, // Вернёт 0
defaultBool // Вернёт false
);
}
}
Почему начальные значения важны?
Экономия газа: Если нужное значение совпадает со значением по умолчанию, можно не инициализировать переменную явно и сэкономить газ при развёртывании контракта.
Безопасность: Отсутствие неинициализированных переменных предотвращает многие ошибки и уязвимости.
Предсказуемость: Всегда знаешь, какое значение будет у переменной, даже если она явно не инициализирована.
— «Понятно! Solidity заботится о том, чтобы у каждой переменной было понятное начальное состояние. Это как если бы каждый новый сейф в банке изначально был пустым, а не содержал случайный мусор. И если мне нужен именно пустой сейф, то незачем тратить время на дополнительную очистку!»
return baseAmount *2; // Удваиваем количество токенов
}
// Функция для работы с логическими значениями
functioncompleteLesson() public{
isLearningComplete =true; // Отмечаем урок как завершенный
}
// Функция для проверки доступа
functioncheckAccess() publicviewreturns (uint8) {
if (isReadyForAdvanced) {
return2; // Готов к продвинутым урокам
} elseif (hasCompletedLesson) {
return1; // Урок завершен, но еще учусь
} else {
return0; // Еще изучаю урок
}
}
}
К вечеру Алекс закрыл ноутбук и задумался:
— «Сегодня я изучил основы работы с числами и логическими значениями в Solidity. Эти простые типы данных — фундамент для всех вычислений в смарт-контрактах. Теперь я понимаю, как выбирать правильный размер для чисел и как использовать логические переменные для управления состоянием контракта. Завтра изучу более сложные типы данных!»