Inflation-Protected Savings Contract

What it does:
A smart contract that helps users preserve the real value of their savings by automatically adjusting balances or yields based on inflation data.

Why it matters:
Inflation silently erodes purchasing power. Traditional savings accounts rarely keep up. This contract introduces a rules-based, transparent mechanism to protect savings against inflation over time.

How it works:

  • Users deposit funds into an inflation-protected vault.

  • Inflation data is provided by a trusted oracle (e.g., CPI).

  • The contract periodically adjusts user balances or credits inflation compensation.

  • Users can withdraw funds with inflation-adjusted value.

  • All adjustments are transparently recorded on-chain.

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

/**
 * @title InflationProtectedSavings
 * @author Nam
 * @notice Savings vault that adjusts balances based on inflation index
 */
contract InflationProtectedSavings {

    // -------------------- DATA STRUCTURES --------------------

    struct Account {
        uint256 principal;        // User deposited amount
        uint256 lastIndex;        // Inflation index at last update
        uint256 adjustedBalance; // Inflation-adjusted balance
        bool active;
    }

    mapping(address => Account) public accounts;

    address public owner;
    uint256 public inflationIndex; // e.g. CPI-based index (scaled)
    uint256 public lastUpdate;

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

    event Deposited(address indexed user, uint256 amount);
    event InflationIndexUpdated(uint256 newIndex);
    event BalanceAdjusted(address indexed user, uint256 newBalance);
    event Withdrawn(address indexed user, uint256 amount);

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

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

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

    constructor(uint256 _initialIndex) {
        require(_initialIndex > 0, "Invalid index");
        owner = msg.sender;
        inflationIndex = _initialIndex;
        lastUpdate = block.timestamp;
    }

    // -------------------- CORE FUNCTIONS --------------------

    /**
     * @notice Deposit ETH into inflation-protected savings
     */
    function deposit() external payable {
        require(msg.value > 0, "Zero deposit");

        Account storage account = accounts[msg.sender];

        if (!account.active) {
            account.principal = msg.value;
            account.adjustedBalance = msg.value;
            account.lastIndex = inflationIndex;
            account.active = true;
        } else {
            _adjustBalance(msg.sender);
            account.principal += msg.value;
            account.adjustedBalance += msg.value;
        }

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

    /**
     * @notice Owner updates inflation index (oracle hook)
     * @dev In production, this should be restricted to a trusted oracle
     */
    function updateInflationIndex(uint256 _newIndex)
        external
        onlyOwner
    {
        require(_newIndex > inflationIndex, "Index must increase");

        inflationIndex = _newIndex;
        lastUpdate = block.timestamp;

        emit InflationIndexUpdated(_newIndex);
    }

    /**
     * @notice Adjust user balance based on inflation
     */
    function adjustMyBalance() external {
        _adjustBalance(msg.sender);
    }

    function _adjustBalance(address _user) internal {
        Account storage account = accounts[_user];
        require(account.active, "No account");

        uint256 indexDelta = inflationIndex - account.lastIndex;

        if (indexDelta > 0) {
            uint256 adjustment =
                (account.adjustedBalance * indexDelta) /
                account.lastIndex;

            account.adjustedBalance += adjustment;
            account.lastIndex = inflationIndex;

            emit BalanceAdjusted(_user, account.adjustedBalance);
        }
    }

    /**
     * @notice Withdraw inflation-adjusted savings
     */
    function withdraw() external {
        Account storage account = accounts[msg.sender];
        require(account.active, "No account");

        _adjustBalance(msg.sender);

        uint256 amount = account.adjustedBalance;

        account.active = false;
        account.principal = 0;
        account.adjustedBalance = 0;

        payable(msg.sender).transfer(amount);

        emit Withdrawn(msg.sender, amount);
    }

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

    /**
     * @notice Get account details
     */
    function getAccount(address _user)
        external
        view
        returns (
            uint256 principal,
            uint256 adjustedBalance,
            uint256 lastIndex,
            bool active
        )
    {
        Account memory a = accounts[_user];
        return (
            a.principal,
            a.adjustedBalance,
            a.lastIndex,
            a.active
        );
    }
}