Solidity. Смарт контракты и аудит – Telegram
Solidity. Смарт контракты и аудит
2.62K subscribers
246 photos
7 videos
18 files
547 links
Обучение Solidity. Уроки, аудит, разбор кода и популярных сервисов
Download Telegram
Наглядное изображение древа Меркла.

Сложно в одном посте написать весь его смысл, но, если говорить кратко, то это такой метод хеширования данных для последующей валидации.

При этом, если хоть один символ в каком-либо месте транзакции будет изменен, то функция проверки будет выдавать ошибку.

#древомеркла
Очередной пример работы древа Меркла.

Если, скажем, вам нужно проверить валидность транзакции Т5, то для проверки вам потребуются только 3 дополнительных хеша.

#древомеркла
Забыл еще вчера важную картинку по теме древа Мерка выложить.

Очень важно, чтобы количество транзакций было "2 в степени n", иначе будет выдаваться ошибка.

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

#древомеркла
Урок 14. Низкоуровневые вызовы

Ну, что? Готовы к хардкорным занятиям по Solidity?

За предыдущие 13 уроков мы многое узнали, но то были цветочки в языке, для новичков. Если вы двигались по обучению вместе со мной, то к данному уроку накопили уже некоторую практику и понимание, как работают смарт-контракты.

В последующие две недели мы закончим основное обучение по языку и начнем разбирать уже прицельные темы по разработке смарт-контрактов: как например, создание своего токена, NFT, DAO, DeFi, Dapp и многое другие.

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

Итак, дамы и господа, новый видео урок - Низкоуровневые вызовы
Над ним стоит посидеть пару дней, чтобы точнее понять, о чем там говорится. Эти знания будут применяться очень часто при создании токенов и проведении выплат в рамках смарт-контрактов.

#низкоуровневыевызовы #урок
1🔥1
В данном примере, call служит для отправки денежных средств на другой контракт, который мы указываем в constructor.

Записывается как: contractAddress.call{value: valueVar}(""), где в начале указывается адрес контракта, а valueVar - сумма.

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

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

Как я понял, вообще call чаще всего используется для отправки денег на другой адрес, или же для вызова функций в стороннем контракте.

#call
🔥2
С помощью call мы также можем обращаться к функциям в стороннем контракте, даже к тем, к которым мы не имеем прямого доступа или интерфейса.

Для этого, вместо денежных средств мы должны передать название самой функции в нужном контракте, а также аргументы, которые данная функция принимает.

Делается это при помощи abi.encodeWithSignature("funcNam(type)", arguments), и выглядит так:

otherContract.call{}(abi.encodeWithSignature("funcNam(type)", arguments));

Следует отметить, что в этом случае ответ всегда приходит в виде байтов: bytes memory response. И к этому response мы можем порождать события с emit.

#call #abi #encodewithsignature
🔥21
Если функция в другом контракте возвращает, например строку, то в нашем контракте, при call вызове, мы можем декодировать ответ с помощью abi.decode(response, (string))

#call #abi #decode
🔥2👍1
Помимо abi.encodeWithSignature можно использовать другой метод, если у вас есть доступ к коду другого контракта.

abi.encodeWithSelector(AnotherContract.funcName.selector, _argument)

При этом более универсальной является первая форма.

#call #abi #encodewithselector
🔥1
Delegatecall у меня был один из самых трудных для понимания. Я несколько раз пересматривал урок, копался в документации, искал в иностранных ресурсах описание и сравнение с call. В итоге, для себя сделал небольшое различие.

С "call" мы как бы посылаем вызов из нашего контракта в функцию в другом контракте, там его обрабатываем и присылаем к себе в контракт ответ.

С "delegatecall" мы как бы забираем функцию из другого контракта к себе в контракт, выполняем ее в рамках своего контракта, и затем отдаем функцию обратно. Вроде как, мы "вырываем" функцию из другого контракта, выполняем ее у себя, и возвращаем на место.

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

#delegatecall
1🔥1
Вообще с delegatecall есть несколько нюансов использования, которые достаточны трудны для понимания не только новичков, но опытных разработчиков.

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

Дело в том, что в случае с delegatecall переменные, устанавливаемые в начале контракта, выступают в некоторой роли слотов памяти. И их порядок играет крайне важную роль в корректной работе самого смарт-контракта.

Про это лучше посмотреть в уроке, начиная с 17 минуты, так как текстом это сложно описать.

#delegatecall #hack
👍1🔥1
Планы по дальнейшему обучению

Сегодня день на самостоятельную работу по вчерашнему уроку, поэтому скринов и комментариев на канале нет. Тем не менее, хочу поделиться небольшими планами, как будет проходить дальнейшее обучение Solidity на данном канале.

Итак, на неделе мы заканчиваем уроки по функционалу Solidity. Завтра будет урок про calldata и memory, в пятницу по hardhat tasks и по сути это все.

Я планирую собрать ссылки на уроки в один пост и напомнить про навигацию\поиску по тегам.

С понедельника начнем уже заниматься разборами самих смарт-контрактов. В течение этого времени мы просмотрим стримы про создание токенов (ERC20), NFT (ERC721), разберем паттерны контрактов Timelock, Commit\reveal, MiltySig, DAO, Governance, Proxy и некоторых других.

Думаю это займет еще недели две-три. После этого также будет один объединяющий пост.

Третьим этапом мы будем разбирать безопасность смарт-контрактов. Рассмотрим популярные методы взлома и защиты.

Сколько займет этот период обучение, пока сказать не могу. Вероятнее всего, также недели две-три.

После этого будет еще один объединённый пост по разделу безопасность, а также несколько постов про ресурсы для самостоятельного обучения и npm пакеты, которые пригодятся в работе со смарт-контрактами.

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

Если все пойдет по плану, и эти этапы будут завершены успешно, то к совсем дальнейшим планам я мог бы отнести дополнительное обучение по hardhat и truffle, а также учеба по react js, чтобы можно было создавать полноценные проекты в web3.

После завершения основного обучения через неделю, вы вполне сможете разбираться в коде смарт-контракта и понимать, что делает та или иная функция.

Если же хотите дорасти вместе со мной до мидл разработчика, то буду рад компании на канале!

Также приветствуются комментарии и предложения!
👍5🔥1
Урок 15. Работа с памятью в Solidity

Еще один сложный для понимания урок, который я пересматривал несколько раз.

Для меня лично, проблемы возникли не только с пониманием организации памяти, но и с добавление языка Yul, который я раньше не встречал в своей практике.

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

Видео урок - работа с памятью

К данному уроку можно вернуться в любой момент, так как он просто рассказывает про внутреннюю работу языка Solidity.

И, на данный момент, я встречал в различных видео всего раза два, когда требовалось использовать assembly и вытаскивать из памяти селектор или другие значение. Уверен, это уже знания продвинутого разработчика Solidity.

Я в течение дня все также буду выкладывать скрины и пояснения кода и работы памяти.

#урок #memory #calldata
🔥1
Solidity резервирует 4 слота памяти, которые хранят в себе до 32 байтов, где первые два слота или 64 байта - это некое служебное пространство, оно уже использкется по умолчанию, и мы не будем обращаться к нему напрямую. Следующие 32 байта хранят в себе указатель на свободное место в памяти, который как бы говорит, что с этого момента ты можешь что-то записать в память. Потом идет пустой слот, после которого мы можем записывать свои данные.

Для того, чтобы обращаться к слотам памяти используют Yul (код с assemly в видео).

Чтобы найти значение строки, которое возвращается в bytes32, нужно найти указатель в памяти, а затем вычесть из него предполагаемый размер данных в байтах. Например, строка "test" точно поместится в 32 байта, поэтому код будет выглядеть как на скрине.

#accembly #memory #calldata #yul
🔥1
Массивы с фиксированной длиной хранятся немного иначе, чем строки. Перед указателем будет размещаться последнее значение массива. А чтобы найти другие значение необходимо вычитать по 32 байта. 

#accembly #memory #calldata #yul
🔥1
В случае с вызовом данных нашей функции, в первых 4 байтах находится селектор самой функции.

#accembly #memory #calldata #yul
🔥1
Основное различие calldata от memory заключается в том, что при использовании memory тратится больше газа, так как его можно перезаписывать.

Calldata же является неизменным значением. Другими словами, мы можем использовать calldata в своих функциях, но изменить его значение у нас не получится.

#accembly #memory #calldata #yul
🔥1
Чтобы получить селектор функции, можно использовать следующую функцию. Более того, данный селектор функции можно найти в artifacts/myContract.json в блоке methodIdentifiers.

#memory #calldata #yul
🔥1
Чтобы найти первый элемент массива с фиксированной длинной в calldata, нам необходимо пропустить первые 4 байта, которые содержат селектор функции.

#accembly #memory #calldata #yul
🔥1
Найти строку в calldata немного сложнее. Так как после селектора есть еще 32 байта, после которых начинается информация о строке. Потом еще слот с байтовой длинной самой строки, и только после этого значение строки.

#accembly #memory #calldata #yul
🔥1
Найти строку в calldata немного сложнее. Так как после селектора есть еще 32 байта, после которых начинается информация о строке. Потом еще слот с байтовой длинной самой строки, и только после этого значение строки.

#accembly #memory #calldata #yul
🔥1
Найти массив с динамической длинной в calldata можно так. Сначала в слотах хранится селектор, потом количество элементов в массиве или его длина, затем идет первый элемент нашего массива.

#accembly #memory #calldata #yul
🔥1