Urban Development Funding Pool

What it does:
Collects and manages pooled funding from investors to finance urban development projects such as roads, parks, housing, and public infrastructure.

Why it matters:
Creates a transparent, accountable funding mechanism for urban development, reducing corruption, improving capital efficiency, and enabling community-backed infrastructure growth.

How it works:

  • A funding pool is created for a specific urban development project

  • Investors contribute funds to the pool on-chain

  • Total contributions are tracked transparently

  • Project milestones and budgets are predefined

  • Funds are released in stages upon milestone approval

  • All fund movements remain publicly auditable

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

/**
 * @title UrbanDevelopmentFundingPool
 * @author Nam
 * @notice On-chain pooled funding for urban development projects
 */
contract UrbanDevelopmentFundingPool {

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

    address public authority; // city authority / project owner

    // -------------------- FUNDING DATA --------------------

    uint256 public totalRaised;
    bool public fundingOpen;

    struct Milestone {
        string description;
        uint256 amount;
        bool approved;
        bool paid;
    }

    Milestone[] public milestones;

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

    mapping(address => uint256) public contributions;

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

    event ContributionReceived(address indexed contributor, uint256 amount);
    event MilestoneAdded(uint256 indexed milestoneId, uint256 amount);
    event MilestoneApproved(uint256 indexed milestoneId);
    event FundsReleased(uint256 indexed milestoneId, uint256 amount);

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

    modifier onlyAuthority() {
        require(msg.sender == authority, "Not authority");
        _;
    }

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

    constructor() {
        authority = msg.sender;
        fundingOpen = true;
    }

    // -------------------- FUNDING LOGIC --------------------

    /**
     * @notice Contribute to the urban development fund
     */
    function contribute() external payable {
        require(fundingOpen, "Funding closed");
        require(msg.value > 0, "Invalid contribution");

        contributions[msg.sender] += msg.value;
        totalRaised += msg.value;

        emit ContributionReceived(msg.sender, msg.value);
    }

    // -------------------- MILESTONE MANAGEMENT --------------------

    /**
     * @notice Add a project milestone
     */
    function addMilestone(string calldata _description, uint256 _amount)
        external
        onlyAuthority
    {
        require(_amount > 0, "Invalid amount");

        milestones.push(
            Milestone({
                description: _description,
                amount: _amount,
                approved: false,
                paid: false
            })
        );

        emit MilestoneAdded(milestones.length - 1, _amount);
    }

    /**
     * @notice Approve a milestone
     */
    function approveMilestone(uint256 _milestoneId)
        external
        onlyAuthority
    {
        Milestone storage milestone = milestones[_milestoneId];
        require(!milestone.approved, "Already approved");

        milestone.approved = true;
        emit MilestoneApproved(_milestoneId);
    }

    // -------------------- FUND RELEASE --------------------

    /**
     * @notice Release funds for an approved milestone
     */
    function releaseFunds(uint256 _milestoneId)
        external
        onlyAuthority
    {
        Milestone storage milestone = milestones[_milestoneId];
        require(milestone.approved, "Milestone not approved");
        require(!milestone.paid, "Already paid");
        require(address(this).balance >= milestone.amount, "Insufficient funds");

        milestone.paid = true;
        payable(authority).transfer(milestone.amount);

        emit FundsReleased(_milestoneId, milestone.amount);
    }
}