Алекс начинает с переменных состояния контракта:
Окей, переменная — это как коробка с названием. Сегодня в ней лежит одно, завтра другое. Самое важное — новое значение переменной состояния сохраняется, если оно было изменено в функции. Блокчейн может хранить информацию!
Переменные
Термины
Переменная состояния — переменная, которая хранится в блокчейне и доступна всем функциям контракта для чтения или изменения. Объявляется в теле контракта. Переменные состояния можно изменять внутри функций смарт-контрактов. Они образуют память контракта и сохраняются между вызовами функций. Изменение переменной состояния в функции увеличивает стоимость вызова этой функции. Для краткости в дальнейшем будем называть переменные состояния просто переменными.
Модификатор видимости переменной — ключевое слово, которое определяет, кто может прочитать переменную – текущий контракт, наследующий контракт, пользователь с помощью кошелька или внешний контракт. Пример модификаторов видимости – public, private или internal.
Объявление переменных состояния
Объявление переменной начинается с типа данных, определяющего, значения какого типа могут храниться в этой переменной. Затем идет имя переменной. Между типом и именем может стоять модификатор видимости. Модификатор видимости определяет, кто может читать эту переменную.
Solidity
contractMyContract{
...
тип_данных имя_переменной;
тип_данных public имя_переменной;
тип_данных private имя_переменной;
тип_данных internal имя_переменной;
...
}
Типы данных переменных
Алекс понимает важный принцип:
— «Каждая переменная в Solidity должна иметь свой тип данных! Это как этикетка на коробке — она говорит, что именно можно в эту коробку положить.»
Тип данных определяет:
Какие значения может хранить переменная
Сколько памяти она занимает
Какие операции с ней можно выполнять
Основные типы данных в Solidity:
uint256 — для положительных целых чисел (0, 1, 2, 100, 1000000...)
int256 — для целых чисел включая отрицательные (-100, -1, 0, 1, 100...)
bool — для логических значений (true или false)
string или string memory — для текста ("Привет", "Алекс", "Мой контракт"...)
address — для адресов кошельков и смарт-контрактов
bytes или bytes memory — для двоичных данных
— «Без указания типа Solidity не поймет, что я хочу хранить в переменной. Это как сказать "дай мне коробку" не объяснив, для чего она нужна — для обуви, книг или продуктов!»
Модификаторы видимости для переменных
Алекс задумывается:
— «Интересно, а кто вообще может видеть мои переменные? Может ли любой пользователь посмотреть, что у меня хранится в контракте? Или есть способы скрыть информацию?»
public – переменную могут прочитать все. Автоматически создается функция-геттер, позволяющая всем читать значение переменной извне контракта. Например, для uint256 public counter будет создана функция function counter() public view returns (uint256), с помощью которой любой контракт или пользователь сможет прочитать значение переменной счетчика.
private – переменная доступна для чтения только внутри данного контракта, даже наследующие контракты не могут ее прочитать
internal – переменная доступна для чтения внутри контракта и его наследников (по умолчанию для переменных)
По умолчанию переменные объявляются как internal.
Важно: Модификатор public позволяет только читать переменную извне контракта, но никак не влияет на возможность ее изменения. Изменять переменную могут только функции внутри контракта. Чтобы переменную можно было изменить извне, нужно создать специальную функцию для этого.
Также важно: Модификаторы internal или private не позволяют скрывать или шифровать информацию! Они всего лишь ограничивают возможность других смарт-контрактов получать к ней доступ. В блокчейне все данные публичны, поэтому переменные состояния не подходят для хранения секретной информации
Алекс решил разобраться с переменными подробнее, и сделал смарт-контракт для экспериментов с переменными. Он пробует простой пример:
Solidity
contractSimpleStorage{
// Это переменная с именем "message", в которой хранится текст.
// Доступна только внутри контракта
string message;
// Это переменная с именем "number", в которой хранится число.
// Доступна только внутри контракта и его дочерних контрактов
uint256 number;
// Это переменная с именем "publicNumber", в которой хранится число.
// Доступна всем
uint256public publicNumber;
// Это переменная с именем "privateBool", в которой хранится булево значение – true или false.
// Доступна только внутри контракта
boolprivate privateBool;
// Это переменная с именем "internalAddress", в которой хранится адрес.
// Доступна только внутри контракта и его дочерних контрактов
addressinternal internalAddress;
}
Одна переменная хранит текст, другая — число. Алекс понимает: переменные бывают разными. Есть строковые переменные — для текстов. Есть числовые переменные — для математических расчётов. Есть булевы значения — правда или ложь. Есть адреса — для хранения данных о владельцах и пользователях.
Инициализация переменных по умолчанию
Алекс замечает интересную особенность:
— «А что, если я объявлю переменную, но не присвою ей значение? Что в ней будет храниться?»
Он изучает документацию и узнает важное правило: в Solidity все переменные автоматически инициализируются значениями по умолчанию.
У каждого типа данных есть значение по умолчанию, которое будет храниться в переменной, если ей не присвоить значение.
Алекс узнает про конструктор — специальную функцию, которая выполняется один раз при создании контракта.
— «Конструктор — это как церемония запуска корабля. Происходит только один раз, когда контракт появляется в блокчейне. После этого конструктор больше никогда не вызывается.»
Что такое конструктор?
Конструктор — это специальная функция, которая:
Выполняется автоматически при развертывании контракта
Может принимать параметры от создателя контракта
Используется для настройки начального состояния
Вызывается только один раз за всю жизнь контракта
Solidity
contractConstructorInitialization{
// Переменные, которые будут инициализированы в конструкторе
owner =msg.sender; // Зависит от того, кто создает контракт
creationTime =block.timestamp; // Зависит от времени создания
initialSupply = _supply; // Передается как параметр
customName = _name; // Настраивается при создании
}
}
3. Значения по умолчанию
Используй когда нулевое значение подходит:
Solidity
contractUserStats{
uint256public score; // Автоматически 0 — новые пользователи начинают с нуля
boolpublic isVerified; // Автоматически false — пользователи не верифицированы
uint256public lastLogin; // Автоматически 0 — еще не входили
}
— «Теперь я понимаю! Solidity сам заботится о безопасности — никаких случайных значений. А я могу выбирать наиболее подходящий способ для каждой переменной.»
Комплексный практический пример
Алекс решает создать контракт игровой платформы, который демонстрирует все способы инициализации:
platformLaunchTime =block.timestamp; // Текущее время блокчейна
// Значения, передаваемые при создании
seasonNumber = _seasonNumber; // Номер сезона задается при создании
welcomeMessage = _message; // Сообщение настраивается
}
}
— «Отлично! Теперь я вижу, как разные способы инициализации работают вместе. Каждый имеет свое предназначение и помогает сделать код более понятным и эффективным.»
Практическое задание по инициализации переменных
Алекс изучил теорию инициализации переменных и решил применить знания на практике:
— «Теперь я знаю, как правильно объявлять переменные! Попробую создать контракт для хранения информации о defi платформе.»
Но когда он начал писать код, то допустил несколько ошибок. Помоги Алексу исправить проблемы с инициализацией переменных.