Time-Lock

KitchenTimelock Overview

The KitchenTimelock contract enforces a 48-hour delay on all privileged administrative actions within the Steakhouse ecosystem. This ensures that no single party, including the multisig Safe, can instantly change critical parameters or rewire core components, giving the community and security monitors time to review any pending updates.


Purpose

  • Mitigates centralization risk: All sensitive functions (e.g., updating factories, treasuries, or fees) must be queued and then executed after the delay.

  • Provides transparent governance: All scheduled updates emit events on-chain, visible before they take effect.

  • Protects users: Prevents sudden changes to token logic, treasuries, or curve math that could harm holders or LPs.


How It Works

Each contract integrated with the timelock uses the timelocked(bytes32 actionKey) modifier on sensitive functions. When a privileged call is made, it is queued first and becomes executable only after the specified delay (48 hours).

modifier timelocked(bytes32 actionKey) {
    require(block.timestamp >= pendingTimelocks[actionKey], "Timelock: not ready");
    _;
}

Admins (Gnosis Safe owners) can queue a change with:

queueTimelock(keccak256("UPDATE_FACTORY"));

And execute it after 48 hours using:

executeTimelock(keccak256("UPDATE_FACTORY"));

Affected Functions

Contract
Timelocked Functions
Delay
Description

Kitchen

setFactory, setBondingCurve, setGraduation, setStorage, setDeployer, transferOwnership, emergencyWithdraw

48h

Core router configuration and treasury management

KitchenFactory

setCreatorBasicAdvanced, setCreatorSimple, setBondingCurve, setGraduation, setKitchen, setDeployer, setStorage, setTreasury

48h

Module rewiring and factory topology updates

KitchenBondingCurve

setStorage, setGraduation, setTreasury, setUtils, transferOwnership, emergencyWithdraw

48h

Curve dependency reconfiguration and treasury redirection

KitchenGraduation

setStorage, setFactory, setBondingCurve, setTreasury, setRouter, transferOwnership, updateStipend, emergencyWithdraw

48h

Graduation-related integrations and ETH distribution controls

KitchenStorage

setTreasury, setGraduationThresholds, authorizeCaller (for new modules)

48h

Registry-level governance and system thresholds

KitchenDeployer

setRouter, setTreasury, setFactory, transferOwnership

48h

Deployment logic and treasury flow

SteakLockers

updateAuthorizedCaller, updateLockFees, updateMinLockTime, transferOwnership

48h

Locker configuration and caller privileges


Example Queue + Execute Flow

Queue an Update

Executed by the Gnosis Safe (owner)

// Queue an update to the Kitchen Factory address
kitchenTimelock.queueTimelock(keccak256("UPDATE_FACTORY"));

This action emits:

event TimelockQueued(actionKey, readyTime);

indicating when the change becomes executable.


Wait 48 Hours

No function can bypass this period. During this time, the update remains visible but inactive on-chain.


Execute After Delay

// After 48h has passed
kitchenTimelock.executeTimelock(keccak256("UPDATE_FACTORY"));

This triggers the pending update inside the target contract (e.g., Kitchen). If executed prematurely, the call will revert with Timelock: not ready.


Example Real-World Scenario

Updating the Treasury Wallet

If governance decides to redirect fees to a new Safe address:

  1. The Safe queues the update via:

    queueTimelock(keccak256("UPDATE_TREASURY"));
  2. 48 hours later, execute:

    executeTimelock(keccak256("UPDATE_TREASURY"));
  3. The change is permanently recorded on-chain, with both queue and execution events logged for transparency.


Security Properties

  • All sensitive parameters are immutable for at least 48h before change.

  • Any proposed modification emits a TimelockQueued event for external monitoring tools.

  • No module can self-update without being whitelisted and timelocked.

  • Works seamlessly across all main modules, Kitchen, Factory, Curve, Graduation, Storage, and Lockers.

Last updated

Was this helpful?