Lifelong Learning Wallet

What it does:
Manages a student’s or lifelong learner’s on-chain funds, scholarships, rewards, and tokens earned through learning achievements.

Why it matters:
Provides a single, secure, and transparent wallet for all educational funding and rewards, enabling easy access, auditability, and integration with learn-to-earn programs.

How it works:

  • Learners have a dedicated on-chain wallet for all educational funds

  • Scholarships, course payments, rewards, and tokens are deposited automatically or manually

  • Wallet tracks incoming funds, usage, and balances for tuition, courses, or milestone rewards

  • Learners can approve smart contract spending for course payments or subscriptions

  • Integrates with Learn-to-Earn, Attendance Reward, and Internship Reward contracts

  • Transaction history, earnings, and expenditures are fully auditable

  • Can support multiple currencies (ETH, stablecoins, platform tokens) for flexibility

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

/**
 * @title LifelongLearningWallet
 * @author Nam
 * @notice Wallet to manage educational funds, scholarships, and learning rewards
 */
contract LifelongLearningWallet {

    address public owner;

    mapping(address => uint256) public tokenBalances; // token address => balance

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

    event Deposit(address indexed from, uint256 amount);
    event TokenDeposit(address indexed token, uint256 amount);
    event Withdrawal(address indexed to, uint256 amount);
    event TokenWithdrawal(address indexed token, uint256 amount);

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

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

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

    constructor() {
        owner = msg.sender;
    }

    // -------------------- ETH MANAGEMENT --------------------

    function deposit() external payable {
        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(uint256 _amount) external onlyOwner {
        require(address(this).balance >= _amount, "Insufficient balance");
        payable(owner).transfer(_amount);
        emit Withdrawal(owner, _amount);
    }

    // -------------------- ERC20 TOKEN MANAGEMENT --------------------

    function depositToken(address _token, uint256 _amount) external {
        require(_amount > 0, "Amount must be >0");
        require(_token != address(0), "Invalid token");

        bool success = IERC20(_token).transferFrom(msg.sender, address(this), _amount);
        require(success, "Token transfer failed");

        tokenBalances[_token] += _amount;
        emit TokenDeposit(_token, _amount);
    }

    function withdrawToken(address _token, uint256 _amount) external onlyOwner {
        require(tokenBalances[_token] >= _amount, "Insufficient token balance");

        tokenBalances[_token] -= _amount;
        bool success = IERC20(_token).transfer(owner, _amount);
        require(success, "Token transfer failed");

        emit TokenWithdrawal(_token, _amount);
    }

    receive() external payable {}
}

// Minimal ERC20 interface
interface IERC20 {
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
}