Skip to content

Mappings and Structs in Solidity

This example demonstrates mappings, structs, and user-defined types in Solidity, including nested mappings and complex data structures.

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

contract MappingsAndStructs {
    // Simple mapping
    mapping(address => uint256) public balances;

    // Nested mapping
    mapping(address => mapping(address => bool)) public isApproved;

    // Struct definition
    struct User {
        string name;
        uint256 age;
        address wallet;
        bool isActive;
    }

    // Mapping using struct
    mapping(address => User) public users;

    // Array of custom struct
    User[] public userList;

    // Events
    event UserCreated(address indexed userAddress, string name);
    event BalanceUpdated(address indexed user, uint256 newBalance);

    // Add balance to address
    function addBalance(uint256 _amount) public {
        balances[msg.sender] += _amount;
        emit BalanceUpdated(msg.sender, balances[msg.sender]);
    }

    // Approve address to manage funds
    function approve(address _spender) public {
        isApproved[msg.sender][_spender] = true;
    }

    // Create new user
    function createUser(string memory _name, uint256 _age) public {
        User memory newUser = User({
            name: _name,
            age: _age,
            wallet: msg.sender,
            isActive: true
        });

        users[msg.sender] = newUser;
        userList.push(newUser);

        emit UserCreated(msg.sender, _name);
    }

    // Update user information
    function updateUser(string memory _newName, uint256 _newAge) public {
        require(users[msg.sender].wallet == msg.sender, "User does not exist");

        users[msg.sender].name = _newName;
        users[msg.sender].age = _newAge;
    }

    // Get user count
    function getUserCount() public view returns (uint256) {
        return userList.length;
    }

    // Check if user exists and is active
    function isUserActive(address _userAddress) public view returns (bool) {
        return users[_userAddress].isActive;
    }
}

Key Concepts

  1. Simple Mappings

    • Key-value pairs
    • Automatically initialized
    • Cannot be iterated
    • O(1) lookup time
  2. Nested Mappings

    • Mapping within a mapping
    • Useful for relationships
    • Multiple key lookups
    • Common in approval systems
  3. Structs

    • Custom data structures
    • Group related data
    • Can contain different types
    • Value and reference types
  4. Mapping with Structs

    • Complex data storage
    • Efficient lookups
    • Organized data structure
    • Common in dApp development

Best Practices

  1. Initialize struct values explicitly
  2. Use events to track state changes
  3. Validate data before storage
  4. Consider gas costs with nested structures
  5. Use appropriate data types for storage efficiency

Common Use Cases

  1. Simple Mapping

    • Token balances
    • User permissions
    • Simple key-value storage
  2. Nested Mapping

    • Token allowances
    • Multi-party permissions
    • Complex relationships
  3. Structs

    • User profiles
    • Game characters
    • Complex business objects
  4. Combined Usage

    • Decentralized exchanges
    • Gaming inventories
    • Complex dApp storage