Shared Expense Settlement

What it does:
Enables groups to record, split, and settle shared expenses transparently on-chain, automating contributions, reimbursements, and balances.

Why it matters:
Eliminates disputes over who paid what, ensures fair settlement, prevents errors, and provides immutable records for all participants.

How it works:

  • Group members add expenses specifying amount, payer, and involved participants

  • Smart contract calculates owed balances automatically

  • Members can settle their shares by sending funds to the contract

  • Automatic reimbursement is triggered when contributions cover owed amounts

  • Integrates with Personal Wallets, Tokenized Payments, or Event Planning Escrow

  • Dashboards display group balances, pending payments, and history of settlements

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

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title SharedExpenseSettlement
 * @author Nam
 * @notice Tracks group expenses and automates settlement on-chain
 */
contract SharedExpenseSettlement is Ownable {

    struct Expense {
        string description;
        uint256 amount;
        address payer;
        address[] participants;
        bool settled;
    }

    mapping(uint256 => Expense) public expenses;
    uint256 public expenseCount;

    mapping(address => mapping(address => uint256)) public balances; // who owes whom

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

    event ExpenseAdded(uint256 indexed expenseId, string description, uint256 amount, address payer);
    event SettlementPaid(address from, address to, uint256 amount);

    // -------------------- EXPENSE MANAGEMENT --------------------

    function addExpense(string calldata _description, uint256 _amount, address[] calldata _participants) external {
        require(_amount > 0, "Amount must be > 0");
        require(_participants.length > 0, "No participants");

        expenseCount += 1;
        expenses[expenseCount] = Expense({
            description: _description,
            amount: _amount,
            payer: msg.sender,
            participants: _participants,
            settled: false
        });

        uint256 share = _amount / _participants.length;
        for (uint256 i = 0; i  0, "No balance owed");
        require(msg.value == owed, "Incorrect payment amount");

        balances[msg.sender][_to] = 0;
        payable(_to).transfer(msg.value);

        emit SettlementPaid(msg.sender, _to, msg.value);
    }

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

    function getOwedBalance(address _from, address _to) external view returns (uint256) {
        return balances[_from][_to];
    }
}