Micro-Investment Round-Up Contract

What it does:
A smart contract that automatically rounds up everyday payments and invests the spare change into a pooled investment vault, enabling users to invest effortlessly with small amounts.

Why it matters:
Many people want to invest but never start due to psychological and financial barriers. Micro-investing turns daily spending into a habit of wealth creation without noticeable effort.

How it works:

  • Users register a preferred round-up unit (e.g. nearest 0.01 ETH).

  • Each payment triggers an automatic round-up calculation.

  • The spare change is transferred into a personal investment vault.

  • Funds are periodically invested into DeFi protocols or pooled strategies.

  • Users can withdraw or rebalance investments anytime.

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

/**
 * @title MicroInvestmentRoundUp
 * @author Nam
 * @notice Automatically rounds up payments and invests spare change
 */
contract MicroInvestmentRoundUp {

    struct Investor {
        uint256 roundUnit;      // e.g. 0.01 ETH
        uint256 vaultBalance;
        bool active;
    }

    mapping(address => Investor) public investors;

    event InvestorRegistered(address indexed user, uint256 roundUnit);
    event PaymentProcessed(
        address indexed user,
        uint256 payment,
        uint256 roundedUp,
        uint256 invested
    );
    event Withdrawal(address indexed user, uint256 amount);

    /**
     * @notice Register or update micro-investment preferences
     */
    function register(uint256 _roundUnit) external {
        require(_roundUnit > 0, "Invalid round unit");

        investors[msg.sender] = Investor({
            roundUnit: _roundUnit,
            vaultBalance: investors[msg.sender].vaultBalance,
            active: true
        });

        emit InvestorRegistered(msg.sender, _roundUnit);
    }

    /**
     * @notice Process a payment and invest the round-up amount
     */
    function processPayment(uint256 _payment) external payable {
        Investor storage investor = investors[msg.sender];
        require(investor.active, "Investor not active");
        require(_payment > 0, "Invalid payment");

        uint256 roundedTotal =
            ((_payment + investor.roundUnit - 1) / investor.roundUnit)
                * investor.roundUnit;

        uint256 roundUpAmount = roundedTotal - _payment;

        require(msg.value == roundUpAmount, "Incorrect round-up value");

        investor.vaultBalance += roundUpAmount;

        emit PaymentProcessed(
            msg.sender,
            _payment,
            roundedTotal,
            roundUpAmount
        );
    }

    /**
     * @notice Withdraw accumulated micro-investments
     */
    function withdraw(uint256 _amount) external {
        Investor storage investor = investors[msg.sender];
        require(investor.vaultBalance >= _amount, "Insufficient balance");

        investor.vaultBalance -= _amount;
        payable(msg.sender).transfer(_amount);

        emit Withdrawal(msg.sender, _amount);
    }

    /**
     * @notice View investor vault
     */
    function getVault(address _user)
        external
        view
        returns (
            uint256 roundUnit,
            uint256 balance,
            bool active
        )
    {
        Investor memory investor = investors[_user];
        return (
            investor.roundUnit,
            investor.vaultBalance,
            investor.active
        );
    }
}