July 11, 2023

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

Вступление

Начну с того, что solidity это строго типизированный язык, а это значит, что у каждой переменной обязательно нужно указывать ее тип:

uint a = 0
string b = "Hi NaN"
bool c = true 

Int / Uint

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

Они могут быть как:

uint8 uint16 uint32 uint64 uint128 uint256

Число после uint указывает на количество бит, используемых для представления значения. Например, uint8 может представить целые числа от 0 до 255 (2^8 - 1), в то время как uint256 может представлять очень большие числа.

String

В языке программирования Solidity, тип данных string используется для представления динамических строковых значений. Строки (string) в Solidity могут содержать любые последовательности символов, включая буквы, цифры, специальные символы и даже пустые строки.

Вот так выглядит строка:

string myString = "Hello, World!";

Тип string поддерживает несколько операций и функций для работы со строками. Некоторые из них включают:

  • Конкатенация строк: Для объединения двух строк можно использовать оператор + или функцию concat.
string myString = "Hello, ";
string anotherString = "World!";
string concatenatedString = myString + anotherString; // Результат: "Hello, World!"
  • Длина строки: Функция length позволяет узнать длину строки (количество символов).
string myString = "Hello";
uint length = bytes(myString).length; // Результат: 5
  • Сравнение строк: Для сравнения строк можно использовать операторы == и !=, а также функцию compare.
string string1 = "Hello";
string string2 = "World";
bool isEqual = (keccak256(abi.encodePacked(string1)) == keccak256(abi.encodePacked(string2))); // Результат: false

int comparisonResult = string1.compare(string2); // Результат: -1 (если первая строка меньше), 0 (если строки равны), 1 (если первая строка больше)
  • Доступ к символам строки: Solidity не поддерживает прямой доступ к символам строки по индексу. Однако можно использовать библиотеки, такие как bytes или abi.encodePacked, чтобы получить байты строки и работать с ними.
string myString = "Hello";
bytes memory stringBytes = bytes(myString);
bytes1 firstCharacter = stringBytes[0]; // Результат: 'H'

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

Bool

Тип данных bool представляет логическое значение, которое может быть либо true (истина), либо false (ложь). Тип bool используется для условных операций и логических выражений.

Пример объявления переменной типа bool:

bool myBool;

Тип bool поддерживает операции и функции для работы с логическими значениями. Некоторые из них включают:

  • Логические операторы: Тип bool поддерживает стандартные логические операторы, такие как логическое И (&&), логическое ИЛИ (||) и логическое НЕ (!). Они используются для комбинирования и проверки логических значений.
bool a = true;
bool b = false;
bool result1 = a && b; // Результат: false
bool result2 = a || b; // Результат: true
bool result3 = !a; // Результат: false
  • Сравнение булевых значений: Можно использовать операторы сравнения (==, !=) для сравнения двух булевых значений.
bool a = true;
bool b = false;
bool isEqual = (a == b); // Результат: false
bool isNotEqual = (a != b); // Результат: true
  • Условные выражения: Булевые значения часто используются в условных выражениях, таких как операторы if, else if и else, для выполнения различных действий в зависимости от истинности ложности условия.
bool condition = true;
if (condition) {
  // Выполняется, если условие истинно
} else {
  // Выполняется, если условие ложно
}
  • Возвращение булевых значений из функций: Функции в Solidity могут возвращать булевые значения. Например:
function isGreaterThan(uint a, uint b) public pure returns (bool) {
  return a > b;
}

Логические значения true и false могут использоваться для управления ходом выполнения программы, принятия решений и задания условий. Они широко применяются в контрактах Solidity для проверки условий выполнения и принятия соответствующих действий в зависимости от результата проверки.

Address

Тип данных address используется для представления адресов Ethereum. Адрес Ethereum - это 20-байтовое значение, которое уникально идентифицирует счет или контракт на блокчейне Ethereum.

Пример объявления переменной типа address:

address myAddress;

Тип address поддерживает операции и функции для работы с адресами Ethereum. Некоторые из них включают:

  • Операторы сравнения: Можно использовать операторы сравнения (==, !=) для сравнения двух адресов.
address address1 = 0x1234567890123456789012345678901234567890;
address address2 = 0x0987654321098765432109876543210987654321;
bool isEqual = (address1 == address2); // Результат: false
bool isNotEqual = (address1 != address2); // Результат: true
  • Баланс адреса: Через переменную типа address можно получить баланс Ether, связанный с указанным адресом, с помощью функции balance.
address myAddress = 0x1234567890123456789012345678901234567890;
uint balance = myAddress.balance;
  • Отправка Ether: Через переменную типа address можно отправить Ether другому адресу с помощью функции transfer. Обратите внимание, что важно проверять успешность выполнения операции перед продолжением работы.
address recipient = 0x0987654321098765432109876543210987654321;
uint amount = 1 ether;
bool success = recipient.transfer(amount);
  • Встроенные функции send и call: В дополнение к функции transfer, можно использовать функции send и call для отправки Ether и выполнения других действий на адресах Ethereum.

Тип address также имеет встроенные члены, такие как balance и transfer, которые предоставляют информацию о балансе адреса и функцию для отправки Ether. Они полезны для взаимодействия с другими адресами Ethereum и управления переводами Ether.

Array

Массив (array) представляет упорядоченную коллекцию элементов одного типа. Массивы могут быть одномерными или многомерными и могут содержать фиксированное количество элементов или быть динамическими, изменяемыми по размеру.

Одномерные массивы:

// Объявление одномерного фиксированного массива с размером 5
uint[5] myFixedArray;

// Объявление одномерного динамического массива
uint[] myDynamicArray;

Многомерные массивы:

// Объявление двумерного фиксированного массива с размерами 3x2
uint[3][2] myFixed2DArray;

// Объявление двумерного динамического массива
uint[][2] myDynamic2DArray;

Операции и функции для работы с массивами:

  • Получение длины массива: Свойство length возвращает количество элементов в массиве.
uint[] myArray = [1, 2, 3, 4, 5];
uint length = myArray.length; // Результат: 5
  • Доступ к элементам массива: Массивы индексируются начиная с нуля. Для доступа к элементу используйте квадратные скобки [индекс].
uint[] myArray = [1, 2, 3, 4, 5];
uint element = myArray[2]; // Результат: 3
  • Изменение элементов массива: Элементы массива могут быть изменены путем присваивания нового значения по индексу.
solidityCopy codeuint[] myArray = [1, 2, 3, 4, 5];
myArray[2] = 10; // Изменение элемента с индексом 2 на 10
  • Добавление элементов в динамический массив: Метод push позволяет добавить элемент в конец динамического массива.
uint[] myArray;
myArray.push(10);
myArray.push(20);
  • Итерация по массиву: Циклы for или while могут быть использованы для итерации по элементам массива.
uint[] myArray = [1, 2, 3, 4, 5];
for (uint i = 0; i < myArray.length; i++) {
  // Использование myArray[i]
}
  • Длина массива как параметр функции: Функции могут принимать массивы в качестве параметров и возвращать массивы.
function doubleValues(uint[] array) public pure returns (uint[] memory) {
  uint[] memory result = new uint[](array.length);
  for (uint i = 0; i < array.length; i++) {
    result[i] = array[i] * 2;
  }
  return result;
}

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

Mapping

mapping - это структура данных, которая представляет собой ассоциативный массив (словарь) для связывания ключей с их значениями. Он позволяет хранить и получать значения по ключу.

mapping объявляется с использованием ключевого слова mapping, за которым следуют типы ключа и значения в угловых скобках < >. Ключ может быть любым типом данных, за исключением динамических массивов, а значение может быть любым типом данных.

Пример объявления mapping:

mapping(uint => string) myMapping;

mapping может быть использован для создания простого словаря, где ключи и значения связаны между собой. Значения могут быть установлены или получены с использованием оператора доступа вида mapping[key].

Пример использования mapping:

mapping(uint => string) names;

function setName(uint id, string memory name) public {
    names[id] = name;
}

function getName(uint id) public view returns (string memory) {
    return names[id];
}

В приведенном примере функция setName принимает id в качестве ключа и name в качестве значения, которое связывается с ключом в mapping. Функция getName принимает id в качестве аргумента и возвращает соответствующее ему значение из mapping.

Важно отметить, что mapping в Solidity не является итерируемым, то есть нельзя получить список всех ключей или значений напрямую. Также нельзя проверить наличие ключа в mapping. Обычно используются другие структуры данных, такие как массивы или дополнительные переменные, для выполнения таких операций.

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

Struct

struct - это пользовательский тип данных, который позволяет объединять несколько различных типов данных в одну структуру. Структуры позволяют создавать новые типы данных, состоящие из нескольких полей, каждое из которых может иметь свой собственный тип.

Структуры определяются с использованием ключевого слова struct, за которым следует имя структуры и список полей в фигурных скобках { }.

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

struct Person {
    string name;
    uint age;
    address wallet;
}

В приведенном примере определена структура Person с тремя полями: name типа string, age типа uint и wallet типа address.

Структуры могут использоваться для создания экземпляров (объектов) этого типа данных, где каждое поле может быть заполнено соответствующим значением.

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

Person myPerson;
myPerson.name = "Alice";
myPerson.age = 30;
myPerson.wallet = 0x1234567890123456789012345678901234567890;

Структуры также могут использоваться внутри других типов данных, таких как массивы, mapping и даже другие структуры.

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

А на этом всё, надеюсь было полезно и понятно.

Телеграм: https://t.me/one_eyes

Чатик: https://t.me/one_eyes_chat