Skip to content

Comments

Add timelock mechanism for risk configuration updates#261

Open
pashap9990 wants to merge 1 commit intostader-labs:mainfrom
pashap9990:feature/risk-config-timelock
Open

Add timelock mechanism for risk configuration updates#261
pashap9990 wants to merge 1 commit intostader-labs:mainfrom
pashap9990:feature/risk-config-timelock

Conversation

@pashap9990
Copy link

Add Timelock Mechanism for Risk Configuration Updates

🎯 Motivation

The SDUtilityPool contract manages critical risk parameters (RiskConfig) that directly impact:

  • Liquidation thresholds - when operator positions can be liquidated
  • Liquidation incentives - bonus & fees for liquidators
  • Loan-to-Value (LTV) ratios - collateralization requirements

Currently, these parameters can be updated instantly by the admin role. While this provides flexibility, it introduces potential risks:

  1. No reaction time for stakeholders: Users cannot prepare for sudden parameter changes that may affect their positions
  2. Malicious or accidental changes: A compromised admin key or configuration error could immediately impact all users
  3. Lack of transparency: No advance notice period for the community to review proposed changes
  4. Trust assumptions: Users must fully trust that admins won't make sudden unfavorable changes

💡 Solution: Two-Step Timelock Pattern

This PR implements a battle-tested governance pattern used by major DeFi protocols (Compound, Uniswap, Aave) to add a mandatory delay between proposing and applying risk configuration changes.

🔧 Technical Changes

New Functions

  1. queueRiskConfig() - Proposes new risk parameters with validation

    • Stores pending configuration
    • Records proposal timestamp
    • Emits RiskConfigQueued event for transparency
  2. applyRiskConfig() - Applies queued configuration after timelock

    • Validates timelock period (1 day) has elapsed
    • Prevents applying if no configuration is queued
    • Resets timelock after applying to prevent replay
  3. cancelQueuedRiskConfig() - Emergency cancellation

    • Allows admin to cancel pending changes if issues are discovered
    • Useful for responding to community feedback

Constants

  • RISK_CONFIG_APPLY = 1 days - Timelock delay period

State Variables

  • pendingRiskConfig - Stores queued configuration
  • riskConfigProposeTime - Tracks when configuration was proposed

Events

  • RiskConfigQueued - Emitted when new config is proposed
  • RiskConfigCancelled - Emitted when pending config is cancelled

🔐 Security Improvements

  1. Transparent governance: All changes are visible on-chain 24 hours before taking effect
  2. Reaction time: Users have 1 day to adjust positions or exit if they disagree with changes
  3. Community oversight: Monitoring tools can alert on queued changes
  4. Reduced trust assumptions: Even with compromised admin keys, attackers cannot instantly change critical parameters
  5. Safety checks:
    • Validates proposal exists before applying
    • Resets state after application to prevent replay attacks
    • Maintains all existing parameter validation
    • Fixed emit bug to use actual parameters instead of pending ones

📊 Impact Assessment

Gas Costs

  • Adds 5 storage slots (~100K gas one-time deployment cost)
  • Minimal impact on existing operations
  • Risk config updates now require 2 transactions instead of 1

Breaking Changes

  • updateRiskConfig() function removed
  • Existing scripts must be updated to use the two-step process
  • Migration path: Update admin scripts to call queueRiskConfig() then applyRiskConfig() after 1 day

Backward Compatibility

  • All other contract functionality unchanged
  • No impact on user-facing operations (delegation, withdrawals, liquidations)
  • Upgradeable architecture allows smooth deployment

🧪 Testing

Added comprehensive test coverage:

  • test_UpdateRiskConfig() - Validates full queue → wait → apply flow
  • test_CancelQueuedRiskConfig() - Validates cancellation mechanism
  • ✅ Existing tests continue to pass

All tests passing:

Ran 2 tests for test/foundry_tests/SDUtilityPool.t.sol:SDUtilityPoolTest
[PASS] test_CancelQueuedRiskConfig() (gas: 106105)
[PASS] test_UpdateRiskConfig(uint256) (runs: 257, μ: 142816, ~: 142871)
Suite result: ok. 2 passed; 0 failed; 0 skipped

📖 Usage Example

// Step 1: Admin proposes new risk parameters
sdUtilityPool.queueRiskConfig(
    85,  // liquidationThreshold: 85%
    10,  // liquidationBonus: 10%
    5,   // liquidationFee: 5%
    80   // ltv: 80%
);
// Event emitted: RiskConfigQueued(85, 10, 5, 80)

// Community reviews, monitoring alerts sent
// Wait 1 day...

// Step 2: After 1 day, admin applies the changes
sdUtilityPool.applyRiskConfig();
// Event emitted: RiskConfigUpdated(85, 10, 5, 80)

// Alternative: Cancel if issues found before applying
sdUtilityPool.cancelQueuedRiskConfig();
// Event emitted: RiskConfigCancelled()

🎯 Benefits

Aspect Before After
Change Speed Instant 1 day delay
Transparency On execution 24h advance notice
User Protection Trust-based Time to react
Attack Surface Immediate exploit 24h detection window
Governance Centralized More decentralized

🔄 Alignment with Industry Standards

This pattern is considered best practice in DeFi:

  • Compound: Uses Timelock for all governance actions (2-day delay)
  • Uniswap: Governance changes have 2-day timelock
  • Aave: Risk parameters require governance vote + timelock
  • MakerDAO: Multi-day delay for critical parameter changes

📝 Files Changed

  • contracts/SDUtilityPool.sol - Core implementation
  • contracts/interfaces/ISDUtilityPool.sol - Interface updates with new events
  • test/foundry_tests/SDUtilityPool.t.sol - Test coverage

🚀 Deployment Notes

When deploying this upgrade:

  1. Update admin scripts to use new two-step process
  2. Monitor queued changes via RiskConfigQueued events
  3. Set up alerts for when changes can be applied
  4. Document new process for future admins

🔍 Security Considerations

  • Timelock period (1 day) balances security with operational flexibility
  • Emergency cancellation allows quick response to discovered issues
  • All parameter validation from original implementation maintained
  • No new external dependencies introduced
  • Follows OpenZeppelin upgradeable patterns

Related Issues: N/A
Type: Enhancement - Security & Governance
Breaking Change: Yes (admin scripts need updates)
Requires Documentation Update: Yes

Implements a 1-day timelock for updating risk configuration parameters to enhance security and provide time for review before changes take effect.

Changes:
- Split risk config updates into queueRiskConfig and applyRiskConfig functions
- Added RISK_CONFIG_APPLY constant (1 day delay)
- Added pendingRiskConfig and riskConfigProposeTime state variables
- Added cancelQueuedRiskConfig function for emergency cancellations
- Added RiskConfigQueued and RiskConfigCancelled events
- Fixed emit bug in _updateRiskConfig to use actual parameters
- Added validation to prevent applying config before timelock period
- Reset timelock after applying to prevent replay
- Updated tests with additional coverage for cancellation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant