Паттерны безопасной разработки
Безопасность — это не геройство после взлома, а скучная дисциплина до него.
Паттерн безопасной разработки — устоявшийся приём проектирования, который по умолчанию устраняет целый класс уязвимостей, освобождая от необходимости «не ошибиться вручную».
Сводим воедино
За курс мы вывели набор паттернов; теперь соберём их как рабочую дисциплину. Идея в том, чтобы правильное было путём наименьшего сопротивления: использовать проверенные кирпичи, а не изобретать своё.
Ключевые паттерны
| Паттерн | Что устраняет |
| Checks-Effects-Interactions | реентранси |
ReentrancyGuard (nonReentrant) | повторный вход (страховка) |
| Pull-over-push | DoS выплат, реентранси |
| Контроль доступа (роли, мультисиг) | несанкционированный вызов |
| Оракулы + TWAP/свежесть | манипуляция ценой |
| nonce + EIP-712 | реплей подписи |
| Снапшоты прошлого блока | флеш-голосование |
Минимизация и проверенные библиотеки
Минимизация: чем меньше кода и привилегий, тем меньше поверхность атаки. Не добавляйте функцию «на всякий случай» — каждая внешняя функция расширяет поверхность. Принцип наименьших привилегий: каждая роль умеет ровно то, что нужно.
Проверенные библиотеки: используйте OpenZeppelin для стандартных кирпичей (ERC-20, Ownable, AccessControl, ReentrancyGuard, Pausable, безопасные обёртки переводов). Эти реализации многократно проаудированы; ваш собственный токен почти наверняка будет содержать тонкую ошибку.
// Собираем из проверенных кирпичей
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract Vault is Ownable, Pausable, ReentrancyGuard {
function withdraw() external nonReentrant whenNotPaused {
// CEI внутри...
}
}Аварийные механизмы
Даже идеальный код стоит снабдить рубильниками: пауза (Pausable) — остановить операции при инциденте; лимиты на вывод/частоту — ограничить ущерб; мониторинг — заметить аномалию рано. Это не признание слабости, а часть зрелого дизайна: предполагаем, что что-то пойдёт не так, и ограничиваем последствия.
Как работает под капотом: безопасные переводы
Разные токены ведут себя по-разному (некоторые не возвращают bool, некоторые берут комиссию при переводе). OpenZeppelin SafeERC20 унифицирует это и проверяет результат, избавляя от тонких багов интеграции — пример того, как библиотека инкапсулирует знание о граблях.
Частые ошибки
- Свой ERC-20/контроль доступа «с нуля». Почти гарантированная тонкая ошибка.
- Лишние функции и привилегии. Раздутая поверхность атаки.
- Нет паузы/лимитов. Инцидент сразу становится катастрофой.
Итоги
- Сделайте безопасное путём наименьшего сопротивления: проверенные паттерны вместо самописа.
- Минимизируйте код и привилегии; применяйте принцип наименьших привилегий.
- Стройте на OpenZeppelin (включая
SafeERC20,Pausable). - Закладывайте аварийные рубильники: пауза, лимиты, мониторинг.