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