По многомерным массивам, imho, самое простое объяснение такое: тип_элемента [] имя_массива где тип_элемента может в свою очередь быть тоже массивом (напримет, uint[]). В этом существенное отличие от обычных языков, где порядок индексов обратный
@ДанШкрд2 жыл бұрын
Спасибо большое за ваш труд! Очень рад, что в самом начале удалось найти такие качественные и проработанные материалы - это значительно облегчает обучение и улучшает понимание!
@cryptomoon47002 жыл бұрын
через 3 дня постоянного просмотра понял о чем говорится в конце урока по структуре данных и мепинге))
@loki8705 Жыл бұрын
Смотрю уже в 7ой раз. И всё еще чего то не понимаю.. . . Видимо у меня впереди 2 незабываемых дня)
@markus_037 Жыл бұрын
Меппинг вобще не понятно 😅😅😅
@alephzero780811 ай бұрын
@@markus_037mapping это как arrays в JS
@mrin0 Жыл бұрын
!Что за жесть началась в struct? Нормально ж всё было.
@IlyaBodrovKrukowski Жыл бұрын
Ой, это не жесть ещё. Там дальше вообще караул будет
@neuromancersmith98902 жыл бұрын
Спасибо большое за уроки по Solidity!
@cryp925 Жыл бұрын
сначала видео показалось сложным, но стоило пересмотреть урок один раз, как все встало на свои места)
@IlyaBodrovKrukowski Жыл бұрын
Увы, местами может быть не очень просто из-за особенностей ethereum, но, действительно, через какое-то время обычно понимание приходит - ничего сверх-сложного тут нет
@Bekcoin Жыл бұрын
4 урок вообще чуть не сломал мой бедный мозг)
@shohzodzet Жыл бұрын
Супер круто, спасибо) Совсем новички в программировании наверное вообще офигели от этого урока))
@IlyaBodrovKrukowski Жыл бұрын
Может быть, может быть
@axelvirtus2514 Жыл бұрын
Совсем новички не должны начинать с web3
@mrin0 Жыл бұрын
@@axelvirtus2514, но начали, соре
@loki8705 Жыл бұрын
Да. Тут я сломался)
@Bekcoin Жыл бұрын
@@axelvirtus2514почему это?
@MrSladkov4 ай бұрын
Илья здравствуйте! К "снаряду" - документации легче подходить после ваших видео. Спасибо за труд.
@IlyaBodrovKrukowski4 ай бұрын
@kyotodub6282 жыл бұрын
спасибо вам за краткую , четкую информацию + у вас приятный голос .
@IlyaBodrovKrukowski2 жыл бұрын
@yevheniimoskalenko16242 жыл бұрын
очень интересно) спасибо за урок!
@bars3742 жыл бұрын
спасибо за ваши уроки! вы лучший по solidity в ютубе
@IlyaBodrovKrukowski2 жыл бұрын
@АлександрИноземцев-и4х2 жыл бұрын
Большое спасибо, прекрасные уроки с практикой в видео, очень полезно
@IlyaBodrovKrukowski2 жыл бұрын
@gylyjovpy2 жыл бұрын
Great tutorial, thanks. Waiting for next lessons. Thx!
@nftNez2 жыл бұрын
Спасибо! Очень качественный контент👍
@IlyaBodrovKrukowski2 жыл бұрын
@ДенисЗайков-ы8к2 жыл бұрын
Отлично ! Спасибо автору канала, очень понятно !
@IlyaBodrovKrukowski2 жыл бұрын
@crypto-pro26 Жыл бұрын
Работа с массивами в памяти очень причудливая)
@IlyaBodrovKrukowski Жыл бұрын
Увы, есть такое
@nigma36232 жыл бұрын
как всегда отличный урок
@IlyaBodrovKrukowski2 жыл бұрын
@ly_pass73522 жыл бұрын
огонь
@IlyaBodrovKrukowski2 жыл бұрын
@synchronization6662 жыл бұрын
Thank you!
@404piano2 жыл бұрын
Отлично!
@StanislavGorchakov2 жыл бұрын
в примере про масив должен быть модификатор pure, а не view, так как мы с состояниями там не работаем
@mair92062 жыл бұрын
Очень ждем уроки по Ruby и Rspec
@МихаилРощин-г4ж2 жыл бұрын
и дальше по солидити
@zagamusic50895 ай бұрын
Подскажите пожалуйста,а есть где то допустим задачи которые можно было бы делать и проверять правильность?) Как например на leetCode,только задачи в рамках которых нужно написать смарт контракт)
@IlyaBodrovKrukowski5 ай бұрын
Хм. Точно не уверен, вроде crypto zombies были, но давно их не смотрел. А так даже не подскажу
@alexsoft9992 жыл бұрын
Супер-пуппер подача материала!
@IlyaBodrovKrukowski2 жыл бұрын
@azion2 жыл бұрын
Cупер контент Молодец
@MikhailKuklenkov Жыл бұрын
Приветствую, Илья! Благодарю за записанный урок. Материал очень информативно, лаконично и просто изложен - безусловно ваша заслуга. К слову, в рамках праздной беседы сформировалось два вопроса: 1. Практическое применение bytes? На вскидку не приходит идей, каким образом в bytes может быть организовано хранение информации и какой именно? 2. В JS посредством скобочной записи возможно обратиться к массиву и добавить элемент не увеличивая длину массива: let arr = [1, 2, 3]; arr.length = 3; arr['element'] = 'password'; arr.length = 3; Возможен ли такой вариант в Solidity?
@IlyaBodrovKrukowski Жыл бұрын
Добрый день! Это правильные вопросы 1. Такой информации много. К примеру, любые данные, которые приходят в функцию изначально (calldata) - это всегда bytes, потому что потенциально этих данных может быть очень много. Кроме того, байткод самого контракта - тоже bytes, в сложных случаях с ним работают напрямую (например, в прокси). Также call (вызов по другому адресу) тоже возвращает bytes, про всё это будет далее 2. Проще всего попробовать самостоятельно (это вообще хорошая идея, тк проще запомнятся подобные штуки), но в целом да, так можно делать
@SCEP9X2 жыл бұрын
Продолжай🥺👍🏻
@OpankiDeLegend2 жыл бұрын
12:20 сейчас компилятор ругается на view, надо ставить pure.
@IlyaBodrovKrukowski2 жыл бұрын
Да это просто предупреждение, не ошибка. Но в принципе правильнее pure
@MultiNanoSpeed2 жыл бұрын
спасибо!
@pleb36722 жыл бұрын
Спасибо
@МихаилПономарев-с6с Жыл бұрын
спасибо большое за информативный урок! а если динамический массив или строка хранятся на блокчейне, то как высчитывается газ за из хранение? цена пересчитывается после увеличения кол-ва элементов в массиве, например, после вызова какой-либо ф-и т.к. под него выделяется больше битов?
@IlyaBodrovKrukowski Жыл бұрын
Ну грубо говоря там такая история. Элементы динамического массива размазаны по всему storage, тк номер слота для хранения элемента считается с помощью хэширования. Потом если добавляется новый элемент, надо сделать следующее - обновить длину массива (она тоже в state), посчитать хэш, чтобы понять куда засовывать элемент, положить элемент в слот с этим номером. Вот за все эти операции мы и платим, там в байткоде это довольно чётко видно (про байткод позднее уроки будут)
@МихаилПономарев-с6с Жыл бұрын
понял, спасибо! @@IlyaBodrovKrukowski
@ВалерийСавельев-н2ц2 жыл бұрын
Вопрос по 4 занятию где Вы описывали создание struct. Хочу убедиться что верно понял логику структуры. В 19 строке где создается mapping - в качестве ключа, мне кажется, логичнее было бы использовать uint порядковый номер записи а address поместить в структуру Balance. Тогда если с одного адреса пройдет два платежа они оба сохранятся. А в Вашем варианте я понял так что второй платеж с тем же адресом затрет информацию о первом платеже.
@IlyaBodrovKrukowski2 жыл бұрын
Да, есть такое дело, там про это упоминается. В принципе, для целей демо это не столь важно, но да, можно и иначе это решить. Но просто тогда нужно номер платежа текущий тоже отдельно хранить. А так конечно, я думаю, что суть вы правильно поняли
@Receive_2 жыл бұрын
@@IlyaBodrovKrukowski я правильно понял, что в строках 16 и 19 нужно поменять местами uint и address, тогда таблица будет выглядеть следующим образом -> Основная таблица в которой будет порядковый номер и баланс, а при переходе в строку платежа(как по ссылке) мы получаем новую таблицу, где видим адрес отправителя и данные по платежу?
@Receive_2 жыл бұрын
@@IlyaBodrovKrukowski ничего не затирается. Проверил тестом в хардхэт, как учат в следующем ролике и в ремиксе. Первый платеж сохраняется под нулевым индексом, второй под первым. Слал с одного адреса. Это еще больше запутало в логике(
@glebrokotov29034 ай бұрын
@@Receive_ по умолчанию при первом обращении totalPayments будет равен 0. это будет номером для первого платежа с адреса отправителя. после этого мы инкрементируем totalPayments и это значение сохраняется за пределами функции. Дальше в этой функции мы используем paymentsNum до инкрементирования, чтобы записать его ключом mapping payments (uint) для текущего платежа. Следующий платёж с этого же адреса получит totalPayments равный 1. Ничего не перезатрёт, но стоит держать в уме, что счёт платежей мы начинаем с 0. В данном примере мы имеем в основе ветки разветвления адрес отправителя, а при переходе на уровень ниже mapping с номерами платежей и информацией о платеже. В Вашем же примере в основе будет порядковый номер платежа. В принципе всё равно будет работать, но не так удобно как в примере автора. В примере Ильи мы может отследить множество транзакций высланных с одного адреса.
@ПетрЛипатов-ф9п5 ай бұрын
вопрос насчет функции из урока: - paymentNum определяется до инкремента - позже paymentNum используется для индекса нового Payment Вопрос: paymentNum был определен до инкремента, следственно новый Payment в этом случае не перезатрет крайний платеж? function pay(string memory message) public payable { uint paymentNum = balances[msg.sender].totalPayments; balances[msg.sender].totalPayments++; Payment memory newPayment = Payment( msg.value, block.timestamp, msg.sender, message ); balances[msg.sender].payments[paymentNum] = newPayment; }
@IlyaBodrovKrukowski5 ай бұрын
Нет, такого быть не должно, ну можно попробовать в ремиксе это проделать. Она будет считаться с нуля, и дальше
@glebrokotov29034 ай бұрын
по умолчанию при первом обращении totalPayments будет равен 0. это будет номером для первого платежа с адреса отправителя. после этого мы инкрементируем totalPayments и это значение сохраняется за пределами функции. Дальше в этой функции мы используем paymentsNum до инкрементирования, чтобы записать его ключом mapping payments (uint) для текущего платежа. Следующий платёж с этого же адреса получит totalPayments равный 1. Ничего не перезатрёт, но стоит держать в уме, что счёт платежей мы начинаем с 0.
@ЕгорВоробьев-щ3ы4 ай бұрын
Здравствуйте! Спасибо за ваши уроки! На русскоязычном ютубе мало таких подробных уроков про блокчейн и Ethereum. Апдейты я смотрю. Но есть один вопрос, почему в типе bytes можно получать длину строки и читать элементы по индексу, а в string нельзя?
@IlyaBodrovKrukowski4 ай бұрын
Потому что это сложно. У меня на канале есть видео про кодировки, можно глянуть kzbin.info/www/bejne/e2bYgpifoJWnmsU Суть в том, что если это "просто байты", то померять длину не проблема. Но если это буквы, которые кодируются байтами, то у разных букв может быть разное кол-во байтов (см utf-8), и это просто сложнее всё учесть
@karliam_v Жыл бұрын
Подскажите, пожалуйста, вот функция getPayment вернула tuple. Но такого типа данных нет в Solidity. Я поглядел в документации и чет его не нашел. Это что такое?
@IlyaBodrovKrukowski Жыл бұрын
Не, это нормально. Функция такое может вернуть вполне, это просто кортеж из нескольких значений. В круглых скобках можно писать. Можно ещё раз (bool ok, bytes memory resp) = addr.call() Это тоже кортеж
@WithoutNickname6662 жыл бұрын
Есть вопрос :) 21:45 Почему мы пишем balances[msg.sender].totalPayments++; Ведь переменная totalPayments относится к структуре Balance, а обращаемся мы к ней почему-то через mapping balances. Я почему-то ожидал увидеть запись на подобие balances[msg.sender] = Balance.totalPayments++; (Понимаю что это совсем не правильно, просто смысл что мы обращаемся именно через структуру Balance к ее атрибутам.
@IlyaBodrovKrukowski2 жыл бұрын
Ну потому что ведь там лежит баланс конкретного аккаунта, поэтому так и пишем
@glebrokotov29034 ай бұрын
В примере Ильи мы обращаемся к полю структуры Balance и изменяем его значение на +1. То есть по простому просто проводим операции с значением totalPayments из структуры Balance, которая соответствует адресу msg.sender. В Вашем примере, если убрать переменные и оставить их только их типы мы получим adress = uint++, что очевидно имеет разные сущности и просто не может работать логически.
@ЯреальныйВалентиныч5 ай бұрын
Здравствуйте! Очень интересные уроки! Я четко поставил цель стать разработчиком смарт контрактов , так как я тесно работаю со сферой криптовалюты , но к сожалению у меня никогда не было опыта с it сферой , и поэтому я понимаю только часть информации из уроков, к примеру понимаю работу конкретной команды, но как только вы пишете строчку, а то и две понимание улетучивается, что порекомендуйте сделать?
@IlyaBodrovKrukowski5 ай бұрын
Наверное, попробовать немного изучить любой "классический" язык - лучше всего python или ruby (про ruby у меня есть уроки). Просто по ним очень много материала и учебников, можно разные примеры смотреть. Потом и soliidty будет проще. Ну, либо просто привыкать в solidity, писать совсем простые контракты (буквально в несколько строк), пробовать их как-то изменять по минимуму, смотреть, что происходит, привыкать к синтаксису
@ЯреальныйВалентиныч5 ай бұрын
@@IlyaBodrovKrukowski большое спасибо, отвечать на все комментарии даже на видео такой давности это показатель того, что у вас масштабная личность, снова благодарю вас за ваш труд! 🤝
@IlyaBodrovKrukowski5 ай бұрын
@@ЯреальныйВалентиныч Благодарю за отзыв, стараюсь
@markersin65842 жыл бұрын
Илья, объясните пожалуйста как интерпретировать 32 строку,где речь идёт про struct, balances[msg.sender].payments [paymentNum]=newPayment.Куда ложится newPayment,в качестве значения в balances или в payments?Вы говорите,что новый платеж записывается в balances,тогда как он попадает в payments,ведь мы потом оттуда считываем поля по индексу.Проясните пожалуйста как правильно понимать эту строку
@IlyaBodrovKrukowski2 жыл бұрын
В мэппинге balanaces находим структуру данных и для неё в поле payments кладём новое значение newPayment, после чего всё это дело помещаем в блокчейн
@ОлегБудин-к3ы2 жыл бұрын
Тип под капотом currentStatus -- uint8. В enum можно не больше 256 элементов, или автоматом станет uint16? И еще по 24:00 вопрос. Постинкремент работает не так, как в С++? его нельзя сразу в 22й строке поставить?
@IlyaBodrovKrukowski2 жыл бұрын
Enums cannot have more than 256 members. - это из доков, так что нет По второму моменту - тут вам проще проверить самостоятельно, как это будет в разных случаях работать, да и в целом закрепится лучше
@Imperial_Raccoon Жыл бұрын
Блин, классно рассказываешь, приятно слушать, но башка кипит, т.к сложнааа.
@IlyaBodrovKrukowski Жыл бұрын
Потом будет проще
@АлександрШевченко-ф4н5и2 жыл бұрын
Почему мы когда хотим создать массив который будет храниться в памяти должны писать модификатор мемори? Ведь когда функция sampleMemory закончится, она и так должна удалить все переменные и т.д. Также работает область видимости, разве не так?
@IlyaBodrovKrukowski2 жыл бұрын
Нет. Попробуйте создать массив без memory - у вас сразу будет ругаться компилятор. Для данных типа reference нужно указывать место хранения в Solidity
@АлександрШевченко-ф4н5и2 жыл бұрын
@@IlyaBodrovKrukowski понял, спасибо
@АлександрШевченко-ф4н5и2 жыл бұрын
@@IlyaBodrovKrukowski кстати, есть возможность провести платную консультацию?)
@IlyaBodrovKrukowski2 жыл бұрын
@@АлександрШевченко-ф4н5и Да, можете у меня на сайте почитать подробности
@БекзодОлимов-я4ц2 жыл бұрын
Здравстуйте, я могу узнать, есть ли какие-то альтернативы методу receive, просто я смотрел проекты смарт контрактов на гитхабе, и там не использовали эту функцию, делали как-то по-другому, у неё есть какие-то недостатки?
@IlyaBodrovKrukowski2 жыл бұрын
Нет, а какие могут быть недостатки? :) Это стандартная функция Solidity. Есть ещё fallback, но там немного про другое. Receive просто принимает деньги
@БекзодОлимов-я4ц2 жыл бұрын
@@IlyaBodrovKrukowski , окей, спасибо, просто почему-то я ее редко встречал
@IlyaBodrovKrukowski2 жыл бұрын
@@БекзодОлимов-я4ц я думаю тут проблема в том, что solidity меняется. насколько я помню, в старых версиях такой функции не было, но теперь уже довольно давно она есть и советую взять на вооружение
@kizik852 жыл бұрын
Отличные уроки! Спасибо Вам!!! Илья, подскажите как Вы в Remix комментируете блок кода? Какое сочетание клавиш?
@IlyaBodrovKrukowski2 жыл бұрын
Ctrl + /
@kizik852 жыл бұрын
@@IlyaBodrovKrukowski пробовал, у меня сочетание клавиш Ctrl + / не даёт такой результат. разные комбинации пробовал и с левым Ctrl и c правым. Поэтому и спрашиваю.
@IlyaBodrovKrukowski2 жыл бұрын
@@kizik85 Странно, должно работать. Может быть, на других ОС иначе? Либо это просто баг, можно почитать issues тут github.com/ethereum/remix-desktop/issues
@kizik852 жыл бұрын
@@IlyaBodrovKrukowski Илья, спасибо Вам. Работает при нажатии "/" кнопки рядом Shift и не работает с кнопкой "/" что на цифровой клавиатуре(Ctrl + /). Разобрался. Спасибо Вам за уроки!!! Смотрю и записываю в тетрадку. Очень круто объясняете, у Вас талант!!!
@IlyaBodrovKrukowski2 жыл бұрын
@@kizik85 Аа, такое может быть, если NumLock находится в определённом положении (не помню точно, то ли включён, то ли выключен)
@trueman84132 жыл бұрын
Привет, подскажи, пожалуйста, у тебя в описании ссылка на буткемп по солидити, если я React разработчик с 2х летним опытом, смогу ли я после буткемпа устроиться Solidity разрабом? будет ли хватать навыков и опыта? или твоих видосиков достаточно для этого))
@IlyaBodrovKrukowski2 жыл бұрын
В курсе значительно больше информации. То есть её можно найти и изучить самому, конечно, просто так она уже все сгруппирована. Ну, и плюс семинары/стримы постоянно. А так - да, конечно, у нас студенты уже активно ходят по собеседованиям, в принципе, вполне успешно
@trueman84132 жыл бұрын
@@IlyaBodrovKrukowski понял, спасибо большое за быстрый ответ)
@IlyaBodrovKrukowski2 жыл бұрын
@@trueman8413
@gjanimationstudio23252 жыл бұрын
поставил 350 ый лайк
@IlyaBodrovKrukowski2 жыл бұрын
благодарю вас, приятно, что моя работа оказалась полезна стольким зрителям
@sagitov2 жыл бұрын
15:30 Мы с пацанами в бане
@IlyaBodrovKrukowski2 жыл бұрын
@Receive_ Жыл бұрын
Очень важный вопрос! Почему если я хочу создать временную переменную типа массив в функции и присвоить ему значение в этой же строке, remix позволит создать только 8ми битный, фиксированной длины массив - uint8[4] memory y = [0, 1, 2, 3];? Но при этом я могу создать временную переменную типа динамический 256 бит массив, как в вашем примере, но без лишних записей - uint[] memory y; и переменную типа фиксированный массив без присвоения ему значений в этой же строке, но с возможностью добавить в следующих, как в вашем примере - uint[10] memory y; Только в этих случаях в параметре returns необходимо указывать именно тот тип, которому принадлежит временная переменная.
@IlyaBodrovKrukowski Жыл бұрын
Динамические массивы нельзя создавать в памяти, только в storage. Это из-за особенностей работы памяти, про неё есть информация далее
@Receive_ Жыл бұрын
@@IlyaBodrovKrukowski Спасибо за ответ. Подскажите пожалуйста по основному вопросу. Почему массив фиксированной длины с присвоением значений в той же строчке, можно создать только типа unit8. Пример: unit8[4] memory y = [0, 1, 2, 3] - можно, а unit[4] memory y = [0, 1, 2, 3] - нельзя. Но при этом unit[4] memory y; y[1] = 1; y[2] = 2; y[3] = 3; Можно. Вернёт функция одно и то же значение, но типы данных будут разные.
@IlyaBodrovKrukowski Жыл бұрын
@@Receive_ Не понял вопроса, всё должно работать. Лучше в чате спрашивать, там проще куски кода кидать
@Receive_ Жыл бұрын
@@IlyaBodrovKrukowski Всегда отвечаете и помогаете разобраться. Безусловно самый драгоценный канал на ютубе!
@IlyaBodrovKrukowski Жыл бұрын
@@Receive_
@easypeet53362 жыл бұрын
под конец процентов 40 понятно только
@WithoutNickname6662 жыл бұрын
Илья, спасибо за уроки! Хотелось бы немного внести конструктивной критики в плане подачи материала. Дело в том, что когда мы затрагиваем любую новую тему в Solidity, то мы слишком сильно с первых же минут усложняем их. Например делаем несколько структур в одной, подключаем сюда mapping, и еще разные всякие штуки. Очень сложно из этого вычленить то, что нужно. Поэтому предлагаю сделать маленько по-другому. Когда мы затрагиваем какую-то новую тему, то брать только ее и всё. Например затронули мы структуры. Значит на простом примере без использования других вещей мы смотрим что это, как это записывается, как это считывается, и т.д. И уже в последнюю очередь как это взаимодействует с другими объектами. Ведь когда мы знаем синтаксис (запись, чтение, изменение), то уже и легче разбираться после. А сейчас всё в куче и очень сложно воспринимается. Спасибо!
@IlyaBodrovKrukowski2 жыл бұрын
Что ж, можно и так подходить к вопросу, это правда. Но в общем и целом я тут ориентируюсь на тех, кто уже имеет опыт разработки, пусть и на другом языке. Делать много маленьких уроков на этом канале я не планировал (по каждому типу - тем более), для этого есть курс на отдельной платформе, где всё рассказывается более детально. Примерно такая ситуация
@WithoutNickname6662 жыл бұрын
@@IlyaBodrovKrukowski Понимаю. У меня есть опыт разработки на Пайтоне, однако многие вещи всё равно не понятны. Я всё это к тому, что не нужно прям весь урок посвящать чисто синтаксису. Буквально 1-2 минутки выделить на чистый синтаксис. И тогда уже будет более понятно. Кстати, всё хотел спросить. Очень часто вижу что в структурах одинаково называют структуру и массив. По типу struct Todo{ }...... Todo[ ]. Почему так делают? Разве это не вносит еще большую путаницу что есть что?
@mikhaillobanov97742 жыл бұрын
@@WithoutNickname666 Todo это не имя а тип данных в твоём примере.
@ivanchernenko79582 жыл бұрын
@@WithoutNickname666 жалко питонистов, бедолаги пишут на своем суржике, а потом в простейших вещах в языках со статической типизацией путаются
@Шишкотряс-х2з2 жыл бұрын
@@ivanchernenko7958 ахаххаха
@del7 Жыл бұрын
БреинДит это ты?
@retro7772 жыл бұрын
все это не для новичков.Нихера почти не понял.И не понятно с чего начинать...