Tokenized Property Ownership

What it does:
A smart contract that tokenizes ownership of a real-world property into digital shares, allowing fractional ownership, transparent transfers, and automated revenue distribution.

Why it matters:
Real estate is illiquid and exclusive. Tokenization lowers entry barriers, improves liquidity, and makes ownership rights transparent and programmable.

How it works:

  • A property is represented by a fixed supply of ownership tokens.

  • Each token equals a fractional claim on the property.

  • Tokens can be transferred between owners.

  • Rental or sale income is distributed proportionally to token holders.

  • Ownership and payouts are fully auditable on-chain.

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

/**
 * @title TokenizedPropertyOwnership
 * @author Nam
 * @notice Fractional property ownership with on-chain income distribution
 */

interface IERC20Minimal {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
}

contract TokenizedPropertyOwnership {

    // -------------------- STATE VARIABLES --------------------

    IERC20Minimal public immutable ownershipToken;
    address public propertyManager;

    uint256 public totalIncomeReceived;
    mapping(address => uint256) public claimedIncome;

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

    event IncomeReceived(uint256 amount);
    event IncomeClaimed(address indexed holder, uint256 amount);

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

    modifier onlyManager() {
        require(msg.sender == propertyManager, "Not manager");
        _;
    }

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

    constructor(address _ownershipToken) {
        require(_ownershipToken != address(0), "Invalid token");
        ownershipToken = IERC20Minimal(_ownershipToken);
        propertyManager = msg.sender;
    }

    // -------------------- INCOME COLLECTION --------------------

    /**
     * @notice Receive rental or sale income
     */
    receive() external payable {
        require(msg.value > 0, "No income");
        totalIncomeReceived += msg.value;
        emit IncomeReceived(msg.value);
    }

    // -------------------- INCOME DISTRIBUTION --------------------

    /**
     * @notice Claim proportional income
     */
    function claimIncome() external {
        uint256 holderBalance = ownershipToken.balanceOf(msg.sender);
        require(holderBalance > 0, "Not a holder");

        uint256 entitled =
            (totalIncomeReceived * holderBalance) /
            ownershipToken.totalSupply();

        uint256 payableAmount =
            entitled - claimedIncome[msg.sender];

        require(payableAmount > 0, "Nothing to claim");

        claimedIncome[msg.sender] += payableAmount;
        payable(msg.sender).transfer(payableAmount);

        emit IncomeClaimed(msg.sender, payableAmount);
    }

    // -------------------- ADMIN --------------------

    /**
     * @notice Change property manager
     */
    function updateManager(address _newManager)
        external
        onlyManager
    {
        require(_newManager != address(0), "Invalid manager");
        propertyManager = _newManager;
    }
}