Solidity. Смарт контракты и аудит
الذهاب إلى القناة على Telegram
Обучение Solidity. Уроки, аудит, разбор кода и популярных сервисов
إظهار المزيد2 592
المشتركون
لا توجد بيانات24 ساعات
-17 أيام
+430 أيام
أرشيف المشاركات
Немного наблюдений из мира web3
"Привет всем аллергикам! Я с вами!" - именно так хочется начать этот пост, потому что уже несколько дней вместе с адской жарой в 36-37 градусов приходит и сезонная аллергия. Помимо того, что у тебя постоянно забит нос, так еще и фокусирование на информации нет никакого.
Пытаюсь вникнуть в код - и такой "а что такое uint?..", читаю репорты и просто не могу связать А с В. Короче, в следующем году надо планировать отпуск на весь этот сезон.
И пока я не особо воспринимаю информацию, просто хочу поделиться с вами своими наблюдениями по протоколам в web3 и тем, какие знания сейчас больше будут пригождаться.
Вначале пара слов про тестирование смарт контрактов.
Осенью прошлого года я писал, что с развитием Foundry и любовью разработчиков к нему, придет новая профессия - тестировщик. И здесь я имел ввиду не разработчик - тестировщик, а именно отдельную специальность; людей, который будут только лишь писать разнообразные тесты для протоколов: юнит, фазз, инфариант и fv. В некотором роде, я оказался прав.
В компаниях, которые работали над собственным проектом, тесты писали и пишут сами разработчики. Но появились другие компании, тот же Trail of Bits, которые стали предлагать написание тестов, как услугу. Позже к ним присоединились и частные разработчики, которые предлагают нишевое тестирование: инварианты или формальную верификацию.
Открылся проект - Recon - от мощных аудиторов, который предлагает сервис по написанию инвариант тестов вкупе с программами Медуза и Foundry.
Тем не менее, с развитием предлагаемых услуг, я не увидел какого-то ажиотажа со стороны разработчиков к сложным тестам. Они все также остались на юнит и фазз тестах в своей основе.
Или может инварианты и формальная верификации прерогатива крупных протоколов с хорошим финансированием?
Также, большую часть выходящих на конкурсные аудиты протоколов, составляют проекты в сфере DeFi. А в Твиттере в постах разработчиков и безопасников чаще появляются посты на тему расчетов, токеномики и финансовых механизмов.
Я бы сказал, что простые токены или NFT уже не так сильно интересны сообществу, как год-два назад. Многие хотят каким-либо образом "прикрутить" DeFi или даже GameFi к своим протоколам.
P.S. Я за игровой индустрией не очень слежу, поэтому приветствуются комментарии на эту тему.
В DeFi сейчас осваиваются темы интеграций с другими крупными протоколами, типа Uniswap, Lido, Aave, а также базовые механики ликвидаций и стейкинга ликвидности. Реже, когда проекты смотрят на деривативы или опционы.
Будет интересно понаблюдать, как будет развиваться сервисы тестирования с DeFi протоколами, ведь после точечных взломов, когда хакеры подбирали необходимые значения чисел для атаки на протокол, должно появиться что-то для предотвращения таких случаев.
В конкурсных аудитах также есть некоторые обновления.
Если раньше на конкурс выходили более простые протоколы, то сейчас стали появляться все чаще миллионники: то Euler, то MakerDao, то еще пара штук в прошлом году. Да, и более профессиональные протоколы, как Uniswap или Chainlink, облюбовали этот способ аудита.
Только на мой взгляд, это, скорее, не конкурсный аудит, а багбаунти ограниченное по времени. Такие протоколы зачастую прошли не один профессиональный аудит от топовых фирм (Spearbit, ToB, etc), поисправляли все что можно, и теперь хотят собрать массовый фидбек.
Это как еще один тренд, но вход по знаниям и навыкам там на уровне от хорошего мидла, т.е. для новичков это будет чрезмерно сложно.
А что вы замечаете на рынке контрактов и аудитов? Куда, думаете, движется сфера web3?
#trend
Solidity hints. Часть 7
Сегодня поговорим о таком интересном опкоде, как extcodesize и его роли во внешних вызовах. Разберем два пункта из репо:
9. The evm considers a call to non-existing contract to always succeed, so there is a check of extcodesize > 0 when making an external call. But call, staticcall, delegatecall, send, transfer do not include this check
11. extcodesize > 0 check is skipped by the compiler if the function call expects return data. the ABI decoder will catch the case of a non-existing contract Because such calls are followed up by abi decoding the return data, which has a check for returndatasize is being at least a non-zero number. So for empty contracts, they would always revert in the end.
Для начала необходимо разобраться вообще за что отвечает excodesize.
excodesize - это специальный опкод EVM, который проверяет, есть ли код у данного адреса или нет. Если код есть, то данный адрес является контрактом.
P.S. Далее прошу более опытных читателей канала поправить меня, если будут неточности.
Когда мы используем низкоуровневые вызовы, такие как call(), delegatecall(), send() и transfer() проверка на существование контракта опускается, т.е. excodesize не исполняется где-то в середине вызова, и EVM считает, что этот вызов по-любому успешный.
При этом, когда мы дополняем такие вызовы проверкой на успешность (bool success,), мы получаем специальные методы, которые могут дать понять, что вызов обвалился на каком-либо этапе. Делается это с помощью другого опкода returndatasize, который отвечает за возвращаемые данные после вызова.
Нужно отметить, что разработчики не должны полагаться на excodesize для проверки на существование контракта, так как она может легко обойтись хакером. Например, у нас есть два контракта:
contract Victim {
bool public tricked;
function isContract(address _addToEval) public view returns(bool){
// The code is only stored at the end of the
// constructor execution.
//Thus extcodesize returns 0 for contracts in construction
uint32 size;
assembly {
size := extcodesize(_addToEval)
}
return (size > 0);
}
function supposedToBeProtected() external {
require(!isContract(msg.sender), "caller is not an EOA");
tricked = true;
}
}
contract Attacker {
bool public successfulAttack;
Victim v;
constructor(address _v) {
v = Victim(_v);
// address(this) doesn't have code, yet. Thus, it will bypass
//isContract() check
v.supposedToBeProtected();
//tricked was set to true on the above execution
successfulAttack = v.tricked();
}
}
Функцию supposedToBeProtected() должен вызывать только пользовательский адрес. Но с помощью конструктора хакер может обойти эту проверку.
Если вдруг вы не знали, то при создании контракта используются два набора кода: код для деплоя, который и идет в самом конструкторе, и код контракта. Получается, что вызов в контракт жертвы пойдет из кода для деплоя, и успешно пройдет проверку.
Именно поэтому не стоит без предварительного исследования и поиска по базам с уязвимостями использовать опкоды, с которыми вы мало знакомы.
#excodesizeSolidity hints. Часть 6
О, сегодня будет один интересный пункт, который порой упускают из виду даже опытные разработчики, и связан он с темой низкоуровневого вызова call.
8. call bypasses function existence check, type checking and argument packing
Вызов call пропускает проверку существования функции, проверку типа данных и упаковку аргументов. Что это означает?
Вообще, call - это такая "зараза", которую нужно контролировать вдоль и поперек. Уже не первый десяток уязвимостей было найдено, только потому что разработчики забыли сделать какую-либо проверку после вызова этого опкода.
Отправь его и он уйдет без вопросов...
Даже в самой документации есть специальная сноска по этому поводу:
The low-level functions call, delegatecall and staticcall return true as their first return value if the account called is non-existent, as part of the design of the EVM. Account existence must be checked prior to calling if needed.
Грубо говоря, что низкоуровневые языки всегда будут возвращать true как первое возвратное значение, даже если аккаунт, на который идет вызов, не существует. Так заложено в EVM и проверка на существование аккаунта ложится на плечи разработчика.
Также и с функциями. Посмотрите на два контракта:
contract Caller {
function testCallFoo(address payable _addr) public payable {
(bool success, bytes memory data) = _addr.call{
value: msg.value,
gas: 5000
}(abi.encodeWithSignature("foo(string,uint256)", "call foo", 123));
}
function testCallDoesNotExist(address payable _addr) public payable {
(bool success, bytes memory data) = _addr.call{value: msg.value}(
abi.encodeWithSignature("doesNotExist()")
);
}
}
contract Receiver {
event Received(address caller, uint256 amount, string message);
fallback() external payable {
emit Received(msg.sender, msg.value, "Fallback was called");
}
function foo(string memory _message, uint256 _x)
public
payable
returns (uint256)
{
emit Received(msg.sender, msg.value, _message);
return _x + 1;
}
}
Из контракта caller мы делаем вызовы во второй контракт. И что самое удивительное, обе функции сработают с call, учитывая то, что в receiver нет функции doesNotExist(), которую мы пытаемся вызвать через testCallDoesNotExist().
А если убрать fallback(), куда падает вызов несуществующих функций, наш call все равно не откатится.
Более того, call все равно как вы упаковываете типы данных. Это также проблема разработчиков правильно передавать данные в другой контракт или функцию.
Кстати, для этих целей есть abi.encodeCall - который практически тоже самое, что и abi.encode, но только добавляет проверку типов данных на соответствие функции, которая была указана в аргументах. Результат кодирования схож с abi.encodeWithSelector.
Подводя итоги можно сказать сказать общепринятые правила в использовании call:
1. Всегда проверять успешность возвращаемого значения;
2. Знать наверняка или самому контролировать вопрос существования адреса, куда отправляется вызов;
3. Проверять правильность кодирования данных при отправке;
Это если и не избавит вас на 100% от ошибок и проблем с call вызовов, но значительно сократить их шанс.
Будьте аккуратны с низкоуровневыми вызовами!
#callSolidity hints. Часть 5
Спасибо всем, кто пережил неделю продаж и остался на канале, понимаю что для многих это действительно испытание. Мы возвращаемся в рабочий ритм и потихоньку продолжаем разбирать репо от Chinmaya, который делал свои заметки по Solidity во время своего обучения. И следующий пункт:
6. enum types are not part of the ABI, they are just a solidity abstraction
Тип данных enum не является частью ABI, это всего лишь абстракция Solidity.
Действительно, enum - это один из способов создания пользовательского типа данных в Solidity. Они явно преобразуются во все целочисленные типы и из них. При этом во время выполнения преобразования проверяется, что значение лежит внутри диапазона перечисления, и в противном случае возникает ошибка Panic.
Enum требуют наличия хотя бы одного значения и не могут иметь более 256 значений, что фактически означает равенство к типу данных uint8 (так он и будет отображаться в ABI).
Когда мы создаем enum, например:
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices choice;
а затем хотим получить значение choice:
function getChoice() public view returns (ActionChoices) {
return choice;
}
в некотором роде, функция будет выглядеть как
getChoice() returns (uint8)
Значения в enum начинаются с 0, и если не установлено какое-либо другое значение, то функция или запрос к переменной вернем именно ноль. За этим необходимо следить в функциях, где от условия enum зависит ход ее исполнения.
7. Delete keyword is simply a reassignment of elements to their default values (ie.zero)
Ключевой метод delete в функциях фактически обнуляет значение, а не удаляет его.
При изучении Solidity нам часто говорили, что тут нельзя создать ни один тип данных с пустым или несуществующим значением. Например:
- boolean: false
- string: ""
- int / uint / enum: 0
- address: 0x0000000000000000000000000000000000000000 (or address(0))
Не помню, чтобы я встречал какие-либо критические уязвимости в последнее время, связанные с этим пунктом, так что, думаю, этот пункт можно просто запомнить.
#enum #default⚡️⚡️⚡️ Менее 4 часов до закрытия продаж! ⚡️⚡️⚡️
Последнее напоминание про курс и закрытие продаж через 4 часа.
Ровно в полночь будут удалены посты и реквизиты для оплаты, а уже завтра будет выложен первый урок!
Успейте занять свое место!
Старт 1 июля!
#курс
⚡️⚡️⚡️ Менее 12 часов до закрытия продаж! ⚡️⚡️⚡️
Сегодня последний день продаж доступа на летний модуль курса. Если опоздаете, то придется ждать следующего потока в следующем году!
Напомню, что данный модуль направлен на практику с кодом и написание смарт контрактов. Вы познакомитесь с популярными паттернами и стандартами, которые играют определяющую роль во многих протоколах.
У нас уже набралась рекодно большая группа учеников, поэтому с понедельника, с началом курса, продаж не будет совсем!
Успейте занять свое место!
Программа модуля Реквизиты для оплаты
Старт 1 июля!
#курс
Осталось менее 48 часов
Для записи на курс осталось менее 48 часов! Меньше двух дней, чтобы принять решение и открыть для себя мир разработки смарт контрактов.
На следующей неделе, уже с понедельника, стартует обучение на летнем модуле нашего курса.
За один месяц вы сможете прокачать свои навыки Solidity разработчика, как если бы обучались сами несколько месяцев!
Это будет самая интенсивная и продолжительная группа, направленная именно на практику с кодом и сопутствующими программами.
Конечно, всю информацию можно найти и в сети на профильных порталах, но здесь она собрана и организована так, чтобы ученики не бросали обучение после первых трудностей. Вы всегда сможете задать вопрос в чате курса или мне в личные сообщения и разобраться с проблемой.
Если вы хотели попробовать что-то новое этим летом, пусть это будет летний модуль курса!
Программа модуля. Реквизиты для оплаты
Старт 1 июля.
Продажи только до ночи воскресенья!
#курс
На сколько будет доступ к каналу и материалам?
Забыл вчера осветить этот вопрос, а он оказался достаточно популярным.
Как мне объяснил один из учеников, на некоторых других курсах, что он проходил, доступ к материалам был ограничен. Порой это был всего один месяц после завершения модуля, чаще - 3-6 месяцев. И если ты не успевал, то все - жди следующего запуска и покупай заново.
Ну, и, конечно, понятно волнение многих: "А что будет, если я не успею пройти модуль вместе со всеми? У меня же еще работа (учеба, дом, семья и т.д.). Могу ли в своем темпе проходить?".
Именно поэтому отвечаю на все эти вопросы в одном отдельном посте.
Канал и чат остаются с вами навсегда. Еще ни один из каналов курса не был удален, и это могут подтвердить ученики самого первого модуля, который проводился в июле прошлого года.
Даже если не будете успевать проходить уроки вместе со всеми, обратная связь и ответы в чатах не прекратятся после завершения курса. Вы всегда сможете задать вопрос мне в личку или другим участникам.
Кроме того, практикумы можно будет сдавать до Нового года. Поэтому вы можете проходить модуль в своем темпе и сдать работу по завершению.
Надеюсь, теперь вам будет проще решиться для себя попробовать этот модуль.
Программа курса Условия оплаты
Старт уже в понедельник!
#курс
Обучение в потоке
Хочу еще поделиться с вами некоторыми неожиданными открытиями, которые я получил, проведя уже 5 модулей - 4 от первого потока и 1 весенний.
Я получал много сообщений в личку, где ученики делились своими переживаниями и достижениями, задавали вопросы и интересовались "а что дальше?". Каждая история ученика - это небольшая борьба: за новые знания, против лени, за крутую работу и необычные перемены в жизни.
Из их обратной связи мне стало понятно, почему многие так любят обучение в группах и на разных курсах. Интересно, найдете ли вы для себя что-то:
1. "Сроки обучения не бесконечны." - мое первое открытие из этой серии. Действительно, когда мы учимся сами по видео на ютуб или задействуем какой-никакой роадмап, мы понятия не имеем, сколько времени этой займет: месяц или полгода. В наших представлениях учеба является каким-то бесконечным процессом.
А на курсе же мы точно знаем, что, например, через 8 недель это закончится. И уже легче планировать свое время и нагрузку.
2. "Внимание на вопросы от других учеников". От нескольких учеников я получал вопросы, где они просили рассказать подробнее о том или ином моменте из урока, который они как бы поняли, но позже прочитали вопрос от другого ученика в чате и "зависли". Другими словами, вопросы в чате помогают как самим задающим его, так и остальным участникам обратить внимание на некоторые нюансы языка и разработки.
3. "Мотивация быть в актуальных уроках". Для небольшого количества учеников играла роль небольшая конкуренция на модуле. В том плане, что если ты немного отстал от группы и затем увидел вопрос по актуальному уроку, то был заряд мотивации догнать остальных и идти в ногу.
4. "Профессиональное сообщество". Для многих играло значительную роль, что все они были на одном уровне в изучении Solidity и могли задавать вопросы друг другу. Никто не отвечал "свысока или снисходительно" и каждый для себя находил поддержку в группе.
5. "Структура и экономия времени!". Также для большинства учеников сыграло ключевую роль структурирование информации; многие говорили, что покупают курс только поэтому. Они не хотели сами составлять себе программу, искать информацию по темам и понятия не имели, как практиковаться с кодом. "Зачем я буду тратить половину времени на поиск, когда тут уже все сделано за меня?" - железный аргумент!
Здорово, что у нас получилось собрать столько учеников и пройти этот путь вместе!
У вас все еще есть время присоединиться к потоку!
Программа курса Условия оплаты
Старт уже 1 июля!
#курс
Первые ученики уже на канале!
Если вы только пришли с работы, то пост для вас! Сегодня старт продаж летнего модуля нашего курса!
26 самых первых учеников уже канале!
Только сейчас вы можете купить сразу оба модуля, так как, начиная с третьего, доступ будет возможен только для текущих учеников. Программа пойдет дальше и догнать остальных будет уже сложно!
Вы получите доступ к закрытым урокам обоих каналов и сможете проходить их в удобное для себя время. Каналы не будут удаляться и все уроки останутся с вами.
Продажи открыты! Успейте занять свое место!
Программа курса.
Условия оплаты в посте выше.
Старт 1 июля!
#курс
🥳🥳🥳 Открытие продаж курса: Практический летний модуль 🥳🥳🥳
55 учеников прошли 1 модуль второго потока курса "Разработчик смарт контрактов на языке Solidity"! 25 уроков с дополнительными материалами и заданиями, 2 практикума для тренировки навыков и 52 финальных вопроса для проверки: все это помогло ученикам начать не простой путь в мир разработки смарт контрактов!
Теперь самое время научиться работать с полученными знаниями и попрактиковаться с кодом более профессионально! Весь октябрь будет построен вокруг интенсивной работы с кодом: чтение, написание и проверка.
Готовы? Присоединяйтесь!
Сегодня я открываю продажи и начинаю добавлять участников в закрытый Телеграм канал.
Итак, как пройти запись и попасть на канал:
1. Оплачиваем курс по реквизитам ниже.
2. Скидываем мне в личные сообщения @zaevlad чек об оплате или хеш транзакции;
3. После этого я добавляю Вас в закрытый канал модуля.
Продажи будут открыты до конца этой недели. Потом на второй модуль будет не попасть!
Реквизиты для оплаты:
1. Перевод на карту:
4276520014513846 Владилен Александрович З
2. Перевод на криптокошелек: 0x331d8654Ff5c314E2baDAAfA83Fdf635650a9E59 . Переводы необходимо делать в сети Polygon, в криптовалютах: USDT / USDC.
Цена за летний модуль: 5000 рублей или 60 USDT / USDC;
Цена для учеников, которые уже ранее покупали курс и хотели бы перепройти его: 2000 рублей или 25 USDT / USDC;
Цена при покупке 1 и 2 модулей: 8000 рублей или 90 USDT / USDC;
Последний раз, когда можно будет купить первый модуль в этом году.
P.S. По всем вопросам можете писать в чат или личные сообщения.
Программа курса.
Старт 1 июля!
#курсПоследний модуль для начинающих в этом году
Уже завтра стартуют продажи летнего практического модуля, рассчитанного на 8 недель. А пока хотел бы еще раз ответить на вопросы, которые мне задавали в личных сообщениях и чатах.
1. Будет ли еще в этом году запуск курса с самого начала?
Нет. Сейчас пройдет летный модуль, потом в сентябре будет последний 3 модуль для продолжающих обучение (с темами про подписи, прокси, работу с памятью и assembly), и на этом курс для начинающих в этом году будет закрыт. Следующий поток только в 2025 году.
2. Можно ли будет позже купить один из модулей?
Также нет. По аналогии с прошлым потоком, модули можно покупать только в период продаж курса.
3. В каком формате идут уроки? Есть ли видео?
Уроки идут в формате текстовых постов с дополнительными материалами (где могут быть видео) и практическими заданиями. В данном модуле, помимо заданий в уроках, есть два практикума, которые вы можете сдать на проверку. Лучший пример уроков можно найти на канале в цикле обучающих постов по Foundry - https://t.me/solidityset/962
4. Есть ли скидки для тех, кто хочет перепройти модуль?
Да, если вы уже ранее покупали 1 - 4 модули, то сейчас цена для вас составит 2000 рублей или 25 USDT
5. Можно ли будет докупить и 1-й модуль вместе с текущим?
Да, в этом случае, цена составит 8000 рублей или 90 usdt.
6. Останется ли канал и чат после завершения курса?
Да, и канал, и чат остаются. Все вопросы можно будет задавать и после завершения модуля.
7. Сколько времени нужно будет уделять урокам?
Этот модуль является практическим. Вам нужно будет выделять по 2-3 часа в день на изучение материалов и выполнение практических заданий.
8. Будет ли роадмап по завершению курса?
Да, я составлю план для вашего дальнейшего обучения в виде роадмапа, где подскажу какие темы необходимо еще изучить.
Если есть еще вопрос, без стеснения задавайте их в чате или мне в личные сообщения!
Старт продаж уже завтра!
Программа курса
#курс
А есть ли интенсивы для мидлов и сеньоров?
Тут на днях гуглил какие-нибудь обучающие программы для продвинутых разработчиков и аудиторов, и обнаружил, что их просто нет. Или я их не нашел?
За весь период своего обучения я погружался во множество различных тем web3 и аудита: от простых CTF до расчетов в DeFi протоколах. Ну, т.е. я хочу сказать, что много знаний уже есть на более-менее базовом уровне. Но вот мне потребовалось на выходных найти информацию по работе с Gnosis Safe: подключение, нюансы безопасности, общая архитектура протокола. И в большинстве статей поисковой выдачи было что-то типа: "Первые упоминания о гречке датированы 8 веком до нашей эры...". Пришлось копаться в официальных доках.
И вот так бывает довольно часто, вместо того, чтобы купить интенсив, в котором разложена информация от и до, с возможностью задать вопрос, я сам гуглю инфу по разным ресурсам и собираю все "по крупицам".
А ведь сколько пользы было бы, если бы зарубежные компании выпускали небольшие курсы по определенным темам (например, как RareSkills). Вот мне было бы интересно узнать:
1. Как работает Gnosis Safe;
2. Как подключать OpenSea;
3. Тики Uniswap V3 и хуки Uniswap V4;
4. Абстрактные аккаунты и их безопасность;
5. Особенности деплоя контрактов на разные L2 сети;
6. Безопасные ликвидации в DeFi протоколах;
7. Что такое блобы и их практическое применение сегодня;
и еще много других нишевых тем с разбором документации, кода и вопросов безопасности.
С одной стороны, крутым разработчикам и аудиторам нафиг это не надо записывать интенсивы, но что насчет компаний, которые проводят стримы и обучающие сессии, те же RareSkills, Alchemy, Updraft?
В общем, если вы знаете какие-нибудь ресурсы, где проводятся нишевые обучающие программы, поделитесь в комментариях.
А я пошел дальше работать над предстоящим модулем, старт которого уже на следующей неделе!
#обучение
Чем отличается джун от мидла?
Несколько раз этот вопрос был задан в чате в контексте того, что вакансий для джунов сейчас мало и берут, в основном, только мидлов и сеньоров. Так как же стать тем самым мидлом без опыта работы?!
На одной из моих старух работ в студии, у нас была ходила типа поговорка: "Джун знает, мидл практикует, сеньор знает, где погуглить". Думаю, она и сейчас не плохо отражает суть индустрии.
Как я сейчас вижу в вакансиях, для мидлов и джунов практически схожие требования: знание Solidity, понимание работы EVM, умение писать тесты, способность работать с современными стандартами EIP, некоторые знания в безопасности смарт контрактов, ну, и может еще в некоторых случаях знание js, react - для подключения фронта.
На собеседовании вопросы будут задавать практически идентичные для обоих кандидатов, но джун "посыпется", когда попросят показать портфолио / реализованные проекты, в общем любой написанный вами код.
В некотором роде, эталоном хорошего разработчика можно считать его GitHub профиль и загруженные туда проекты.
Вы можете начать наполнять его с самого начала своего обучения. Это не только будет отличным бонусом к прохождению собеседования, но хорошей практикой работы с Git (а это чаще всего, также является одним из требований на работу).
Что можно сохранять на начальном уровне обучения?
1. Практика с функциями и типами данных. Это просто, но это покажет, что вы серьезно подходили к своему обучению. На первом модуле курса было два практикума, и во втором были упражнения со вложенными маппингами и структурами. Он может стать прекрасным примером того, что вы умеете работать со сложными типами данных.
2. Ваш первый токен или nft. Написали токен? Создайте файл "ERC20 practice" и тоже загрузите на Git.
3. По сути, изучая каждый новый ERC (подписи, vaults, прокси, и т.д.) вы можете создавать практический проект. Не волнуйтесь за качество своего кода. Так или иначе 100% безопасным его вы не сделаете, но при этом обязательно добавляйте комментарии! Это прям очень важно!
4. Когда вы изучите базис, то можете глянуть этот пост, где я предлагаю несколько проектов для практики: https://t.me/solidityset/1112 Каждый из них покажет потенциальному работодателю ваши знания и навыки в программировании. А если еще к ним будут приложены хотя бы простые тесты - это сильно повысит шансы на получение работы.
На текущем модуле мы делаем акцент именно на практику. Если вы будете действительно выполнять каждое задание и практикумы, то в итоге в вашем GitHub может появиться более 14 практических проектов! И это за два месяца!
Работы будет очень много! Это будет серьезная прокачка навыков за лето!
Старт уже 1 июля!
#курс
Проблемы, когда пытаешься учиться сам
Пару месяцев назад, когда я начал на канале разбирать Uniswap V2, у меня появилось дикое желание углубиться в DeFi системы: разобрать их механику, принципы начисления процентов и другие математические операции, я столкнулся с той же проблемой, с какой сталкивался в самом начале своего обучения языку Solidity.
А именно, нет достаточно хорошей структурированной информации по defi протоколам. Такой, ну чтобы, постепенно изучаешь один протокол, переходишь к следующему. Когда идет от простого к сложному, с достаточным количеством объяснений.
Есть куча отдельных статей (спасибо RareSkills!), но собирать все вместе и обрабатывать бывает очень сложно. Я смотрел Compound, а потом такой: "Ну, глянем деривативы DyDx"... И все... И уже собираешь по кусочкам посты из разных уголков сети.
P.S. Если знаете вот прям хорошие статьи разборы по DyDx, Lido, GMX, Renzo, Balancer и других, буду признателен, если поделитесь в комментариях.
Или другой пример, вот изучил ты Uniswap V2 и что дальше лучше смотреть: перейти на Uniswap V3 или посмотреть более простой Balancer V2?
В общем, поиск и структурирование информации порой занимает больше времени, чем само обучение.
Изначально я и запускал курс по модулям, чтобы структурировать и разложить информацию от простого к более сложному для начинающих разработчиков. Даже, если вы решите сами заниматься, то можно спокойно использовать темы уроков, как пошаговый гайд.
Сейчас я могу посмотреть назад и сказать: "Так, вот эта тема мне потребуется, чтобы понять эту область разработки, поэтому ее нужно изучить чуть раньше." И вот так переставляя темы уроков, получился прекрасный модуль, где не будет возникать каши в голове.
Посмотрите, как разложена информация по Foundry на канале. Сначала внимательно изучаем основы программы, потом "то, что она вообще делает", затем простые тесты, и уже в самом конце - инвариант тесты. Начни изучать сразу тесты и, скорее всего, либо забросишь это дело, либо будешь писать их "коряво", не понимая, как можно сделать проще.
Тоже самое и с написание смарт контрактов. Начните с малого и до конца лета получите отличную базу знаний и практики!
Старт курса 1 июля!
#курс
Кто планирует пойти на практический летний модуль? Прошу оставить свой голос (кроме учеников текущего 1 модуля)
Программа летнего практического модуля
Сегодня я рад представить вам программу летнего модуля продолжительностью 8 недель!
Это будет крутой курс направленный прежде всего на практику с кодом и формирование правильных привычек разработки смарт контрактов. Вы узнаете не только про популярные стандарты ERC20, ERC721, ERC4626, но и научитесь сами понимать и разбирать менее изнвестные EIP.
Более того изучите популярные паттерны и сможете использовать их в своих проектах.
Это будет очень интенсивный модуль! Итак, программа практического модуля:
Неделя 1
Урок 1. Подготовка рабочего пространства
Урок 2. Плагины и настройки
Урок 3. Терминал, Node JS, NPM
Урок 4. Работа с GitHub
+ Интенсив с нуля для начинающих
Неделя 2
Урок 5. Стандарт ERC20. Разбор кода и EIP
Урок 6. ERC20 от Open Zeppelin
Урок 7. Свой токен и подключение OZ
Урок 8. ERC20. Особенности и разнообразие
Урок 9. ERC20. Проблемы безопасности
Неделя 3
Урок 10. ERC721. Разбор кода и EIP
Урок 11. ERC721. Использование в проектах
Урок 12. ERC721. Проблемы безопасности
Урок 13. Подключение токенов в свой проект
Неделя 4
Урок 14. Hardhat. Подключение и настройка
Урок 15. Hardhat. Подключение контрактов и чтение тестов
Урок 16. Foundry. Настройка и запуск
Урок 17. Foundry. Тесты
Практикум после 1-й части модуля
Неделя 5
Урок 18. Стандарт ERC4626
Урок 19. Стандарт ERC4907
Урок 20. Стандарт ERC6551
Неделя 6
Урок 21. Голландский аукцион
Урок 22. Multisig и Timelock
Урок 23. Commit/reveal
Урок 24. DAO и governance
Неделя 7
Урок 25. Ролевая система в контрактах
Урок 26. Файловый паттерн
Урок 27. Структуры storage
Урок 28. Селекторы функций и поинтеры
Неделя 8
Урок 29. Defi паттерн: стейкинг
Урок 30. Defi паттерн: ликвидации и займы
Урок 31. Базовая безопасность и аудит
Финальный практикум модуля 2
Стоимость: 5000 рублей или 60 USDT
Стоимость для тех, кто хочет перепройти: 2000 рублей или 25 USDT
Стар продаж: 26 июня
Старт обучения: 1 июля
Ниже будет небольшой опрос, прошу, проголосовать за один из вариантов, чтобы я смог правильно спранировать нагрузку.
#курс
Solidity hints. Часть 4
Идем дальше, и на очереди у нас пункт под номером пять:
5. Before using delegatecall, ensure that storage layout is in same order in both contracts
Используя функцию delegatecall(), убедитесь, что переменные состояния идут в одинаковом порядке.
Еще одна популярная проблема с низкоуровневыми функциями. Возьмем к примеру два контракта:
contract A {
address public sender;
address public owner;
function setAddress(address _contract, address addr) public payable {
(bool success, bytes memory data) = _contract.delegatecall(
abi.encodeWithSignature("setAddress(address)", addr)
);
}
}
contract B {
address public owner;
address public sender;
function setAddress(address addr) public payable {
owner = msg.sender;
}
}
Если вы не помните основную особенность delegatecall(), то напомню, что он "как бы забирает" функцию из другого контракта и выполняет ее в рамках контракта, где он был вызван.
Если мы вызовем функцию setAddress() в контракте А, то и изменение в памяти произойдет в контракте А, а не в контракте В, куда идет вызов.
В данном примере мы видим, что функция setAddress() в контракте В должна обновить переменную owner. Допустим, мы хотим обновить такую же переменную у себя в контракте А.
Сделав вызов функции А::setAddress(), транзакция пройдет успешно, но в А обновится переменная sender, а не owner, как это было запланировано!
Это произошло именно из-за того, что был нарушен порядок переменных в контракте. Поэтому за ним нужно пристально следить. Да и вообще, если не знаете точно "зачем", то использовать delegatecall крайне не безопасно.
Если хотите сами попробовать разобраться в этой проблеме, то рекомендую пройти задачу Ethernaut 16, прекрасный пример, когда низкоуровневая функция может принести проблемы. Да и сама задача приближена к реальному контракту.
#delegatecallSolidity hints. Часть 3
Постепенно выходим из состояния выходного дня и принимается за работу.
Вообще, не смотря на сезон отпусков и желания провести время где-то у моря, уже третий год - лето у меня самый загруженный период. Вот и сейчас на следующие 2,5 месяца у меня следующие планы:
1. Подготовить крутую практическую программу для 2 модуля курса;
2. Запустить 8 недельный курс на все лето;
3. Разобрать 4-5 defi проекта (пока в планах, Uniswap V3, Compound, Euler и DyDx);
4. Вывести на зарубежный рынок свой проект по пре-аудиту протоколов;
5. Закончить соло аудит;
И это еще не учитывая другие планы вне web3. В общем лето будет - ух!
Зато к осени уже будут новые знания и хороший "фундамент" для последующего рабочего года. Вы, кстати, тоже можете начать свое обучение и много преуспеть до следующего сезона.
А пока, возвращаемся к разбору пунктов из репо Chinmaya:
4. Using low level functions to call a contract = handing over control to it
Используя низкоуровневые функции для вызова контракта, вы фактически передаете контроль над исполнение функции другому человеку, который может оказаться злоумышленником.
Это, вероятно, один из самых популярных вопросов базовой безопасности смарт контрактов, который изучают начинающие аудиторы на различных CTF - capture the flag - задачки по взлому контрактов.
Например, следующий код с уязвимостью реентранси демонстрирует эту проблему:
mapping (address => uint) private userBalances;
function withdraw() public {
uint256 bal = userBalances[msg.sender];
require(bal > 0);
(bool sent,) = msg.sender.call{value: bal}("");
require(sent, "Failed to send Ether");
balances[msg.sender] = 0;
}
Есть некий маппинг, где хранятся балансы пользователей, и функция вывода средств с контракта. Мы вызываем низкоуровневый call на msg.sende и передаем всю сумму с баланса.
Отправителем транзакции вполне может оказаться смарт контракт, который "ловит" внешние вызовы в него через функции receive() или fallback(). И уже в них он может реализовать какую-либо хакерскую атаку, например:
fallback() external payable {
if (address(etherStore).balance >= AMOUNT) {
etherStore.withdraw();
}
}
т.е. он "ловит" call функцию, и перенаправляет вызов обратно в контракт для вывода остальных средств. В итоге это приведет к опустошению первого контракта. А следовательно другие пользователи потеряют все свои активы.
Вообще, всегда нужно быть аккуратными с низкоуровневыми вызовами call() и delegatecall(), желательно не давая пользователям контролировать адрес, куда идет вызов.
Там есть и другие проблемы с такими функциями и о них можно почитать в подборке Solodit.xyz или узнать больше на Ютуб каналах, посвященных безопасности.
Будьте аккуратны!
#call #delegatecallКонтракты и паттерны
Уже на следующей неделе я выложу программу летнего практического курса. Видел в чате много вопросов про обучение с нуля и постараюсь придумать, как новички могли бы быстро догнать текущих учеников и продолжить обучение с ними.
А пока пара слов про паттерны в контрактах, которые следует знать разработчику.
Вообще "паттерн", на мой взгляд, это какая общая идея, которую можно использовать во многих проектах. В некотором роде, популярные библиотеки от Open Zeppelin с реализацией токенов ERC20 и ERC721 тоже являются частью вселенной (кто пропел?) паттернами.
Помимо стандартов сложились и другие общие идеи, которые мы наблюдаем в сегодняшних протоколах. И их можно разделить на три основные группы:
1. Архитектурные паттерны;
2. Паттерны кода;
3. DeFi паттерны;
В первую категорию можно отнести:
1. Аукционы: голландский и английский. Там пользователи делают свои ставки, и в зависимости от типа аукциона, цена падает или растет.
2. Multisig - когда для одобрения исполнения какой-либо функции в протоколе требуется подтверждение несколькими пользователями, управляющими данным функционалом.
3. DAO и governance - популярные (де)централизованные системы и управление протоколом через голосование пользователей;
4. Commit / reveal - некая система (например, голосование) основанная на хешировании данных и последующее их подтверждение;
Паттерны кода куда более сложные для разбора и используются в некоторых профессиональных протоколах с какой-либо определенной целью. К ним можно отнести File pattern.
Ну, и популярные ныне DeFi паттерны:
1. Стейкинг - депозит токенов с целью получить выгоду от последующих наград ил выплат;
2. Айрдропы - первоначальная раздача токенов для привлечения внимания к протоколу;
3. Займы и ликвидации - уже традиционный инструмент большинства финансовых протоколов;
4. Свапы и Vaults - обмен токенов;
Сюда также можно включить более сложные системы связанные с опционами и деривативами, но разобраться с ними "в лёгкую" не получится, так как нужно иметь некоторые представления о работе бирж и трейдинга в целом.
Современным разработчикам нужно знать эти паттерны не только чтобы уметь реализовывать сложные системы, но и быстро разбираться в коде протокола, который ему могут предоставить на доработку.
Если вы учитесь самостоятельно, то обратите на этот список и изучите, если что пропустили. Для других - большинство этих тем мы будем разбирать на практическом модуле.
Всем отличной пятницы и приятных выходных!
#patterns
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
