Язык Solidity: Структуры (Урок 5)

Предыдущие уроки:
Язык Solidity: Неllo World (Урок 1)
Язык Solidity: Типы данных (Урок 2)
Язык Solidity: Переменные состояния контракта (Урок 3)
Язык Solidity: Массивы и соответствия (Урок 4)
Структура User
В языках программирования структуры подразумневают отдельные (комплексный) типы данных. Опять же возвращаясь к аналогии с нашим PHP и БД можно сравнить с описанием таблицы, а каждая переменная типа этой структуры - запись в этой таблице. Так же как записи в таблицах могут ссылаться на записи в других таблицах по внешнему ключу, можно определить связи между структурами внутри контракта.Как мы знаем - контракты довольно часто применяются для сбора средств (ICO).
Предлагаю как обычно начать с простых примеров дабы въехать в курс дела :)
Вообще любой программист должен воспринимать структуры без особых затруднений, так как большинство приложений вводят и выводят данные именно в виде данных структур, отформатированными по определенным правилам.
Первым примером будет такой контракт:
pragma solidity ^0.4.0;
contract MyStruct {
struct User {
string name;
uint8 age;
uint256 balance; // тип можно просто uint - псевдоним
}
// ID нового юзера
uint lastUserId;
// Создаем соответствие (массив), где будем держать юзеров
mapping(uint => User) users;
// И как обычно добавляем функции для взаимодействия
// с контрактом
// Добавление юзера
function addUser(string name, uint8 age, uint256 balance) returns (uint thisId) {
thisId = lastUserId++; // увеличиваем счетчик на 1
users[thisId] = User(name, age, balance);
}
}
Теперь в наш контракт можно добавлять пользователей. Например ввод:
{
"string name": "Ivan I",
"uint8 age": "34",
"uint256 balance": "215"
}
То наш вывод функции (ID пользователя) будет такой:
{
"uint256 thisId": "0"
}
здесь у нас не 1, потому что мы используем постинкремент: thisId = lastUserId++
в данном случае сначала выполняется присваивание, а затем переменная увеличивается на 1.
Если мы добавим нового пользователя, например:
{
"string name": "Ivan I",
"uint8 age": "34",
"uint256 balance": "215"
}
то получим соответственно:
{
"uint256 thisId": "1"
}
и так далее.
Работа с балансом пользователя (учебный пример - как в реальности надо разберем позже)
Для работы с балансом, пишем 3 функции: проверка, зачисление и снятие.
Понятное дело, поскольку мы еще не обсуждали контроль доступа, в реальности так никто не делает (поскольку любой может изменять эти данные). Но нам важно понять принцип.
Просмотр текущего баланса
// Просмотр баланса
function getUserBalanceById(uint userId) returns (uint) {
// Проверка корректности ID
if(userId < 0 && userId > lastUserId) return 0;
// Возвращаем баланс
return users[userId].balance;
}
Тут первая строчка проверяет, что такой аккаунт есть в хранилище данных контракта.
Вторая возвращает его. Так как мы используем массив структур - мы передаем в качестве индекса id пользователя, а для извлечения баланса используем точечный синтаксис.
Пополнение баланса
// Пополнение баланса
function addUserAmount(uint userId, uint amount) {
if(userId > 0 && userId <= lastUserId && amount > 0) {
users[userId].balance += amount;
}
}
Теперь например, если мы добавим пользователя с id=1 и балансом 500 токенов, и вызовем эту функцию с параметрами:
{
"uint256 userId": "1",
"uint256 amount": "30"
}
то getUserBalanceById(1)
вернет 530.
Снятие токенов с баланса
Аналогичным образом токены снимаются
// Это совсем неправильная функция
// Просто вычитает c баланса :)
function daj(uint userId, uint many) {
if(userId > 0 && userId <= lastUserId && many > 0) {
users[userId].balance -= many;
// TODO send
}
}
При транзакции с вызовом этой функции баланс пользователя аналогичным как и при пополнении образом уменьшится на значение many.
Полный код контракта MyStruct
pragma solidity ^0.4.0;
contract MyStruct {
struct User {
string name;
uint8 age;
uint256 balance; // тип можно просто uint - псевдоним
}
// ID нового юзера
uint lastUserId;
// Создаем соответствие (массив), где будем держать юзеров
mapping(uint => User) users;
// И как обычно добавляем функции для взаимодействия
// с контрактом
// Добавление юзера
function addUser(string name, uint8 age, uint256 balance) returns (uint thisId) {
thisId = lastUserId++; // увеличиваем счетчик на 1
users[thisId] = User(name, age, balance);
}
// Просмотр баланса
function getUserBalanceById(uint userId) returns (uint) {
// Проверка корректности ID
if(userId < 0 && userId > lastUserId) return 0;
// Возвращаем баланс
return users[userId].balance;
}
// Пополнение баланса
function addUserAmount(uint userId, uint amount) {
if(userId > 0 && userId <= lastUserId && amount > 0) {
users[userId].balance += amount;
}
}
// Это совсем неправильная функция
// Просто вычитает c баланса :)
function daj(uint userId, uint many) {
if(userId > 0 && userId <= lastUserId && many > 0) {
users[userId].balance -= many;
// TODO send
}
}
}
@rusldv Поздравляю! Вы добились некоторого прогресса на Голосе и были награждены следующими новыми бейджами:
Вы можете нажать на любой бейдж, чтобы увидеть свою страницу на Доске Почета.
Чтобы увидеть больше информации о Доске Почета, нажмите здесь
Если вы больше не хотите получать уведомления, ответьте на этот комментарий словом
стоп
Ваш пост поддержали следующие Инвесторы Сообщества "Добрый кит":
kavalsky, niiu, archibald116, rusalka, orezaku, vika-teplo, el-puzo, galinakim
Поэтому я тоже проголосовал за него!
Узнать подробности о сообществе можно тут:
Разрешите представиться - Кит Добрый
Правила
Инструкция по внесению Инвестиционного взноса
Вы тоже можете стать Инвестором и поддержать проект!!!
Если Вы хотите отказаться от поддержки Доброго Кита, то ответьте на этот комментарий командой "!нехочу"
dobryj.kit теперь стал Делегатом! Ваш голос важен для всего сообщества!!!
Поддержите нас на странице https://golos.io/~witnesses, вот так: