Land Registry on Blockchain

What it does:

Records, verifies, and transfers land ownership on-chain, ensuring that property records are immutable, transparent, and tamper-proof.

Why it matters:

Eliminates fraud, duplicate titles, and opaque paperwork by creating a single source of truth for land ownership that anyone can verify but no one can secretly alter.

How it works:

Land parcels are registered with unique IDs and metadata at deployment or by an authorized registrar.

Each land parcel is linked to a single owner address on-chain.

Ownership transfers require the current owner’s consent and are permanently recorded.

Historical ownership remains publicly auditable, creating trust and legal clarity.

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

/**
 * @title LandRegistry
 * @author Nam
 * @notice Decentralized land ownership registry on blockchain
 */
contract LandRegistry {

    // -------------------- ROLES --------------------

    address public registrar; // government / authority / trusted entity

    // -------------------- LAND STRUCT --------------------

    struct Land {
        uint256 landId;
        address owner;
        string metadata;   // IPFS hash / land description
        bool exists;
    }

    // -------------------- STORAGE --------------------

    mapping(uint256 => Land) public lands;

    // -------------------- EVENTS --------------------

    event LandRegistered(uint256 indexed landId, address indexed owner);
    event OwnershipTransferred(
        uint256 indexed landId,
        address indexed from,
        address indexed to
    );

    // -------------------- MODIFIERS --------------------

    modifier onlyRegistrar() {
        require(msg.sender == registrar, "Not registrar");
        _;
    }

    modifier landExists(uint256 _landId) {
        require(lands[_landId].exists, "Land not registered");
        _;
    }

    modifier onlyOwner(uint256 _landId) {
        require(msg.sender == lands[_landId].owner, "Not land owner");
        _;
    }

    // -------------------- CONSTRUCTOR --------------------

    constructor() {
        registrar = msg.sender;
    }

    // -------------------- REGISTRATION LOGIC --------------------

    /**
     * @notice Register a new land parcel
     * @param _landId Unique land identifier
     * @param _owner Initial owner address
     * @param _metadata Property details (IPFS hash / legal description)
     */
    function registerLand(
        uint256 _landId,
        address _owner,
        string calldata _metadata
    ) external onlyRegistrar {
        require(!lands[_landId].exists, "Land already exists");
        require(_owner != address(0), "Invalid owner");

        lands[_landId] = Land({
            landId: _landId,
            owner: _owner,
            metadata: _metadata,
            exists: true
        });

        emit LandRegistered(_landId, _owner);
    }

    // -------------------- OWNERSHIP TRANSFER --------------------

    /**
     * @notice Transfer land ownership to a new owner
     * @param _landId Land identifier
     * @param _newOwner New owner address
     */
    function transferOwnership(
        uint256 _landId,
        address _newOwner
    )
        external
        landExists(_landId)
        onlyOwner(_landId)
    {
        require(_newOwner != address(0), "Invalid new owner");

        address previousOwner = lands[_landId].owner;
        lands[_landId].owner = _newOwner;

        emit OwnershipTransferred(_landId, previousOwner, _newOwner);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    /**
     * @notice Get land details
     */
    function getLand(uint256 _landId)
        external
        view
        landExists(_landId)
        returns (
            uint256 landId,
            address owner,
            string memory metadata
        )
    {
        Land memory land = lands[_landId];
        return (land.landId, land.owner, land.metadata);
    }
}