Skip to content

Enhancement: Add C3 Linearization Order Printer #2784

@dguido

Description

@dguido

Summary

Add a printer that displays the C3 linearization order for contract inheritance, helping developers understand the method resolution order (MRO) and inheritance hierarchy in complex Solidity projects.

Motivation

Solidity uses C3 linearization for multiple inheritance resolution, which determines:

  • Function override order - Which implementation is called
  • State variable initialization order - Critical for contract correctness
  • Constructor execution order - Important for proper initialization
  • Super call resolution - Which parent implementation super refers to

Understanding C3 linearization is crucial but challenging:

  • The algorithm is non-intuitive for complex hierarchies
  • Order affects contract behavior significantly
  • Mistakes can lead to unexpected function calls
  • Critical for upgrade patterns and proxy contracts

C3 Linearization Background

C3 linearization creates a linear order from a directed acyclic graph (DAG) of inheritance, ensuring:

  1. Precedence preservation - Children come before parents
  2. Monotonicity - Consistent ordering across inheritance chains

Example Inheritance Scenario

// Diamond inheritance pattern
contract A { function foo() virtual {} }
contract B is A { function foo() override {} }
contract C is A { function foo() override {} }
contract D is B, C { function foo() override(B, C) {} }

// C3 Linearization for D: [D, C, B, A]
// This means C.foo() overrides B.foo() when both are inherited

Expected Output Formats

Basic Format

C3 Linearization for TokenVault
================================================
 0. → [SELF] TokenVault (contracts/TokenVault.sol:45)
 1.   [BASE] Pausable (contracts/security/Pausable.sol:12)
 2.   [BASE] ReentrancyGuard (contracts/security/ReentrancyGuard.sol:8)
 3.   [BASE] AccessControl (contracts/access/AccessControl.sol:20)
 4.   [BASE] Context (contracts/utils/Context.sol:5)
 5.   [ROOT] ERC165 (contracts/interfaces/ERC165.sol:3)

Detailed Format (--verbose)

C3 Linearization for TokenVault
================================================

 0. → [SELF] TokenVault (contracts/TokenVault.sol:45)
      Functions: 15 | Modifiers: 2 | State Variables: 5
      Constructor: ✓ Explicit
      Overrides: deposit(), withdraw(), pause()
      New Functions: emergencyWithdraw(), setFee()

 1.   [BASE] Pausable (contracts/security/Pausable.sol:12)
      Functions: 4 | Modifiers: 1 | State Variables: 1
      Constructor: ✗ None
      Provides: pause(), unpause(), paused(), whenNotPaused modifier
      Inherited by: TokenVault

 2.   [BASE] ReentrancyGuard (contracts/security/ReentrancyGuard.sol:8)
      Functions: 0 | Modifiers: 1 | State Variables: 1
      Constructor: ✓ Initializes _status
      Provides: nonReentrant modifier
      Note: Constructor sets initial reentrancy status

[... continues ...]

Constructor Execution Order:
-----------------------------
1. ERC165.constructor()
2. Context.constructor()
3. AccessControl.constructor()
4. ReentrancyGuard.constructor()
5. Pausable.constructor()
6. TokenVault.constructor(address _token, uint256 _fee)

Super Call Resolution:
----------------------
- super.deposit() in TokenVault calls → Pausable.deposit()
- super._msgSender() in TokenVault calls → Context._msgSender()

Advanced Features

1. Conflict Detection

Detect potential issues in linearization such as:

  • Functions that might be shadowed unexpectedly
  • Ambiguous super calls
  • Constructor order dependencies

2. Constructor Order Analysis

Determine the exact order of constructor execution, which is the reverse of the linearization order.

3. Super Resolution Helper

Trace where super.function() calls resolve to in the inheritance chain.

Command-Line Interface

# Basic linearization
slither . --print c3-linearization

# With details
slither . --print c3-linearization --verbose

# Specific contract
slither . --print c3-linearization --contract TokenVault

# Include interfaces
slither . --print c3-linearization --include-interfaces

# Show constructor order
slither . --print c3-linearization --show-constructors

# Detect conflicts
slither . --print c3-linearization --detect-conflicts

Test Cases

// Complex diamond inheritance
contract A { function foo() virtual {} }
contract B is A { function foo() override {} }
contract C is A { function foo() override {} }
contract D is B, C { function foo() override(B, C) {} }

// Expected output for D:
// 0. D (current contract)
// 1. C (rightmost parent)
// 2. B (next parent)  
// 3. A (common base)

// Multiple inheritance levels
contract Base { }
contract Left is Base { }
contract Right is Base { }
contract Child is Left, Right { }
contract GrandChild is Child { }

// Expected output for GrandChild:
// 0. GrandChild
// 1. Child
// 2. Right
// 3. Left
// 4. Base

Benefits

  1. Understand override behavior - Know exactly which function is called
  2. Debug inheritance issues - Identify unexpected shadowing
  3. Verify constructor order - Ensure proper initialization
  4. Design better hierarchies - Avoid linearization conflicts
  5. Educational value - Learn C3 linearization through examples

Integration Features

  1. IDE Integration - Export to JSON for IDE tooltips
  2. Documentation Generation - Auto-generate inheritance docs
  3. Verification Tools - Validate upgrade compatibility

Priority

Medium - While not identifying vulnerabilities directly, understanding C3 linearization is crucial for correctly reasoning about contract behavior, especially in complex inheritance hierarchies common in DeFi protocols. This printer provides immediate educational value and helps prevent inheritance-related bugs. It's particularly valuable for upgrade patterns and proxy contracts where linearization order affects functionality.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions