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
);
}
}