ru
Feedback
Solidity. Смарт контракты и аудит

Solidity. Смарт контракты и аудит

Открыть в Telegram

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

Больше
2 592
Подписчики
Нет данных24 часа
-17 дней
+430 день
Архив постов
Как работает Nodelegatecall Вчера закончились продажи курса, а значит мы возвращаемся в рабочую колею. И начнем нашу неделю с разговора о модификаторе nodelegatecall. Модификатор nodelegatecall предотвращает отправку вызовов delegatecall в контракт. Сначала я покажу сам код, а затем мы обсудим, для чего это нужно. Ниже упрощенный модификатор nodelegatecall, изначально созданный в Uniswap V3 для noDelegateCall:
contract NoDelegateCallExample {
    address immutable private originalAddress;

    constructor() {
        originalAddress = address(this);
    }

    modifier noDelegateCall() {
        require(address(this) == originalAddress, "no delegate call");
        _;
    }
}
Address(this) будет меняться в зависимости от среды выполнения, но originalAddress всегда будет адресом кода, использующего nodelegatecall. Поэтому если другой контракт выполнит delegatecall функции с модификатором noDelegateCall, то address(this) не будет равен originalAddress и транзакция откатится. Крайне важно, чтобы original address был неизменяемой переменной, иначе контракт, выполняющий delegatecall, мог бы намеренно поместить в этот слот адрес контракта, использующего NoDelegateCall, и обойти оператор require. Вот, например, как этот модификатор может быть протестирован:
contract NoDelegateCall {
    address immutable private originalAddress;

    constructor() {
        originalAddress = address(this);
    }

    modifier noDelegateCall() {
        require(address(this) == originalAddress, "no delegate call");
        _;
    }
}

contract A is NoDelegateCall {
    uint256 public x;

    function increment() noDelegateCall public {
        x++;
    }
}

contract B {
    uint256 public x; // this variable does not increment

    function tryDelegatecall(address a) external {
        (bool ok, ) = a.delegatecall(
            abi.encodeWithSignature("increment()")
        );// ignore ok
    }
}
Контракт B выполняет delegatecall для A, который использует модификатор nodelegatecall. Хотя транзакция B.tryDelegatecall не откатится, поскольку возвращаемое значение низкоуровневого вызова игнорируется, переменная хранения x не будет увеличена, поскольку транзакция внутри контекста delegatecall вернется. Зачем вообще использовать nodelegatecall? Uniswap V2 - один из самых популярных протоколов DeFi. Он столкнулся с конкуренцией со стороны других проектов, которые копировали его исходный код построчно и продвигали новый продукт как альтернативу Uniswap V2, а иногда и стимулировали пользователей, предоставляя airdrop. Для того чтобы предотвратить это, команда Uniswap лицензировала Uniswap V3 через Business Source License - любой может скопировать код, но он не может использовать его в коммерческих целях до истечения срока действия лицензии в апреле 2023 года. Однако если кто-то захочет сделать «копию» Uniswap V3, он может просто создать прокси-клона и указать ему на контракты Uniswap V3, а затем продавать этот проект, как альтернативу Uniswap V3. Модификатор nodelegatecall не позволяет этого сделать. #nodelegatecall

‼️ Последние 8 часов продаж курса! Это небольшое напоминание для тех, кто всегда ждет последнего момента перед принятием решения. Осталось менее 8 часов для записи на курс, так как продажи закроются в полночь. Уже более 30 учеников присоединились к модулю и мы ждем последних! Уже с завтрашнего дня пойдут первые уроки. Больше уже вы не сможете получить этот модуль с поддержкой преподавателя, он будет доступен только для самостоятельного прохождения. Успейте занять свое место! Программа курса            Условия и оплата Старт уже завтра! #курс

Для записи на курс осталось менее 48 часов! Время — ваш главный ресурс. И если вы всерьез настроены войти в разработку смарт-контрактов, то сейчас критический момент. Самостоятельное обучение — это путь проб и ошибок, где каждая ошибка может стоить вам месяцев переучивания, упущенных возможностей и даже финансовых потерь. Вы можете научиться писать контракты, но пропустить уязвимости, которые сделают ваш код мишенью для хакеров. Вы можете разобраться с синтаксисом, но не заметить, как неоптимальный код съедает бюджет на газ. Вы можете создать токен или NFT, но упустить детали, которые позже обернутся переделкой всей архитектуры. Я прошел этот путь и знаю, сколько времени теряется на исправление ошибок, которые можно было избежать с самого начала. Курс — это не просто информация. Это направление, фокус и исправление ошибок до того, как они войдут в привычку. Это знания, которые я получил бы ценой месяцев проб и ошибок, но теперь они структурированы и готовы для вас. У вас осталось меньше двух дней, чтобы принять решение. Не упустите шанс учиться правильно с первого дня. Запишитесь на курс, пока есть возможность. Программа курса            Условия и оплата Начинаем 5 мая! #курс

Последний поток курса в таком формате Три года мы делали идеальный курс для новичков в Solidity, но всё меняется. Третий поток в Telegram станет последним в таком формате, и это отличный шанс пройти обучение именно с живой поддержкой и общением. Сейчас у вас есть возможность учиться в небольшой группе, где я проверяю задания, отвечаю на вопросы и помогаю разбирать сложные моменты. Такой формат отлично подходит тем, кто ценит персональный подход и хочет сразу получать обратную связь. В следующем году курс переедет на новую платформу – это будет удобный сайт самоучитель с четкой структурой и практическими заданиями. Но, конечно, там уже не будет общего чата и возможности задавать вопросы. Поэтому если вам важна поддержка преподавателя – сейчас самое время присоединиться. Переход на платформу открывает перед нами массу возможностей: новые форматы, напоминания, быстрые обновления и т.д. Но если вы хотите учиться в уютной атмосфере Telegram канала с живым общением – добро пожаловать в третий поток. Группа стартует 5 мая, записаться можно по ссылке ниже. Программа курса            Условия и оплата P.S. На платформе курс тоже будет крутым – просто другим. А пока ловите последний шанс поучиться в "старом добром" формате! #курс

10 фактов о курсе и модуле В последний день апреля, хотел поделиться с вами некоторыми фактами о курсе: 1. Это уже третий поток курса, стартовавшего в 2023 году. 2. Курс прошло более 250 учеников в общем количестве. Многие проходили модули по два раза! 3. На этом потоке будет 93 урока в общей сложности: от нуля до уверенного разработчика! 4. Это структурированный курс, где уже отфильтрована лишняя информация и расставлены правильные акценты. 5. Курс сэкономит полгода проб и ошибок, потому что построен на четкой методике, а не на обрывочных знаниях. Вы будете учиться тому, что действительно используют в проектах, а не абстрактным примерам из документации. 6. Большинство курсов учат писать код, но не думать в парадигме блокчейна. В результате после месяцев обучения человек может скопировать чужой контракт, но не способен спроектировать свой. Наш курс построен иначе: мы сразу погружаемся в логику смарт-контрактов и EVM, чтобы вы не тратили время на бесполезные туториалы. 7. После окончания курса канал и чат не удаляется, а значит, что доступ к материалам модуля у вас остается навсегда. 8. сэкономит полгода проб и ошибок, потому что построен на четкой методике, а не на обрывочных знаниях. Вы будете учиться тому, что действительно используют в проектах, а не абстрактным примерам из документации. 9. Вы можете проходить курс в своем темпе: делать задания, изучать уроки и задавать вопросы. Не нужно подстраивать свое расписание под созвоны, стримы или другую онлайн активность. 10. Низкая стоимость и модульность позволяет "попробовать для себя" Solidity и смарт контракты. Не нужно вписываться на годовое обучение, если вам что-то не понравится или решите, что программирование не для вас. Присоединяйтесь! Программа курса Условия и оплата Курс стартует уже на следующей неделе - 5 мая! #курс

Про vibe coding и Solidity Когда все вокруг говорят, что нейросети скоро заменят программистов, я решил проверить это на практике. Взял отчасти незнакомый стек — Python + React + MySQL — и поставил задачу: создать крипто мессенджер с end-to-end шифрованием. Не вникая в код, просто давая указания нейронке. Итог? Три дня борьбы с бессмысленными правками, тоннами логов и внезапными ошибками в рабочих частях кода. Нейросеть путала версии библиотек, "чинила" то, что не ломалось, и в итоге выдала монструозный проект, который проще переписать с нуля, чем отладить. Это был фейл... 1. В самом начале я столкнулся с проблемой версий библиотек и Python, библиотек и React+Vite... Я использовал рекомендованный набор библиотек от нейронок и когда возникли ошибки, нейронки такие: "А ты не знал?! Как жаль... Вот так нужно все перенастроить...". Ок, пара часов возни и все установлено. 2. Потом мы создали компоненты для фронтенда и подключили авторизацию. Вроде, все было ок, пока не потребовалось создание секретной фразы для криптографии. Тут пошли "танцы с бубном". 3. Невообразимое логирование, куча отладочных файлов и тестов. В итоге, папка проекта и сам код раздулись просто комарно. Я уже сдался и пошел настраивать все сам и вникать в код. 4. Дальше был Python. При, казалось бы, огромной базе знаний в сети, нейронки просто не смогли подключиться к базе данных. Запускались куча терминалов, вводились одинаковые команды. И снова логирование... 5. Что самое плохое было, так это то, что нейронка пыталась корректировать файлы, который не нуждались в этом. Создавая связь с базой данных, он исправлял и компоненты фронтенда, и версии библиотек с их переустановкой и массой других не нужных действий. И это все в работе с популярными языками программирования. С Solidity дела обстоят куда серьезнее. Нейронки плохо понимают контекст. Они не видят последствий. Они просто комбинируют куски кода из интернета. Я учу Solidity не для того, чтобы вы писали всё вручную. Я учу вас понимать, что делает нейросеть. Видеть её ошибки. Правильно ставить ей задачи. Потому что в мире, где любой может сгенерировать контракт за минуту, настоящий навык — это умение отличить рабочую вещь от финансовой бомбы. Курс стартует 5 мая. Первый модуль — база, чтобы читать и разбирать любой контракт. Второй — практика с упором на безопасность. Это тот минимум, после которого ты сможешь работать с нейросетями, а не надеяться на них. P.S. Если вы разработчик и хотите попробовать реализовать задумку с крипто мессенджером, я могу дать технические описания, которые мы создавали с нейронками, и вы пройдете мои "страдания". #курс

🔼Первые ученики уже на канале!🔼 Если вы только пришли с работы, то пост для вас! Сегодня старт продаж 1 модуля нашего курса! Самые первые ученики уже канале! Вы супер! Уверенность в действиях очень сильно помогает в учебе! Знаю, у вас будет очень интересный путь Solidity разработчика!  Ждем остальных, ведь по опросу желающих было куда больше: 60 проголосовавший ЗА! Это идеальное время получить новые знания и профессию. Web3 развивается и разработчики смарт контрактов будут еще больше востребованы! Для кого этот курс: подходит для всех, кто ни разу не работал с кодом и не знает, что такое программирование Курс рассчитан на НЕСПЕШНОЕ прохождение каждой темы и времени на ее освоение, поэтому он длится 4+ месяцев. Сложность повышается с каждым модулем, по мере вашей готовности к новым темам, во избежание путаницы в голове из-за большого объема информации. Задача: курс нацелен на плавное изучение языка Solidity и освоение новой профессии разработчика смарт контрактов. По окончанию всех модулей вы будете иметь достаточно знаний и сформированные скилы, чтобы претендовать на работу в зарубежных компаниях.     Особенности курса: - Уроки с акцентами на безопасности кода; - Тестовые вопросы, собранные из реальных собеседований; - Написан простым языком, без технических усложнений; - Основной принцип: регулярность лучше интенсивности; - Основная цель: сформировать понимание языка Solidity, его характеристик и особенностей; Что входит в урок: Объяснение материала, описание проблем безопасности (если требуется), дополнительные источники для самообучения, практическое задание. Тестовое задание по окончанию модуля. Продажи открыты! Успейте занять свое место! Программа курса. Условия оплаты в посте выше. Старт 5 мая! #курс

🥳🥳🥳 Открытие продаж курса: Модуль 1 🥳🥳🥳 Более 150 учеников в общем количестве прошли второй поток нашего курса "Разработчик смарт контрактов на языке Solidity"! 67 уроков с дополнительными материалами и заданиями, 5 практикумов для тренировки навыков и более 150+ вопросов для самопроверки: все это помогло ученикам начать не простой путь в мир разработки смарт контрактов! Обучение не должно останавливаться, поэтому мы делаем перезапуск курса с самого начала, с первого модуля, чтобы уже к концу лета вы получили новые знания и навыки работы с кодом! Этот модуль был переработан и невероятно улучшен, чтобы дать вам наиболее полные знания по блокчейну и Solidity! Готовы? Присоединяйтесь!   Сегодня я открываю продажи и начинаю добавлять участников в закрытый Телеграм канал. Итак, как пройти запись и попасть на канал: 1. Оплачиваем курс по реквизитам ниже. 2. Скидываем мне в личные сообщения @zaevlad чек об оплате или хеш транзакции; 3. После этого я добавляю Вас в закрытый канал модуля. Продажи будут открыты до конца этой недели. Потом на первый модуль будет не попасть! Реквизиты для оплаты: 1. Перевод на карту: 4276520014513846, Владилен Александрович З. 2. Перевод на криптокошелек: 0x331d8654Ff5c314E2baDAAfA83Fdf635650a9E59 . Переводы необходимо делать в сети Polygon, в криптовалютах: USDT / USDC. Цена за первый модуль: 5000 рублей или 60 USDT / USDC; Цена для учеников, которые уже ранее покупали курс и хотели бы перепройти его: 1500 рублей или 18 USDT / USDC; P.S. По всем вопросам можете писать в чат или личные сообщения. Программа курса. Старт 5 мая! #курс

Старт продаж на 1 модуль в понедельник! Приятно, что желающий пойти на модуль собралось уже 50 человек! Понимаю, что многие не дойдут, но, уверен, что группа наберется! Поэтому уже в этот понедельник откроются продажи, а уже с 5 мая начнется сам модуль! Вчера я думал, когда лучше всего стартовать: до майских праздников или после? С одной стороны, многие приступят к обучению после всех выходных, а с другой - ну, не особо хочется затягивать, чтобы летний модуль также успеть запустить в июне. В итоге, принял решение сделать продажуу модуля в течение всей следующей недели: кто-то захочет сразу присоединиться, кто-то дождется праздников и зайдет позже. Время для всех! Еще также немного информации по урокам: меня в личке спрашивали, а будут ли уроки / нужно ли знание JavaScript для старта, так как в некоторых курсах он идет с самого начала программы. Я против такого подхода с JavaScript для обучения написания смарт контрактов по нескольким причинам. Во-первых, вы никогда не выучите JS за пару уроков. Вот вся "эта история" с языком, требует не меньшего времени изучения, чем любой другой язык. Да, JS и Solidity похожи, да для подключения библиотек для взаимодействия сайта и смарт контракта нужен ethers.js (библиотека на javascript) и Hardhat для тестирования. Но это разные вещи! Представьте, что вы идете в первый класс, где вы получаете свой первый букварь по родному языку. Но тут руководство школы приходит и говорит, что еще будете изучать язык и сразу грамматику монгольского языка. Ну, а что: буквы похожи, слова также пишутся... Норм... И какая каша тогда в голове будет? Во-вторых, к JavaScript добавляют еще изучение React / React+Vite / Vue. А там еще и TypeScript выглядывает из-за угла, так как это стандарт в сегодняшнем мире. В итоге ученик приходит изучать один Solidity, а ему в сжатые сроки рассказывают про 2 языка, и 3 фреймворка. Этот подход хорош, если вы заходите на обучение минимум на 1 год с постоянной практикой, домашними заданиями и проверками! А если, это обучение на 2-3 месяца - в голове будет каша и ноль знаний. Разделите свое обучение! Не старайтесь "заглотить" все и сразу. Вполне вероятно, что через некоторое время вы увлечетесь самой технологией блокчейна и решите изучать другой язык, например Rust. Или захотите стать аудитором и участвовать в конкурсах - тогда вам JS вообще никогда не потребуется. И вот только если вы поймете, что смарт контракты и dapp - это ваше, и захотите создать полноценное приложение, то только тогда тратьте время на JavaScript. Именно поэтому на первом модуле я даю информацию по базовым аспектам языка Solidity и, теперь уже, EVM. Вы познакомитесь с языком, пощупаете его, сделаете пару движений и уже потом поймете, насколько это "ваша тема". Жду вас на новом модуле 3 потока! #курс

Вы пойдете на 1 модуль?
Anonymous voting

🧨 Программа 1 модуля курса, 3 поток! Сегодня хочу показать вам программу модуля, над которой я работал последние два месяца. И это что-то невероятное, чем я очень горжусь! Прежде чем приступать к переработке модуля, я просмотрел все вопросы учеников с прошлых модулей, программы других похожих курсов, роадмапы и многое другое. В этом модуле будет собрана информация, которая даст максимально полное представление для ученика о мере Эфириума и разработки смарт контрактов! Во-первых, появилось много сетей различных уровней и их количество будет расти, поэтому ученику нужно дать представление: зачем это нужно, как работает и чем отличается от всех остальных. Во-вторых, сам Эфириум претерпевает изменения все более крупного масштаба, и нужно понимать, всю внутреннюю механику процесса. В-третьих, я понял, что вместе с базовыми знаниями Solidity нужно давать объяснение ученикам, как это происходит на уровне виртуальной машины Эфириум. Простыми словами с отсылками к Yellow Pages. В-четвертых, было бы здорово, если бы после модуля у ученика был бы некоторый материал для самостоятельной практики, на случай, если он будет не готов идти на последующие модули и потребуется время, чтобы все усвоить после первого. P.S. Сразу скажу, что модуль будет запускаться, если будет набрано достаточно количество учеников. Если же нет - он будет отложен на некоторый срок. Поэтому голосование после поста крайне желательно! Итак, вот программа модуля: Неделя 1 Урок 1. Введение в программирование: код и алгоритмы. Урок 2. Web3 и его компоненты. Урок 3. Блокчейн, сайдчейн и различные уровни сетей. Урок 4. Что такое сеть Эфириум? Урок 5. Архитектура Эфириум. Дополнительно: Консенсус (общее); Дополнительно: Состояния сети и Деревья; +30 вопросов для самопроверки Неделя 2 Урок 6. Введение в Solidity. Дополнительно: Типы аккаунтов. Что такое транзакция? Урок 7. Начало работ с Remix. Дополнительно: Правила именований в контрактах; Дополнительно: Процесс создания контрактов на уровне EVM; Урок 8. Переменные в Solidity. Дополнительно: Общий обзор всех типов данных. Урок 9. Тип данных: bool. Дополнительно: Какие операторы существуют? Урок 10. Тип данных: string. Дополнительно: История форков; +30 вопросов для самопроверки Неделя 3 Урок 11. Тип данных: uint/int. Дополнительно. Условия в программировании; Урок 12. Тип данных: bytes. Дополнительно: Почему важен шардинг для EVM? Урок 13. Тип данных: array. Урок 14. Тип данных: enum. Урок 15. Тип данных: mapping. +30 вопросов для самопроверки Неделя 4 Урок 16. Event и error в коде. Дополнительно: Больше о событиях и логировании; Урок 17. Функции. Урок 18. Валидация ошибок в коде. Урок 19. Циклы и итерации. Урок 20. Модификаторы. Дополнительно: Выполнение транзакции на уровне EVM; +30 вопросов для самопроверки Неделя 5 Урок 21. Структуры и вложенности Урок 22. Глобальные переменные Дополнительно: Память EVM. Дополнительно: Работа с памятью EVM. Общее. Урок 23. Наследования Практикум 1 Урок 24. Интерфейсы Дополнительно: Вызов между контрактами на уровне EVM; +30 вопросов для самопроверки Неделя 6 Урок 25. Библиотеки Дополнительно. Знакомство с библиотеками Open Zeppelin; Урок 26. Call, statickcallm Дополнительно: Межсетевое взаимодействие: проблемы и решения; Урок 27. Delegatecall +15 вопросов для самопроверки Практикум 2 Бонус: задачник для самостоятельной практики в Remix на 30 заданий! Итого: 6 недель, 27 уроков, 17 дополнительных уроков по EVM, 165 вопросов для самопроверки, 30 практических заданий, 2 практикума! По стоимости, думаю, будет доступная для каждого, но чуть выше, чем в прошлом году - 5000 рублей. Формат - текстовые посты с домашними заданиями в закрытой группе в Телеграм, видео только в дополнительных материалах. Сам канал удаляться не будет, информация в нем останется с вами навсегда. Уверен, что этот модуль будет одним из самых "мясных" на рынке! Ниже будет опрос для тех, кто хотел бы пойти на обучения. Прошу проголосовать тех, кто заинтересован. Всем прекрасного дня и настроения! #курс #обучение

Содержание предыдущих постов Что-то давно я не делал подборку с темами прошедших постов, а ведь их собралось не мало практически за последние полгода. По традиции сделал небольшое оглавления с быстрыми ссылками для удобства поиска. P.S. Также буду рад и признателен репостам. Обучающие посты 1. Solidity hints. Часть 22 2. Solidity hints. Часть 23 3. Solidity hints. Часть 24 4. Solidity hints. Часть 25 5. Merkle-Patricia Trees. 14 постов 6. Низкоуровневый вызов и высокоуровневый вызов в Solidity. 2 поста 7. RSA алгоритмы. 4 поста 8. Самые популярные типы DAO. 3 поста 9. Обновляемые контракты (Transparent proxy). 5 постов 10. Calldata Encoding. 3 поста 11. Понимание метаданных смарт-контракта. 2 поста 12. Пара слов о Passkeys 13. Все, что нужно знать об интеграции Chainlink. 3 поста 14. Работа с мультисиг кошельками. 7 постов 15. Blockchain reorgs. 2 поста Видео 16. Запись стрима "Подготовка протокола (dApp) к аудиту" 17. Запись стрима "ERC4626: проблемы и решения" 18. Пробы записи видео и разбор функций 19. Постфикс и префикс в Solidity 20. Взлом контракта через calldata 21. Опасный модификатор Для начинающих аудиторов 22. Небольшая история о путешествии в мире аудита 23. Челлендж: 50 не валидных репортов 24. Нужно ли доводить аудит до конца? 25. Коротко о двойных стандартах в конкурсных аудитах 26. Роудмап: Как стать аудитором смарт контрактов. 3 поста 27. Конкурсные аудиты с пулом "по условию" - Conditional Pool 28. Упражнение для начинающих аудиторов 29. Про подготовку к аудиту 30. Ловушка аудитора и недостаток валидации Остальное 31. Минимальные требования для работы 32. Тестирование != тестирование 33. Перспективы для новичков в web3 34. Компилятор тоже умеет шутить Приятного изучения и хорошего дня! #offtop

Blockchain reorgs. Часть 2 Продолжаем наш разговор про реорганизацию блокчейна. Off-ramp системы Под криптовалютным off-ramp понимается процесс обмена криптовалют на фиатную валюту. К системам, осуществляющим офф-рампинг криптовалют, относятся: - централизованные биржи (CEX); - провайдеры криптовалют в фиат; Криптовалютные депозиты в этих системах подтверждаются после определенного количества блоков, прошедших с момента транзакции, чтобы смягчить любые проблемы, которые могут быть вызваны перестройкой блокчейна. В этой серии постов приведены некоторые конкретные требования к подтверждению блоков, которые существуют на известных CEX. Например, Coinbase требует 35 подтверждений блоков для депозитов ETH, в то время как Binance - только 12. По наблюдениям, CEX склонны сильно затягивать с подтверждением. Например, реорганизация блокчейна Ethereum более чем на 2 блока не происходила уже несколько лет. Off-ramp системы, особенно CEX, являются привлекательной целью для атак 51%. В прошлом было несколько случаев, когда злоумышленники получали 51% ресурсов проверки сети (коэффициент хеширования) и инициировали вывод средств на нескольких биржах, а затем реорганизовывали цепочку, чтобы повторно инициировать вывод средств на других биржах. Наиболее заметные атаки 51% затрагивают токены Verge, Ethereum Classic, Bitcoin Gold, Feathercoin и Vertcoin. Смягчить последствия этой формы атаки не так просто. Одним из компонентов решения является чрезмерное увеличение количества требуемых подтверждений. Однако в таких случаях этого недостаточно, поскольку захват сети может длиться неопределенное количество времени. Необходимо внедрить решение для мониторинга сети в сочетании с приостановкой снятия/пополнения средств. Протоколы, которые требуют от пользователей создать что-то, а затем взаимодействовать с этим в два этапа Этот тип проблем с реорганизацией наиболее часто встречается в данной категории уязвимостей. Они возникают, когда протокол требует от пользователей сначала создать или инициировать компонент, а затем, в другой транзакции, взаимодействовать с ним. Еще одним важным и ключевым условием является то, что развернутые контракты используют ключевое слово в Solidity "new" для создания контракта (или опкод CREATE). Обе эти процедуры полагаются на nonce вызывающего контракта для определения адреса вновь развернутого контракта и не учитывают никаких пользовательских данных. Например, протокол использует шаблон factory для развертывания контрактов, чьи функции не имеют прав доступа. Скажем, логика фабрики развертывает контракт одним вызовом, предоставляя специальные разрешения развертывающему. После развертывания пользователь отправляет депозит только что развернутому контракту. Примерный сценарий атаки в описанном выше случае: 1. Alice создает Vault через контракт фабрики (транзакция A); 2. затем Alice вносит в Vault токены (транзакция B); 3. происходит реорганизация блока, и транзакция A отбрасывается (транзакция B все еще существует); 4. обычно транзакция B возвращается, если выполняется; 5. Bob развертывает свой Vault, который первоначально сделала Alice (через фронтран), и из-за базовой проблемы оно= создается по тому же адресу, что и первоначальное хранилище 6. депозит Alice попадает в Bob Vault, и тот может его снять; Для того, чтобы решить эту проблему, используйте опкод create2, а соль должна содержать элементы, характерные для вызывающей стороны (например, хэш на входы плюс msg.sender). #reorg

P.S. Скрин, который забыл прикрепить к предыдущему посту.
P.S. Скрин, который забыл прикрепить к предыдущему посту.

Blockchain reorgs. Часть 1 Эту тему мне приходилось касаться только на аудитах. Ни у себя на канале, ни на других каналах я не встречал информации про такое событие как реорганизация блоков в блокчейне, и чем это может быть опасно. Возможно, материал и был, но мне он так и не встретился. Поэтому следующие несколько постов мы посвятим этой теме. В Web3 мы часто слышим идиому «блокчейн неизменен», но бывают случаи, когда это не так, точнее, он становится практически неизменным (достигает окончательности) только по прошествии некоторого времени с момента майнинга блока, содержащего транзакции пользователей. Это связано с событиями, называемыми реорганизациями блокчейна, или сокращенно reorg. Реорганизация - это событие, когда блок, который был частью канонической цепи, перестает быть частью канонической цепи, потому что его вытесняет конкурирующий блок. Реорганизации происходят из-за более мягкого способа работы клиента проверки блокчейна. Алгоритм, определяющий, какая цепь является канонической (правило выбора форка), при определенных обстоятельствах может прийти к выводу, что текущая история цепей не является оптимальной, и выбрать другую цепь из тех, что предоставляют конкурирующие майнеры (цепочки форков), чтобы стать канонической цепью. Когда происходит перестройка блока, то, будучи внешним наблюдателем цепочки, вы видите, что: 1. Несколько блоков были отброшены и заменены другими; 2. Это не означает, что все транзакции в исходных блоках были отброшены, большое количество транзакций, вероятно, все еще будет включено в новые блоки, возможно, даже все, но не в том же порядке; Реорганизации появляются чаще, чем люди думают. Используя такие сканеры, как polygonscan.com/blocks_forked, для Polygon reorgs, вы можете увидеть, что они появляются часто. При разработке или аудите протоколов, которые могут быть уязвимы к проблемам реорганизации, необходимо учитывать некоторые моменты, характерные для каждой цепи. В качестве ориентира можно использовать таблицу на скрине. Примечания и наблюдения - Приведенные на скрине данные были собраны либо со сторонних агрегаторов, либо с сайтов, напрямую отображающих исходные данные. Они также взяты после любых крупных изменений в сети, например, для Ethereum после PoS и для BNB Chain после их последних крупных изменений в масштабируемости, которые резко снизили скорость реорганизации. - При принятии решения о том, сколько блоков ждать перед подтверждением транзакции вне цепи в чувствительных системах (например, при переходе с криптовалюты на фиат), лучше всего подождать на несколько блоков больше, чем наибольшая глубина реорганизации на этой цепи, которая имела место в прошлом. - Например, депозиты на CEX от Polygon могут ждать даже 200 блоков, прежде чем будут считаться окончательными. Системы, основанные на случайной составляющей в сети Протоколы, содержащие случайный компонент, естественным образом подвержены влиянию реорганизации блокчейна. Такими протоколами могут быть ставки, казино, игры со случайной системой вознаграждения, практически все, что вычисляет случайность с помощью оракула. Пример ситуаций, которые могут возникнуть: - игрок выигрывает хорошее вознаграждение в случайном розыгрыше, но из-за реорганизации блокчейна теряет его; - азартный игрок проигрывает в игре в кости, но благодаря реорганизации блокчейна он теперь фактически выигрывает; На практике для вычисления случайного числа часто используется VRF (Verifiable Random Function) от Chainlink. Этот API принимает время подтверждения блока, которое, если верить документации, представляет собой: - сколько блоков служба VRF ждет, прежде чем записать выполнение в сеть, чтобы сделать потенциальные атаки на перезапись невыгодными в контексте вашего приложения и его стоимости под риском. Для того, чтобы смягчить эту проблему, достаточно выбрать подходящее время подтверждения блока. #reorg

Проект на виду. Часть 5. ИИ вас не заменит В какой-то рекламе в Твиттере встретил прекрасную фразу: ИИ вас не заменит, вас заменит человек, который умеет работать с ИИ. И знаете, в этом есть огромная доля правды. Даже для Solidity разработчиков... Я все еще в процессе создания проекта, хотя концепция немного сместилась в сторону web3 безопасности. Подробнее об этом расскажу позже, а сейчас хочу поделиться некоторыми моментами разработки. В общем, для собственного эксперимента и практики, я выбрал стек React+Vite, Tailwind (стили), бек на Python + flask, mysql + php. Из этого списка я никогда ранее не работал с Vite, Tailwind и Python. И если с Vite и стилями еще можно как-то разобраться, если ты знаешь реакт и css, то Python для меня идет с абсолютного нуля. Для генерации скриптов я использую нейросети. И запросы отправляю практически всем: DeepSeek, ChatGPT, Grok, Claude, Gemini. И хочу поделиться, что я заметил. Во-первых, создание контекста запроса и сам запрос крайне важны для того ответа, который вы хотите получить. Нейросеть будет давать вам варианты какие посчитает нужным. Порой у меня складывалось впечатление, что у них есть некоторый вариант заложенного опыта выдачи "более кратких ответов". Например, при одинаковых запросах ChatGPT и DeepSeek выдадут два разных по длине кода. Во-вторых, нейросети могут лениться. Особенно этим, в моем опыте, страдает ChatGPT. При хороших ответах он выдает обрезанный код, даже если просишь написать полный скрипт. И тут надо понимать, где они что-то недоговаривают, а где ответ - норм. В-третьих, пока что они плохо работают с большим объемом кода. Если файл содержит 1000+ строчек кода, нейронки будут выдавать вам ответ, который будет только портить изначальную идею скрипта. В-четвертых, редакторы кода со встроенными нейронками, лучше для полноценных проектов, чем отдельные чаты. Опять же дело в контексте проекта. IDE справляется намного лучше с распознаванием структуры файлов и правками кода. В-пятых, если вы не понимаете, что происходит в коде и просите исправить ошибку, нейронки вполне могут вас забросать ненужным логированием, отладочными файлами и тестами. В итоге скрипт из 400+ строк превращается в отладочного монстра на 1200+ строк. В-шестых, многие ИИ делают то, что не требовалось. Очень часто в простом запросе, они выдают результат с "улучшениями, адаптацией, рекомендациями", которые запросто могут привести к негодности весь проект. И это при том, что я тестировал код на Python! Одном из самых популярных языков в мире, с огромной документацией, примерами и наработками. А вот теперь представьте, что будет если попытаться создать web3 проект без знаний и понимания кода! Это будет не просто ужасный по безопасности протокол, но еще и качество кода будет сильно под вопросом. А после загрузки в блокчейн, такой продукт будет уже не изменить. Поэтому Solidity все же учить будет нужно, чтобы понимать работу кода и правильно направлять нейронки при работе с кодом. Кроме того, такие проекты также будут обязательны к аудиту. Хотите использовать нейронки для работы? Тогда вам нужно наверняка знать, что они делают с кодом. Учите Solidity и учитесь формировать запросы с контекстом. #offtop

Работа с мультисиг кошельками. Часть 7 Как развернуть (Gnosis) Safe Multisig локально с помощью anvil? Safe Wallet - это один из самых популярных мультисиг кошельков на Ethereum и других EVM-совместимых блокчейнах. Он широко используется отдельными разработчиками, командами и DAO для безопасного управления криптоактивами. Этот кошелек достаточно просто развернуть в своей среде разработки. Давайте пойдем по шагам. 1. Для начала нам потребуется скопировать кошелек с официального репо:
git clone https://github.com/safe-global/safe-smart-account.git
2. Далее установим его зависимости:
npm i 
Надеюсь, вы уже знаете как работать с терминалом и у вас не возникнет никаких проблем с этими двумя шагами. В конце можно проверить, что все установилось правильно, выполнив команду:
npm run build
3. Теперь мы готовы запустить все тесты и проверить, готовы ли мы к развертыванию, для этого просто запустите:
npm run test
Выполнение всех тестов займет около 30 минут в зависимости от вашей машины. Деплой в локальную сеть 4. Создайте файл .env в каталоге проекта со следующим содержимым:
MNEMONIC=”test test test test test test test test test test test junk”
NODE_URL="http://127.0.0.1:8545"
5. Запускаем Anvil:
anvil
6. Это не обязательно, но мы можем перекомпилировать контракты, если в них были внесены какие-либо изменения:
npm run build
7. Теперь, наконец, мы можем развернуть все контракты в локальной сети с помощью команды
npx hardhat --network custom deploy
В терминале появятся логи с контрактами и адресами Safe для дальнейшего взаимодействия. Вот, в общем, и все! Мы сделали деплой Safe в локальную сеть и теперь можно отправлять транзакции с нашего проекта для тестирования вызовов. #multisig

    receive() external payable {}

   function getOwners() public view returns (address[] memory) {
        return owners;
    }

    function getTransaction(uint256 _txIndex) public view
        returns (
            address to,
            uint256 value,
            bytes memory data,
            bool executed,
            uint256 numConfirmations
        )
    {...}
Это минимальный пример контракта мультисига. Можно еще добавить работу с подписями, разрешенные токены, ролевую систему и т.д. Но это уже нужно смотреть под конкретный пример. Далее поговорим о деплое кошелька, на примере Safe. #multisig

Работа с мультисиг кошельками. Часть 6 Продолжаем разбирать контракт простого мультисиг кошелька, и сегодня поговорим о функциях в нем. Хочу еще раз уточнить, что это исключительно показательный пример такого контракта, и, если вы хотите реализовать что-то с его использованием, то лучше всего искать схожие проекты, изучать их код и уже после копировать структуру к себе. Кроме того, аудит проходить в этом случае будет крайне необходимым решением. Итак, какие же функции нам потребуются? 1. Во-первых, нам нужно как-то создавать транзакцию, которую будет необходимо подписать определенным количествам владельцев мультисига. 2. Также нам потребуется собирать подписи участников для одобрения транзакции; 3. Кроме того, возможно, некоторые захотят отозвать свою подпись после каких-то раздумий. 4. Ну, и понятное дело, исполнять ее. В итоге у нас получается:
function submitTransaction(...) public {...} 
function confirmTransaction(...) public {...}
function revokeConfirmation(...) public {...}
function executeTransaction(...) public {...}
Начнем с первой. У нас уже была структура подписи и массив для сохранения. Поэтому тут все просто:
    function submitTransaction(address _to, uint256 _value, bytes memory _data) public onlyOwner {
        uint256 txIndex = transactions.length;

        transactions.push(
            Transaction({
                to: _to,
                value: _value,
                data: _data,
                executed: false,
                numConfirmations: 0
            })
        );

        emit SubmitTransaction(msg.sender, txIndex, _to, _value, _data);
    }
Просто определяем id транзакции по длине текущего массива, создаем новые записи в структуре и помещаем в массив. При необходимости можно порождать событие. Далее функции ободрения и отзыва для владельцев мультисига.
    function confirmTransaction(uint256 _txIndex)
        public
        onlyOwner
        txExists(_txIndex)
        notExecuted(_txIndex)
        notConfirmed(_txIndex)
    {
        Transaction storage transaction = transactions[_txIndex];
        transaction.numConfirmations += 1;
        isConfirmed[_txIndex][msg.sender] = true;

        emit ConfirmTransaction(msg.sender, _txIndex);
    }

    function revokeConfirmation(uint256 _txIndex)
        public
        onlyOwner
        txExists(_txIndex)
        notExecuted(_txIndex)
    {
        Transaction storage transaction = transactions[_txIndex];

        require(isConfirmed[_txIndex][msg.sender], "tx not confirmed");

        transaction.numConfirmations -= 1;
        isConfirmed[_txIndex][msg.sender] = false;

        emit RevokeConfirmation(msg.sender, _txIndex);
    }
Тут будет обязательным использование модификаторов для проверки, что такая транзакция вообще была создана ранее, что она еще не исполнена, и что данный участник еще не голосовал за нее. Берем id транзакции, делаем проверки и изменяем numConfirmations в нужную сторону. Далее исполнение транзакции.
    function executeTransaction(uint256 _txIndex)
        public
        onlyOwner
        txExists(_txIndex)
        notExecuted(_txIndex)
    {
        Transaction storage transaction = transactions[_txIndex];

        require(
            transaction.numConfirmations >= numConfirmationsRequired,
            "cannot execute tx"
        );

        transaction.executed = true;

        (bool success,) =
            transaction.to.call{value: transaction.value}(transaction.data);
        require(success, "tx failed");

        emit ExecuteTransaction(msg.sender, _txIndex);
    }
В общем, проверяем также на существование транзакции, ее статус, количество собранных подтверждений, и в завершении используем call для ее исполнения. Вы также можете добавить функцию получения Эфира и несколько геттеров, которые сделают использование контракта более удобным.