Solidity. Смарт контракты и аудит
2.63K subscribers
246 photos
7 videos
18 files
555 links
Обучение Solidity. Уроки, аудит, разбор кода и популярных сервисов
Download Telegram
Подсказки по безопасности - 1

Постепенно я буду разбирать файлы из приведенного выше roadmap и делать посты с подсказками по безопасности.

В данных статьях, файлах и рекомендациях, часто встречаются разборы конкретных контрактов и их функций. Сидеть над каждым отдельным случаем не вижу смысла, так как придется изучать и сам контракт и логику выполнения транзакций. Это будет очень затратно по времени и не факт, что пробема останется актуальной для других контрактов. Поэтому я буду выкладывать общие рекомендации по безопасности, которые могут пригодиться в работе.

Подсказка 1

Токены, у которых decimals больше 18, могут стать проблемой.

Считается, что максимальное значение decimals любого токена равен 18. Однако есть другие токены, типа YAMv2, у которых decimals равен 24. Это может привести к проблемам с выполнениями расчетов в функциях. Поэтому нужно проверять, чтобы контракт смог обрабатывать не стандартные значения decimals.

#security #tip #st
👍1
Подсказки по безопасности - 2

Неконтролируемое значение return в функциях transfer и transferFrom.

Выполнение функций ERC20 не всегда последовательное. Некоторые исполнения transfer / transferFrom могут вернуть false на неуспешную транзакцию вместо отката (revert). Поэтому его обязательно нужно обрабатывать в require().

Также нужно следить и за true в return, как это рекомендует сам стандарт. В некоторых случаях, вызов transfer() будет revert, даже если транзакция пройдет успешно. Это случается потому, что Solidity проверяет RETURNDATASIZE на соответствие интерфейсу ERC20.

Рекомендация. Проверяйте значение return / revert на 0 / false / true или используйте SafeERC20 от OpenZeppelin.


#security #tip #st
👍1
Подсказки по безопасности - 3

Отсутствие процедуры проверки ввода значений.

В своих функциях желательно проверять, что:

- uint больше 0;
- uint имеет ограничения;
- int не может иметь отрицательное значение;
- длина массива должна совпадать, когда он передается как аргумент;
- адрес не должен быть 0х0;

#security #tip #st
Подсказки по безопасности - 4

Использовать фиксированные лимиты газа не рекомендуется.

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

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

#security #tip #st
👍1
Подсказки по безопасности - 5

Оценивайте все токены прежде, чем начнете работать с ними в контракте.

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

#security #tip #st
👍1
Подсказки по безопасности - 6

Pragma и версии Solidity.

Использование последних версий Solidity позволяет избегать ошибок и багов, которые встречались в более ранних версиях.

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

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

#security #tip #st
👍1
Подсказки по безопасности - 7

Не защищенная withdraw() функция (external \ public) может позволить злоумышленникам переводить деньги и токены с вашего контракта.

#security #tip #st
👍1
Подсказки по безопасности - 8

С помощью extcodesize мы можем проверить, кто делает вызов функции в нашем контракте: внешний контракт или пользователь. Однако, эту систему можно обмануть, создав пустой контракт с вызовом нужной функции в его конструкторе.

contract OnlyForEOA { ... function setFlag()...}

contract FakeEOA {
    constructor(address _a) public {
        OnlyForEOA c = OnlyForEOA(_a);
        c.setFlag(1);
    }
}

В этом случае, хоть вызов будет идти из внешнего контракта, в нашем контракте будет отображаться его пользователь (tx.origin).

#security #tip #st
Подсказки по безопасности - 9

Удаление struct в котором есть mapping, не удаляет сам mapping. Это может быть использовано против вас.

struct BalancesStruct{
  address owner;
  mapping(address => uint) balances;
}
mapping(address => BalancesStruct) public stackBalance;

function remove() internal{
  delete stackBalance[msg.sender];
}

В этом случае лучше использовать закрытие struct(lock), а не его удаление.

#security #tip #st
Обзор пройденного

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


Решение задач

Решение задач Ethernaut (1-25)
Поиск по хештегам #ethernaut

Решение задач Damn Vulnerable Defi (1-10)
Поиск по хештегам #dvd #DamnVulnerableDefi

Решение задач Capture The Ethers (1-20)
Поиск по хештегам #capture #cte


Безопасности и оптимизация газа

Безопасность и взлом контрактов v1.0

Подсказки по безопасности (9 постов)
Поиск по хештегам #security #tip #st

Оптимизация газа (18 постов)
Поиск по хештегам #gas #optimization #hint

Уязвимость в struct

Опасность tx.origin

Защити свой Метамаск

Гайд по проверке контракта (pdf)


Работа с памятью

Структура / хранение данных

Динамические массивы и мэппинги в storage


Разбор нюансов

Лезем в опкод! (5 постов)

Из чего состоит транзакция? (5 постов)

Описание Remix Debugger (3 поста)


Другое

Логические побитовые операции

Что такое динамические NFT?

MetaMask Flask and Snaps

Чтение событий в mainnet

Ролевая система (access control)

Если захотите поделиться где-нибудь одним из постов, пожалуйста, оставляйте ссылки на канал.

Приятного обучения.
👍6
Solidity Tip

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

В функциях возможно определить локальный маппинг, но с указанием на storage data location (не уверен, как это точно перевести).

Такой способ работы со вложенными маппингами поможет вам сократить расход газа в операциях.

#solidity #mapping #tip
👍9
Игры с байткодом

Байткод контрактов обычно начинается с 6080604052, который генерируется за счет операции mstore(0x40,0x80). Но возможен и такой вариант:

Попробуйте выполнить операцию mstore(0x40,returndatasize()) в самом начале. Ваш байткод будет начинаться с 3d604052!

Пример кода можно увидеть на скрине выше.

P.S. По слухам, это может помешать верификации на Etherscan, так что пробуйте с осторожностью.  

#bytecode #tip
1👍1