---
# System prepended metadata

title: 'Solidity Mastery Handbook: Zero to Advanced'

---

# Solidity Mastery Handbook: Zero to Advanced
## A Security-First Guide for Smart Contract Development

---

## Level 1: The Basics

### 1.1 Pragma Directive

**The 'What':**
A pragma directive tells the Solidity compiler which version to use when compiling your contract. It's the first line in every Solidity file and ensures version compatibility.

**The Syntax:**
```solidity
// Fixed version (most secure)
pragma solidity 0.8.20;

// Version range (use cautiously)
pragma solidity ^0.8.0;

// Multiple constraints
pragma solidity >=0.8.0 <0.9.0;
```

**The 'Why':**
Different compiler versions can introduce breaking changes, new features, or security patches. Locking to a specific version ensures your contract behaves predictably and prevents compilation with untested versions.

**Security & Bugs:**
- **Vulnerability:** Using `^` (caret) allows any 0.8.x version, which might include untested compiler bugs or breaking changes
- **Best Practice:** Always use a fixed version (e.g., `0.8.20`) for production contracts
- **Best Practice:** Use Solidity 0.8.0+ which has built-in overflow/underflow protection
- **Gas Tip:** Newer versions often include gas optimizations; test before upgrading
- **Warning:** Versions below 0.8.0 don't have automatic overflow checks and require SafeMath

---

### 1.2 State Variables

**The 'What':**
State variables are permanently stored in contract storage on the blockchain. They persist between function calls and transactions.

**The Syntax:**
```solidity
contract Storage {
    // State variables
    uint256 public count;           // Automatically gets a getter
    address private owner;          // Only accessible internally
    mapping(address => uint) balances;
    bool internal isActive;
    
    constructor() {
        owner = msg.sender;
        count = 0;
    }
}
```

**The 'Why':**
Use state variables to store data that must persist across transactions, like user balances, ownership records, or contract configuration. They're essential for maintaining contract state.

**Security & Bugs:**
- **Gas Cost:** Reading state variables costs 100-2100 gas (warm/cold); writing costs 20,000 gas (new) or 5,000 gas (update)
- **Vulnerability:** Uninitialized state variables default to zero/false, which can cause logic errors
- **Best Practice:** Always initialize state variables explicitly in the constructor
- **Gas Optimization:** Cache state variables in memory when reading multiple times in a function
- **Security:** Use `private` for sensitive data (though it's still visible on-chain)
- **Vulnerability:** Never store plaintext passwords or secrets in state variables

```solidity
// BAD: Multiple state reads
function badExample() public view returns (uint) {
    return count + count + count; // 3 SLOAD operations
}

// GOOD: Cache in memory
function goodExample() public view returns (uint) {
    uint256 _count = count; // 1 SLOAD
    return _count + _count + _count;
}
```

---

### 1.3 Data Types

#### 1.3.1 Value Types

**The 'What':**
Value types hold their data directly and are copied when assigned or passed to functions.

**The Syntax:**
```solidity
contract DataTypes {
    // Integers
    uint8 smallNumber;      // 0 to 255
    uint256 largeNumber;    // 0 to 2^256-1 (default uint)
    int256 signedNumber;    // -2^255 to 2^255-1
    
    // Address types
    address userAddress;
    address payable recipient; // Can receive Ether
    
    // Boolean
    bool isActive;
    
    // Bytes
    bytes32 hash;           // Fixed-size byte array
    bytes1 singleByte;
    
    // Enums
    enum Status { Pending, Active, Completed }
    Status currentStatus;
}
```

**The 'Why':**
Value types are fundamental building blocks. Use smaller types like `uint8` only when packing variables in storage; otherwise, `uint256` is more gas-efficient in operations.

**Security & Bugs:**
- **Vulnerability:** Integer overflow/underflow (pre-0.8.0) - use SafeMath or upgrade to 0.8.0+
- **Gas Trap:** Using `uint8` instead of `uint256` in calculations costs MORE gas due to conversion
- **Best Practice:** Use `uint256` for calculations, only use smaller types for storage packing
- **Security:** Use `address payable` explicitly when contract needs to send Ether
- **Vulnerability:** Unchecked type conversions can truncate data

```solidity
// DANGEROUS (pre-0.8.0)
uint8 balance = 255;
balance += 1; // Wraps to 0 without SafeMath

// SAFE (0.8.0+)
uint8 balance = 255;
balance += 1; // Reverts with overflow error

// Gas inefficiency example
uint8 a = 1;
uint8 b = 2;
uint8 c = a + b; // Costs more gas than uint256 due to checks
```

#### 1.3.2 Reference Types

**The 'What':**
Reference types don't contain data directly but reference a location where data is stored. Changes to one reference affect all references to the same data.

**The Syntax:**
```solidity
contract ReferenceTypes {
    // Arrays
    uint[] public dynamicArray;
    uint[5] public fixedArray;
    
    // Structs
    struct User {
        address wallet;
        uint256 balance;
        bool isActive;
    }
    
    User[] public users;
    
    // Strings (dynamic byte arrays)
    string public name;
    
    // Bytes (dynamic)
    bytes public data;
    
    function arrayExample() public {
        // Memory arrays
        uint[] memory tempArray = new uint[](5);
        
        // Storage reference
        uint[] storage storageRef = dynamicArray;
        storageRef.push(1); // Modifies state
    }
}
```

**The 'Why':**
Use arrays for lists, structs for complex data, and strings for text. Memory is for temporary data; storage persists on-chain.

**Security & Bugs:**
- **Vulnerability:** Unbounded arrays can cause out-of-gas errors in loops
- **Gas Trap:** Dynamic arrays in storage are expensive; each push costs 20,000+ gas
- **Best Practice:** Never loop over unbounded arrays; implement pagination
- **Memory Safety:** Memory arrays have fixed size and cannot be resized
- **Gas Optimization:** Use `bytes` instead of `string` when possible (strings are just bytes)
- **Vulnerability:** Deleting array elements leaves gaps; use swap-and-pop pattern

```solidity
// DANGEROUS: Unbounded loop
function badIteration() public {
    for(uint i = 0; i < users.length; i++) {
        // Can run out of gas if users array is large
    }
}

// SAFE: Pagination pattern
function safeIteration(uint start, uint count) public view returns (User[] memory) {
    uint end = start + count > users.length ? users.length : start + count;
    User[] memory page = new User[](end - start);
    for(uint i = start; i < end; i++) {
        page[i - start] = users[i];
    }
    return page;
}

// Efficient delete pattern
function removeUser(uint index) public {
    users[index] = users[users.length - 1]; // Swap with last
    users.pop(); // Remove last element
}
```

---

### 1.4 Mappings

**The 'What':**
Mappings are hash tables that store key-value pairs. They provide O(1) lookup time and are the most gas-efficient way to store associative data.

**The Syntax:**
```solidity
contract MappingExamples {
    // Simple mapping
    mapping(address => uint256) public balances;
    
    // Nested mapping
    mapping(address => mapping(address => uint256)) public allowances;
    
    // Mapping with struct values
    struct Account {
        uint256 balance;
        bool exists;
    }
    mapping(address => Account) public accounts;
    
    function updateBalance(address user, uint256 amount) public {
        balances[user] = amount;
    }
    
    function approve(address spender, uint256 amount) public {
        allowances[msg.sender][spender] = amount;
    }
}
```

**The 'Why':**
Mappings are ideal for storing user data, permissions, or any key-value relationships. They're more gas-efficient than arrays for lookups and don't have iteration overhead.

**Security & Bugs:**
- **Critical:** Mappings cannot be iterated; you cannot get all keys or values
- **Default Values:** Non-existent keys return default values (0, false, address(0)), not errors
- **Best Practice:** Use a boolean flag to check if a key exists
- **Gas Efficiency:** Mappings are cheaper than arrays for sparse data
- **Vulnerability:** Forgetting to check existence can lead to logic errors
- **Security:** Nested mappings are common for allowance patterns (ERC-20)

```solidity
// VULNERABLE: Doesn't check if user exists
function badWithdraw() public {
    uint amount = balances[msg.sender]; // Returns 0 if not set
    // Could lead to logic errors
}

// SECURE: Check existence
mapping(address => bool) public hasAccount;

function safeWithdraw() public {
    require(hasAccount[msg.sender], "No account");
    uint amount = balances[msg.sender];
    require(amount > 0, "No balance");
    // Safe to proceed
}

// Track keys if iteration needed
address[] public userList;
mapping(address => bool) public isUser;

function addUser(address user) public {
    if(!isUser[user]) {
        userList.push(user);
        isUser[user] = true;
    }
}
```

---

### 1.5 Basic Math Operations

**The 'What':**
Arithmetic operations allow mathematical calculations. Solidity 0.8.0+ includes automatic overflow/underflow checks.

**The Syntax:**
```solidity
contract MathOperations {
    function basicMath(uint a, uint b) public pure returns (uint) {
        uint sum = a + b;           // Addition (checks overflow)
        uint difference = a - b;    // Subtraction (checks underflow)
        uint product = a * b;       // Multiplication
        uint quotient = a / b;      // Division (rounds down)
        uint remainder = a % b;     // Modulo
        uint power = a ** b;        // Exponentiation
        
        return sum;
    }
    
    // Unchecked block for gas optimization (use carefully!)
    function uncheckedMath(uint a, uint b) public pure returns (uint) {
        unchecked {
            return a + b; // No overflow check, saves gas
        }
    }
}
```

**The 'Why':**
Use standard math for most operations. The `unchecked` block can save gas when you're certain overflow is impossible, but use it sparingly.

**Security & Bugs:**
- **Pre-0.8.0 Critical:** Always use SafeMath library for versions below 0.8.0
- **Division by Zero:** Always reverts automatically in Solidity
- **Rounding:** Division always rounds DOWN towards zero
- **Gas Savings:** `unchecked` saves ~20 gas per operation but removes safety
- **Vulnerability:** Integer overflow in token calculations can drain contracts
- **Best Practice:** Only use `unchecked` in loops with guaranteed bounds
- **Precision Loss:** Use fixed-point math libraries for financial calculations

```solidity
// VULNERABLE (pre-0.8.0 without SafeMath)
uint8 balance = 250;
balance += 10; // Wraps to 4 silently

// SAFE (0.8.0+)
uint8 balance = 250;
balance += 10; // Reverts: "Arithmetic operation overflow"

// Precision loss example
uint price = 100;
uint discount = 33; // 33% discount
uint finalPrice = price - (price * discount / 100); // 67 (precision lost)

// Better: Use basis points (10000 = 100%)
uint DENOMINATOR = 10000;
uint discountBps = 3333; // 33.33%
uint finalPrice = price - (price * discountBps / DENOMINATOR); // More precise

// Safe unchecked usage
function sumArray(uint[] memory arr) public pure returns (uint) {
    uint sum = 0;
    for(uint i = 0; i < arr.length;) {
        sum += arr[i];
        unchecked { i++; } // i won't overflow array length
    }
    return sum;
}
```

---

## Level 2: Functions & Control

### 2.1 Function Visibility Specifiers

**The 'What':**
Visibility specifiers control who can call a function. They're crucial for access control and security.

**The Syntax:**
```solidity
contract VisibilityExample {
    uint private secretValue;
    
    // Public: callable from anywhere
    function publicFunc() public returns (uint) {
        return secretValue;
    }
    
    // External: only callable from outside (cheaper gas)
    function externalFunc(uint[] calldata data) external returns (uint) {
        return data[0];
    }
    
    // Internal: only this contract and derived contracts
    function internalFunc() internal view returns (uint) {
        return secretValue;
    }
    
    // Private: only this contract
    function privateFunc() private view returns (uint) {
        return secretValue;
    }
}
```

**The 'Why':**
Use `external` for functions only called externally (saves gas on calldata). Use `public` when the function needs internal and external access. Use `internal` for shared logic in inheritance. Use `private` for truly internal-only functions.

**Security & Bugs:**
- **Critical Security:** Default visibility is `public` in old versions; always specify explicitly
- **Gas Optimization:** `external` is cheaper than `public` when passing arrays (uses calldata)
- **Vulnerability:** Functions without visibility can be called by anyone
- **Best Practice:** Mark all functions with visibility; use most restrictive possible
- **Common Bug:** Forgetting to restrict admin functions leads to exploits
- **Security:** Private functions are still visible in bytecode; don't store secrets

```solidity
// DANGEROUS: No visibility specified (old Solidity)
function withdraw() { /* anyone can call */ }

// SECURE: Explicit visibility with access control
address public owner;

modifier onlyOwner() {
    require(msg.sender == owner, "Not owner");
    _;
}

function withdraw() external onlyOwner {
    // Only owner can call
}

// Gas comparison
// Public function (can be called internally or externally)
function publicArray(uint[] memory data) public pure returns (uint) {
    return data.length; // Memory copy costs gas
}

// External function (cheaper for external calls)
function externalArray(uint[] calldata data) external pure returns (uint) {
    return data.length; // Direct calldata access
}
```

---

### 2.2 Function Modifiers

**The 'What':**
Modifiers are reusable code that runs before (or after) function execution. They're commonly used for access control, validation, and state checks.

**The Syntax:**
```solidity
contract ModifierExample {
    address public owner;
    bool private locked;
    
    constructor() {
        owner = msg.sender;
    }
    
    // Access control modifier
    modifier onlyOwner() {
        require(msg.sender == owner, "Not authorized");
        _; // Function body executes here
    }
    
    // Reentrancy guard
    modifier nonReentrant() {
        require(!locked, "Reentrant call");
        locked = true;
        _;
        locked = false;
    }
    
    // Validation modifier
    modifier validAddress(address addr) {
        require(addr != address(0), "Invalid address");
        _;
    }
    
    // Using multiple modifiers
    function restrictedFunction(address recipient) 
        external 
        onlyOwner 
        validAddress(recipient) 
        nonReentrant 
    {
        // Function logic
    }
}
```

**The 'Why':**
Modifiers reduce code duplication and make access control patterns reusable. They improve readability by separating validation logic from business logic.

**Security & Bugs:**
- **Vulnerability:** Modifiers execute before the function; order matters with multiple modifiers
- **Reentrancy:** Always place `nonReentrant` modifier first
- **Gas Cost:** Each modifier adds gas overhead; don't overuse
- **Best Practice:** Keep modifiers simple; complex logic should be in functions
- **Bug:** Forgetting `_;` means the function never executes
- **Security:** State changes in modifiers should be carefully considered

```solidity
// VULNERABLE: Wrong modifier order
function withdraw() external nonReentrant onlyOwner {
    // If onlyOwner is checked first, attacker might bypass nonReentrant
}

// SECURE: Correct order
function withdraw() external onlyOwner nonReentrant {
    // Access control first, then reentrancy protection
}

// VULNERABLE: State-changing modifier
modifier badModifier() {
    secretValue++; // State changes in modifier are hard to track
    _;
}

// BETTER: Keep modifiers for checks only
modifier goodModifier() {
    require(condition, "Failed check");
    _;
}

// Advanced pattern: Modifier with cleanup
modifier timedAction() {
    require(block.timestamp >= startTime, "Too early");
    _;
    lastActionTime = block.timestamp; // Post-execution logic
}
```

---

### 2.3 View and Pure Functions

**The 'What':**
`view` functions promise not to modify state. `pure` functions promise not to read or modify state. These guarantees allow the compiler to optimize and enable free off-chain calls.

**The Syntax:**
```solidity
contract StateAccess {
    uint public value = 100;
    
    // View: reads state but doesn't modify
    function getValue() public view returns (uint) {
        return value; // Reading state is allowed
    }
    
    function checkBalance(address user) public view returns (uint) {
        return address(user).balance; // Reading blockchain state
    }
    
    // Pure: no state access at all
    function add(uint a, uint b) public pure returns (uint) {
        return a + b; // Only uses parameters
    }
    
    function hash(string memory data) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(data));
    }
}
```

**The 'Why':**
Use `view` for read-only operations that need state access. Use `pure` for utility functions that don't need state. Both are free when called externally (off-chain), making them perfect for getters and calculations.

**Security & Bugs:**
- **Gas:** `view` and `pure` are free for external calls but cost gas when called internally
- **Compiler Enforcement:** Compiler prevents state modifications in `view` and reads in `pure`
- **Best Practice:** Always mark functions that don't modify state as `view` or `pure`
- **Bug:** Calling non-view functions from view functions costs gas and can fail
- **Security:** View functions can still be exploited via reentrancy when calling external contracts
- **Optimization:** Use `pure` for helpers and libraries when possible

```solidity
// View function behavior
function viewExample() public view returns (uint) {
    // ALLOWED:
    return value;                    // Read state
    uint balance = address(this).balance; // Read blockchain
    
    // NOT ALLOWED (compiler error):
    // value = 10;                   // Modify state
    // payable(msg.sender).transfer(1); // Send Ether
}

// Pure function behavior
function pureExample(uint a) public pure returns (uint) {
    // ALLOWED:
    return a * 2;                    // Use parameters
    uint result = 5 + 5;            // Local calculations
    
    // NOT ALLOWED (compiler error):
    // return value;                 // Read state
    // return address(this).balance; // Read blockchain
}

// Common mistake: marking as view when it should be pure
function badPure() public view returns (uint) {
    return 100; // Should be pure, no state needed
}

function goodPure() public pure returns (uint) {
    return 100; // Correct
}

// Gas consideration
function internalCallCost() public view returns (uint) {
    return getValue(); // Costs gas even though getValue is view
}
```

---

### 2.4 Payable Functions

**The 'What':**
The `payable` modifier allows a function to receive Ether. Without it, transactions sending Ether will revert.

**The Syntax:**
```solidity
contract PayableExample {
    mapping(address => uint) public balances;
    
    // Receive Ether
    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }
    
    // Fallback function (receives Ether sent to contract directly)
    receive() external payable {
        balances[msg.sender] += msg.value;
    }
    
    // Fallback for calls to non-existent functions
    fallback() external payable {
        // Handle unknown function calls
    }
    
    // Send Ether (not payable)
    function withdraw(uint amount) external {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        
        // Three ways to send Ether:
        // 1. transfer (2300 gas, reverts on failure)
        payable(msg.sender).transfer(amount);
        
        // 2. send (2300 gas, returns bool)
        // bool success = payable(msg.sender).send(amount);
        // require(success, "Send failed");
        
        // 3. call (forwards all gas, returns bool) - RECOMMENDED
        // (bool success, ) = payable(msg.sender).call{value: amount}("");
        // require(success, "Transfer failed");
    }
}
```

**The 'Why':**
Use `payable` when your function needs to receive Ether. Always validate amounts and update state before transferring to prevent reentrancy attacks.

**Security & Bugs:**
- **Critical:** Always use Checks-Effects-Interactions pattern to prevent reentrancy
- **Gas Limits:** `transfer` and `send` limit gas to 2300, which can fail with smart contract recipients
- **Best Practice:** Use `call` for sending Ether in modern Solidity (with reentrancy guards)
- **Vulnerability:** `transfer` can break with future EVM changes; `call` is more future-proof
- **Security:** Always check return values when using `call` or `send`
- **Bug:** Forgetting `payable` on address types prevents sending Ether

```solidity
// VULNERABLE: Reentrancy attack
function vulnerableWithdraw() external {
    uint amount = balances[msg.sender];
    (bool success, ) = msg.sender.call{value: amount}(""); // External call before state change
    require(success);
    balances[msg.sender] = 0; // TOO LATE! Attacker can reenter
}

// SECURE: Checks-Effects-Interactions pattern
function secureWithdraw() external nonReentrant {
    uint amount = balances[msg.sender];
    require(amount > 0, "No balance"); // Checks
    
    balances[msg.sender] = 0; // Effects (state change FIRST)
    
    (bool success, ) = msg.sender.call{value: amount}(""); // Interactions
    require(success, "Transfer failed");
}

// Modern recommendation: use call with reentrancy guard
function recommendedWithdraw() external {
    uint amount = balances[msg.sender];
    require(amount > 0, "No balance");
    
    balances[msg.sender] = 0; // Update state first
    
    (bool success, ) = payable(msg.sender).call{value: amount}("");
    require(success, "Transfer failed");
}

// receive vs fallback
// receive: called when msg.data is empty
receive() external payable {
    emit Received(msg.sender, msg.value);
}

// fallback: called when no other function matches
fallback() external payable {
    emit FallbackCalled(msg.sender, msg.value, msg.data);
}
```

---

### 2.5 Error Handling: Require, Revert, and Assert

**The 'What':**
Solidity provides three methods for error handling. `require` validates conditions, `revert` provides custom errors, and `assert` checks invariants.

**The Syntax:**
```solidity
contract ErrorHandling {
    uint public value;
    address public owner;
    
    // Custom errors (gas efficient, Solidity 0.8.4+)
    error Unauthorized(address caller);
    error InsufficientBalance(uint requested, uint available);
    
    constructor() {
        owner = msg.sender;
    }
    
    // Require: validate inputs and conditions
    function setValue(uint newValue) external {
        require(msg.sender == owner, "Not owner");
        require(newValue > 0, "Value must be positive");
        require(newValue <= 1000, "Value too large");
        value = newValue;
    }
    
    // Revert: explicit revert with custom error
    function setValueWithCustomError(uint newValue) external {
        if(msg.sender != owner) {
            revert Unauthorized(msg.sender);
        }
        if(newValue == 0 || newValue > 1000) {
            revert("Invalid value");
        }
        value = newValue;
    }
    
    // Assert: check invariants (should never fail)
    function criticalOperation() external {
        uint oldValue = value;
        // ... complex operations ...
        assert(value >= oldValue); // Invariant: value should never decrease
    }
}
```

**The 'Why':**
Use `require` for input validation and access control. Use custom errors with `revert` for gas-efficient error handling. Use `assert` for invariants that should never be false (failing assert indicates a bug).

**Security & Bugs:**
- **Gas Efficiency:** Custom errors save ~2000 gas compared to string errors
- **Assert vs Require:** `assert` consumes all remaining gas (pre-0.8.0), while `require` refunds unused gas
- **Best Practice:** Use `require` for user errors, `assert` for internal consistency
- **Vulnerability:** Error messages are visible on-chain; don't include sensitive data
- **Modern Pattern:** Prefer custom errors for production contracts
- **Bug:** Using `assert` for input validation wastes gas on failure

```solidity
// Gas comparison
// Expensive: string error
function expensiveCheck(uint amount) external {
    require(amount > 100, "Amount must be greater than 100"); // ~50 gas for string
}

// Cheap: custom error
error AmountTooLow(uint amount, uint minimum);
function cheapCheck(uint amount) external {
    if(amount <= 100) {
        revert AmountTooLow(amount, 100); // ~30 gas, saves ~20 gas
    }
}

// WRONG: Using assert for validation
function wrongAssert(uint value) external {
    assert(value > 0); // Bad: consumes all gas if fails
}

// RIGHT: Using require for validation
function rightRequire(uint value) external {
    require(value > 0, "Value must be positive"); // Refunds gas
}

// Assert for invariants
mapping(address => uint) public balances;
uint public totalSupply;

function transfer(address to, uint amount) external {
    require(balances[msg.sender] >= amount, "Insufficient balance");
    
    balances[msg.sender] -= amount;
    balances[to] += amount;
    
    // Invariant: total supply never changes in transfer
    assert(balances[msg.sender] + balances[to] == totalSupply);
}

// Revert with conditional logic
function complexValidation(uint a, uint b) external {
    if(a > b) {
        revert("A must not exceed B");
    } else if(a == 0) {
        revert("A cannot be zero");
    } else if(b > 1000) {
        revert("B too large");
    }
    // Continue if all checks pass
}
```

---

## Level 3: Contract Interaction

### 3.1 Inheritance

**The 'What':**
Inheritance allows contracts to inherit properties and functions from parent contracts. Solidity supports multiple inheritance with a specific linearization order (C3 linearization).

**The Syntax:**
```solidity
// Base contract
contract Ownable {
    address public owner;
    
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    constructor() {
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Invalid address");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// Single inheritance
contract Token is Ownable {
    mapping(address => uint) public balances;
    
    function mint(address to, uint amount) external onlyOwner {
        balances[to] += amount;
    }
}

// Multiple inheritance
contract Pausable {
    bool public paused;
    
    modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }
    
    function pause() internal {
        paused = true;
    }
}

contract AdvancedToken is Ownable, Pausable {
    mapping(address => uint) public balances;
    
    function transfer(address to, uint amount) external whenNotPaused {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        balances[to] += amount;
    }
    
    function emergencyPause() external onlyOwner {
        pause();
    }
    
    // Override parent function
    function transferOwnership(address newOwner) public override onlyOwner {
        require(newOwner != address(0), "Invalid address");
        require(!paused, "Cannot transfer while paused");
        super.transferOwnership(newOwner); // Call parent implementation
    }
}
```

**The 'Why':**
Inheritance promotes code reuse and creates hierarchical relationships. Use it to implement common patterns like ownership, pausability, and access control without duplicating code.

**Security & Bugs:**
- **Linearization:** With multiple inheritance, Solidity uses C3 linearization (right-to-left, depth-first)
- **State Variables:** Child contracts can access parent's state; be careful with visibility
- **Constructor Order:** Parent constructors execute before child constructors
- **Vulnerability:** Diamond problem in multiple inheritance can cause unexpected behavior
- **Best Practice:** Keep inheritance hierarchies shallow (2-3 levels max)
- **Security:** Override functions must include `override` keyword in 0.6.0+
- **Gas:** Deep inheritance increases deployment costs

```solidity
// COMPLEX: Multiple inheritance order matters
contract A {
    function foo() public virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function foo() public virtual override returns (string memory) {
        return "B";
    }
}

contract C is A {
    function foo() public virtual override returns (string memory) {
        return "C";
    }
}

// Order matters!
contract D is B, C {
    // C3 linearization: D -> C -> B -> A
    // foo() will return "C" because C is rightmost
    function foo() public override(B, C) returns (string memory) {
        return super.foo(); //