🎓 A1Learner
🔍
0 of 48 lessons completed

Solidity Linearization

Linearization is the order Solidity lines up a contract's parents and the contract itself. That order decides which version of a shared function runs first.

Super calls the next contract in line

B sits on top of A. Its label adds B after A's label.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract A {
    function label() public pure virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function label() public pure override returns (string memory) {
        return string.concat(super.label(), "B");
    }
}

A diamond runs each version once, in order

D inherits from B and C. The chain runs A, then B, then C, then D.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract A {
    function label() public pure virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function label() public pure override virtual returns (string memory) {
        return string.concat(super.label(), "B");
    }
}

contract C is A {
    function label() public pure override virtual returns (string memory) {
        return string.concat(super.label(), "C");
    }
}

contract D is B, C {
    function label() public pure override(B, C) returns (string memory) {
        return string.concat(super.label(), "D");
    }
}

The most-derived version wins the call

D2 replaces the chain with its own label. A caller of D2 gets only D.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract A {
    function label() public pure virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function label() public pure override virtual returns (string memory) {
        return string.concat(super.label(), "B");
    }
}

contract C is A {
    function label() public pure override virtual returns (string memory) {
        return string.concat(super.label(), "C");
    }
}

contract D2 is B, C {
    function label() public pure override(B, C) returns (string memory) {
        return "D";
    }
}

Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract Start {
    function trace() public pure virtual returns (string memory) {
        return "start";
    }
}

contract Walk is Start {
    function trace() public pure override virtual returns (string memory) {
        return string.concat(super.trace(), "-walk");
    }
}

contract Run is Start {
    function trace() public pure override virtual returns (string memory) {
        return string.concat(super.trace(), "-run");
    }
}

contract Done is Walk, Run {
    function trace() public pure override(Walk, Run) returns (string memory) {
        return string.concat(super.trace(), "-done");
    }
}

Key points

  • Order: Solidity lines up the most-derived contract first and its bases after it.
  • Super: super.f() calls the next contract in that order, not necessarily the parent you wrote.
  • Most-derived wins: When several parents define a function, the most-derived contract's version is the one a caller gets.
  • One chain: In a diamond, a shared function runs once through the chain instead of once per parent.

In this example, Start returns the first step. Walk and Run each add one step after the result of super.trace(). Done inherits from Walk and Run. Its super call walks the lined-up order, so the full trace reads start, then walk, then run, then done.

Note

The is list runs most-base-like first, but the call order runs most-derived first.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Remix IDE

Exercise

D inherits from B and C, and both sit on A. What does super.label() inside D call?