Разработка таймлок-контрактов
Compound Finance ввёл таймлок-контракт в мейнстрим. Их Timelock.sol — двухдневная задержка перед исполнением любых изменений протокола — стал стандартом после того, как несколько DeFi-протоколов потеряли средства из-за мгновенных admin-операций. Сейчас таймлок — это базовое требование любого аудитора и первый вопрос на листинге.
Идея простая: административное действие не исполняется сразу, а ставится в очередь с минимальной задержкой. Пользователи видят предстоящее изменение и могут выйти из протокола, если оно их не устраивает. Это не панацея, но это честный контракт с пользователями.
Две реализации: OpenZeppelin TimelockController vs кастомный контракт
OpenZeppelin TimelockController — первый выбор для большинства случаев. Поддерживает роли (proposer, executor, canceller), пакетное исполнение операций, проверку минимальной задержки. Интегрируется с Governor для on-chain голосований. Хорошо протестирован, используется Compound, Uniswap, Aave.
Кастомный таймлок нужен, когда:
- Требуются разные задержки для разных типов операций (например, 48 часов для изменения fee, 7 дней для изменения admin)
- Нужна интеграция с мультисигом без Governor
- Специфическая логика отмены или экстренных операций
Мы работаем с обоими вариантами. Для нового протокола, как правило, начинаем с TimelockController — он покрывает 80% случаев.
Критичные детали реализации
Минимальная задержка
48 часов — минимум для production-протокола. Меньше — пользователи не успевают отреагировать. Стандарт DeFi-протоколов: 24-72 часа для параметров, 7 дней для смены owner/admin.
uint256 public constant MIN_DELAY = 2 days;
uint256 public constant MAX_DELAY = 30 days;
Предотвращение replay-атак
Каждая операция идентифицируется хэшем параметров плюс salt. Без salt одна и та же операция (например, setFee(100)) может быть поставлена в очередь только один раз. С salt — любое количество раз. Убеждаемся, что клиент понимает это поведение.
Экстренные функции
Почти всегда нужен bypass для критических ситуаций — если найдена уязвимость, нельзя ждать 48 часов. Паузатор (Pausable) с отдельной ролью — стандартное решение. Но паузатор, в свою очередь, должен быть ограничен: он только останавливает, не меняет логику.
Интеграция с Governor
Для полноценного on-chain управления цепочка выглядит так: Governor → TimelockController → Protocol. Голосование проходит в Governor, победившее предложение ставится в очередь TimelockController, после задержки исполняется.
OpenZeppelin предоставляет GovernorTimelockControl — адаптер, который связывает эти два контракта. Главная ошибка — дать TimelockController прямой admin-доступ к протоколу, минуя Governor. Это делает голосование декоративным.
Сроки
Деплой TimelockController с конфигурацией ролей — 1 день. Кастомный таймлок с несколькими уровнями задержки — 2-3 дня. Интеграция с существующим Governor — 1-2 дня в зависимости от архитектуры протокола. Тесты входят в оценку.







