Solidity
October 14, 2022

Solidity | Типы данных

Начну с того, что solidity это строго типизированный язык, а это значит, что у каждой переменной обязательно нужно указывать ее тип (uint a = 0, string b = "Hello"). Это напоминает язык c++, там тоже нужно указывать всегда тип переменных.

int и uint - целое число

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

Int и uint - это тип данных intenger (целые числа), int - это положительные и отрицательные числа, uint - только положительные.

String - строка

Про строки сказать много не получиться, потому что они очень слабо реализованы в solidity. Из за того что строки хранятся в виде байтового массива, мы не можем посчитать их длину. То есть понятие str.length() нету. Так же мы не можем склеивать строки, например: если у нас есть str1 = "Hello" и str2 = "world", мы не можем сказать str3 = str1 + str2. Еще мы не можем проиндексировать строку, сказать например str[0] и достать первую букву не получится. В целом со строками работать часто бывает бессмысленно в виду того, что у них отсутствует очень много полезных функций, а так все так же как и в других языках. Надеемся, что в бедующих версиях solidity это изменится.

Bool - логическое значение

Bool - это значение true или false. То есть мы просто можем сказать: bool pay = true, что-то там сделать и после выполнения этого чего-то сказать: pay = false
В общем как и во всех языках.

Address - адрес

Address - это особенный тип данных, который был создан специально для solidity. Он содержит 20-байтовое значение адреса эфириум кошелька или смарт-контракта, очень полезная штука и используется в каждом смарт-контракте как минимум для назначения овнера. Например address owner = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4.

bytes32 и bytes - байтовый массив

Bytes32 содержит последовательность из 32 байтов, так же можно задать bytes1 или bytes4 (любой вид от 1 до 32). С помощью bytes32 мы можем просто декодировать байты во внешнем интерфейсе, и в блокчейне будет храниться меньше данных.

Например в этой функции я нашу строку кодирую в bytes32.

На выходе мы получаем: bytes32: 0x48656c6c6f20776f726c64000000000000000000000000000000000000000000
если вы знаете что такое таблица ASCII, то вы заметите, что 48656c6c6f20776f726c64 - это и есть наш Hello world
Но у нас еще есть такая штука, как массив байтов с динамическим размером - bytes
Ну что я щас буду вам объяснять, давайте лучше покажу

как можно заметить не значащие нули пропали, что и логично, ведь у нас динамический массив, но по газу выигрыша не будет. Единственное, что можно заметить это какой то не понятный memory - это означает что переменная временная и не сохраняется в блокчейн. Но об этом по подробнее в другой раз.

На самом деле про байтовые массивы можно еще много говорить, но я думаю уже и так достаточно рассказал. Кстати 0x в начале означает, что это шестнадцатеричная система.

Array - массив

Массивы можно делать любых типов данных. Но нужно понимать, что смешивать их нельзя. Например взять uint и string в одни массив нельзя.
Как массивы обозначаются в solidity: тип данных, [длинна] и название (uint[3] array).
Так же можно создать динамический массив: uint[] array
Ну тут я думаю много говорить нет смысла.
Банальный пример, где я создаю массив из 3 элементов и потом просто перезаполняю его.

Обратите внимание как я заполняю аргумент функции в Remix. Это нужно делать именно так [1, 3, 4], иначе будет ошибка. Ну и потом я обращаюсь к последнему элементу массива и он мне возвращает цифру 4, как и должно быть.

Struct - структуры данных

Struct - очень интересный тип данных. Он в себя вмещает другие типы данных, такие как uint, address, bytes32. Например:
struct Human {
address me;
uint age;
uint height;
string name;
}
Количество данных внутри структуры не ограниченно. Но самое интересное, что можно создать массив из структур. В нашем случае можно создать массив из людей, где у каждого будут свои данные.
Как это сделать: мы говорим, что наша структура это массив Human[] и называем (Human[] public peaple). Это уже интересно.

Давайте попробуем создать пример:

Так мы создаем структуру Human, передаем туда наши поля (myAdr, age, name, myBalance), потом я создаю функцию, где просто передаю аргументы и в самом теле функции я засовываю нашего человека в массив людей.
Обратим внимание, что все аргументы функции в Remix я передаю подряд, через запятую именно в том порядке, в котором я их указал в коде.
Ну и потому по старой методике обращаемся к 1 элементу массива и видим, что у нас в массиве появился человек!
Так же мы можем обратиться к любому члену структуры через точку (Human.name), как вариант.

Mapping или просто ключ значение

Mapping - это что то на подобии библиотек в питоне. Выглядит так:
mapping(address => uint) name. В данном случает ключом выступает address а значением uint. Ну вроде ни чего особенного.
Давайте рассмотрим пример:

Вот мы создали mapping, назвали его balances. Теперь просто, когда мы создаем структуру человека в нашей функции, то и в добавок по адресу в mapping добавляем значение баланса. Дальше мы можем просто обратиться по адресу в mapping и узнать баланс человека. Обратите внимание в Remix, что адрес в структуре совпадает с адресом, который я вставляю в mapping (balances).

Ну думаю на этом можно закончить рассказ о типах данных. Дальше больше. Рассмотрели самые важные и те, которые чаще всего используются из них. Если где-то не точно что-то рассказал или ошибся, то буду рад, если напишите об этом.

tg: мой телеграмчик)