Vyper theorytheory 0/50 · 0%
Foundations · hard

41. No inheritance: composing via interfaces and calls

How Vyper achieves modularity without base contracts.

Instead of inheriting shared logic, Vyper contracts compose by calling out to other deployed contracts through interfaces, or by copy-adapting a well-reviewed pattern into each contract explicitly. This trades some code duplication for the guarantee that every contract's logic is fully visible in its own file.

interface Registry:
    def is_allowed(user: address) -> bool: view

registry: public(address)

@external
def restricted_action():
    assert Registry(self.registry).is_allowed(msg.sender), "not allowed"

This pattern also naturally supports upgradeable 'policy' contracts: swap the registry address and behaviour changes without touching the calling contract's code.

Check your understanding

  1. 1. How does Vyper share logic across contracts without inheritance?

  2. 2. What's a benefit of the 'each contract fully visible in its own file' approach?

  3. 3. What does swapping a registry contract's address enable?