Skip to content

Conversation

ignasirv
Copy link
Collaborator

@ignasirv ignasirv commented Jul 21, 2025

Add Emergency Recovery Functions to Sovereign Bridge

📋 Overview

This PR introduces critical emergency recovery capabilities to the BridgeL2SovereignChain contract, enabling administrative intervention in edge cases and recovery scenarios for sovereign chain bridges when for any reason, Pessimistic Proof (PP) computation fails or tree states become inconsistent.

✨ New Features

🔧 Emergency Administrative Functions

  1. setMultipleClaims(uint256[] globalIndexes)

    • Allows setting multiple claims in the claimedBitmap
    • Opposite functionality to existing unsetMultipleClaims
    • Enables recovery from missed or incorrectly unset claims
  2. backwardLET(uint256 newDepositCount, bytes32[32] newFrontier, bytes32 nextLeaf, bytes32[32] proof)

    • Enables rollback of the Local Exit Tree (LET) to a previous state
    • Uses subtree inclusion verification for cryptographic security
    • Validates that nextLeaf exists at position newDepositCount in current tree
    • Verifies newFrontier consistency with Merkle proof siblings
    • Only allows rollback (newDepositCount < currentDepositCount)
  3. forwardLET(bytes32[] newLeaves, bytes32 expectedStateRoot)

  4. setLocalBalanceTree(uint32[] originNetwork, address[] originTokenAddress, uint256[] amount)

    • Direct manipulation of local balance tree entries
    • Batch updates for multiple token balances
    • Critical for fixing balance inconsistencies between networks

🏗️ Infrastructure Changes

  1. _isValidSubtreeFrontier() in DepositContractBase
    • Core subtree validation functionality
    • Ensures frontier consistency with Merkle proof siblings
    • Reusable cryptographic primitive for tree operations

🔒 Security Model

Access Control

  • All functions protected by onlyGlobalExitRootRemover modifier
  • Only authorized recovery operators can execute emergency functions

Cryptographic Security

  • Subtree Inclusion Proofs: backwardLET uses rigorous mathematical validation
  • Health Checks: forwardLET validates final state against expected root
  • Input Validation: Array length checks, deposit count constraints

Risk Mitigation

  • Rollback Only: backwardLET prevents unauthorized forward movement
  • Proof Requirements: Cryptographic evidence required for all tree modifications
  • Event Logging: All operations emit detailed events for transparency

📊 Events Added

  • BackwardLET(uint256 newDepositCount, bytes32 newRoot)
  • ForwardLET(uint256 newDepositCount, bytes32 newRoot)
  • SetClaim(uint32 leafIndex, uint32 sourceNetwork)
  • SetLocalBalanceTree(uint32 indexed originNetwork, address indexed originTokenAddress, uint256 newAmount)

🚨 Custom Errors Added

  • InvalidDepositCount(): Invalid deposit count for tree operations
  • InvalidInclusionProof(): Merkle proof validation failed
  • InvalidLeavesLength(): Empty or invalid leaves array
  • InvalidExpectedRoot(): Computed root doesn't match expected
  • InvalidSubtreeFrontier(): Frontier inconsistent with proof siblings

🧪 Testing

Comprehensive Test Coverage

  • Permission Controls: Verified only GlobalExitRootRemover can execute
  • Subtree Validation: Cryptographic proof verification in backwardLET
  • Incremental Updates: Efficient leaf addition in forwardLET
  • Input Validation: Array length mismatches, invalid parameters
  • Success Scenarios: Normal operation with proper event emission
  • Error Cases: Invalid proofs, wrong deposit counts, health check failures
  • Edge Cases: Empty arrays, boundary conditions, maximum tree capacity
  • Integration: Complex scenarios combining all functions
  • Interoperability: Compatibility with existing bridge operations

🎯 Use Cases

These functions address critical recovery scenarios:

  1. Tree Rollback: Recover from corrupted or invalid LET states using backwardLET
  2. Bulk Synchronization: Efficiently sync multiple deposits using forwardLET
  3. Claim Recovery: Restore accidentally unset claims with setMultipleClaims
  4. Balance Reconciliation: Fix local balance tree inconsistencies
  5. Emergency Response: Quick recovery from various edge cases without redeployment

🔄 Function Lifecycle

Typical Recovery Flow:

  1. Diagnose: Identify tree inconsistency or missing claims
  2. Rollback: Use backwardLET to return to known good state
  3. Resync: Use forwardLET to replay valid operations
  4. Balance Fix: Use setLocalBalanceTree to correct token balances
  5. Claim Restore: Use setMultipleClaims to restore valid claims

⚠️ Important Notes

  • Emergency Use Only: These functions are designed for exceptional circumstances
  • Cryptographic Security: All tree operations require mathematical proofs
  • Public Visibility: All changes are transparent via events and on-chain verification
  • No Normal Operations: These do not affect day-to-day bridge functionality
  • GER Updates: All LET modifications automatically update Global Exit Root

📝 Migration Notes

  • Removed: setLocalExitTree function (replaced by backwardLET/forwardLET)
  • No Breaking Changes: Existing functionality remains intact
  • Backward Compatible: All existing bridge operations continue normally

🔧 Technical Details

Subtree Inclusion Algorithm

backwardLET implements a sophisticated validation:

  1. Next Leaf Verification: Proves nextLeaf exists at newDepositCount position
  2. Frontier Consistency: Ensures newFrontier matches proof siblings at appropriate heights
  3. Mathematical Soundness: Leverages Merkle tree properties for cryptographic security

Optimization Features

  • Incremental Updates: forwardLET uses existing _addLeaf for efficiency
  • Batch Operations: All functions support bulk updates to minimize gas costs
  • Health Checks: Built-in validation prevents invalid state transitions

Version: BRIDGE_SOVEREIGN_VERSION = "v10.2.2" - Updated to reflect new emergency recovery capabilities
Testing: 100% test coverage for all new functionality
Security: Cryptographically secure with comprehensive input validation

Copilot

This comment was marked as outdated.

@ignasirv ignasirv requested a review from Copilot July 23, 2025 15:18
Copilot

This comment was marked as outdated.

@ignasirv ignasirv force-pushed the feature/outposts branch 5 times, most recently from 01d8c18 to a0570bc Compare July 23, 2025 15:42
bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata newFrontier
) external onlyGlobalExitRootRemover {
_resetTree(newDepositCount, newFrontier);
// emit event
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be worth to call GER to udpate local exit tree

Copy link
Collaborator

@laisolizq laisolizq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ignasirv ignasirv changed the title Add permissioned functions for claim and tree updates [Outpost] sovereign bridge changes Jul 28, 2025
@ignasirv ignasirv requested a review from Copilot July 28, 2025 16:55
Copilot

This comment was marked as outdated.

Comment on lines +148 to +168
function _isValidSubtreeFrontier(
uint256 subTreeLeafCount,
bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata subTreeFrontier,
bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata currentTreeProof
) internal pure returns (bool) {
// Verify subtree frontier consistency with the proof
uint256 index = subTreeLeafCount;
uint256 height = 0;

// Check each height where subtree frontier should have elements
while (index != 0 && height < _DEPOSIT_CONTRACT_TREE_DEPTH) {
if ((index & 1) == 1) {
// At this height, subtree has an element that must match proof sibling
if (subTreeFrontier[height] != currentTreeProof[height]) {
return false; // Frontier element doesn't match proof
}
}
// If bit is 0, subtree doesn't have element at this height (skip check)

height++;
index >>= 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess this is the first approach, it should be marked as darft the PR

steps will be like::
Take the frist bit ( in reversed order) is different from both deposit counts.
Once that happen, proof inside that "branch" provide the merkle proof using the leftover frontier to get to the previous branch roort

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of picking the first bit in reverse order, I am picking the last one in normal order, I don't see what you mean.

@ignasirv ignasirv changed the base branch from feature/ongoing-v0.3.0 to feature/v12 July 29, 2025 09:14
invocamanman and others added 27 commits August 25, 2025 12:30
Introduces `_rollbackTree` to revert the Merkle tree state, with guards
against invalid rollback operations. Implements permissioned functions
to set claims and update local exit and balance trees, emitting events
to signal changes. Extends tests to ensure proper permissions, event
emissions, and correct functionality.

Enhances contract security by restricting sensitive actions to
authorized roles, leveraging robust revert conditions to maintain
consistency.

Relates to issue #123
Also use leave struct at forwardLER
Introduces `_rollbackTree` to revert the Merkle tree state, with guards
against invalid rollback operations. Implements permissioned functions
to set claims and update local exit and balance trees, emitting events
to signal changes. Extends tests to ensure proper permissions, event
emissions, and correct functionality.

Enhances contract security by restricting sensitive actions to
authorized roles, leveraging robust revert conditions to maintain
consistency.

Relates to issue #123
Added checks

wip
@krlosMata krlosMata changed the title [Outpost L2] sovereign bridge changes [v0.3.5 phaseI III]:newConsensusType-outpostsL2 Aug 26, 2025
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.

6 participants