DEV Community

Cover image for πŸ‹οΈ Day 10 of #30DaysOfSolidity β€” Building a Decentralized Fitness Tracker with Events & Milestones
Saurav Kumar
Saurav Kumar

Posted on

πŸ‹οΈ Day 10 of #30DaysOfSolidity β€” Building a Decentralized Fitness Tracker with Events & Milestones

Introduction

Today we’re building FitTrack, a decentralized fitness tracker on Ethereum! πŸƒβ€β™‚οΈπŸ’ͺ

The goal: allow users to log workouts, track progress, and unlock on-chain milestones like β€œ10 workouts in a week” or β€œ500 total minutes exercised.”

This project demonstrates how to use:

  • Events to log activity
  • Indexed parameters for efficient off-chain filtering
  • Structs and mappings for user data
  • Emitting events to notify milestones

Think of it as a backend for a decentralized fitness app, fully on-chain.


Key Concepts

  1. Events – Log important actions on the blockchain for transparency.
  2. Logging Data – Track user workouts with type, duration, calories, and timestamp.
  3. Indexed Parameters – Make events filterable by user for frontends or analytics tools.
  4. Emitting Events – Notify when users reach milestones.

Source Code

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

/// @title FitTrack - A Decentralized Fitness Tracker
/// @author Saurav
/// @notice Log your workouts and unlock fitness milestones on-chain
/// @dev Demonstrates event indexing, mappings, and user data tracking
contract FitTrack {
    struct Workout {
        string workoutType;
        uint256 duration; // in minutes
        uint256 calories;
        uint256 timestamp;
    }

    struct UserStats {
        uint256 totalWorkouts;
        uint256 totalMinutes;
        uint256 totalCalories;
        uint256 lastWeekWorkouts;
        uint256 lastWeekStart;
    }

    mapping(address => Workout[]) private workouts;
    mapping(address => UserStats) public userStats;

    /// @notice Emitted when a workout is logged
    event WorkoutLogged(address indexed user, string workoutType, uint256 duration, uint256 calories);

    /// @notice Emitted when user reaches 10 workouts in a week
    event WeeklyGoalReached(address indexed user, uint256 workoutsCount);

    /// @notice Emitted when user reaches 500 total minutes milestone
    event TotalMinutesMilestone(address indexed user, uint256 totalMinutes);

    /// @dev Log a workout session
    function logWorkout(string memory _type, uint256 _duration, uint256 _calories) external {
        require(_duration > 0, "Duration must be greater than 0");

        Workout memory newWorkout = Workout({
            workoutType: _type,
            duration: _duration,
            calories: _calories,
            timestamp: block.timestamp
        });

        workouts[msg.sender].push(newWorkout);
        UserStats storage stats = userStats[msg.sender];

        stats.totalWorkouts += 1;
        stats.totalMinutes += _duration;
        stats.totalCalories += _calories;

        // Weekly logic
        if (block.timestamp > stats.lastWeekStart + 7 days) {
            stats.lastWeekStart = block.timestamp;
            stats.lastWeekWorkouts = 0;
        }

        stats.lastWeekWorkouts += 1;

        emit WorkoutLogged(msg.sender, _type, _duration, _calories);

        // Check milestones
        if (stats.lastWeekWorkouts == 10) {
            emit WeeklyGoalReached(msg.sender, stats.lastWeekWorkouts);
        }

        if (stats.totalMinutes >= 500 && (stats.totalMinutes - _duration) < 500) {
            emit TotalMinutesMilestone(msg.sender, stats.totalMinutes);
        }
    }

    /// @notice Get all workouts of a user
    function getWorkouts(address _user) external view returns (Workout[] memory) {
        return workouts[_user];
    }

    /// @notice Get user's current stats
    function getUserStats(address _user) external view returns (UserStats memory) {
        return userStats[_user];
    }
}
Enter fullscreen mode Exit fullscreen mode

How It Works

  1. Users call logWorkout() with:
  • workoutType (e.g., Running, Yoga)
  • duration in minutes
  • calories burned
  1. The contract updates UserStats (total workouts, minutes, calories).

  2. Events are emitted:

  • WorkoutLogged β†’ every workout
  • WeeklyGoalReached β†’ 10 workouts in a week
  • TotalMinutesMilestone β†’ when total minutes reach 500
  1. Frontends or analytics tools can filter events by user using the indexed parameters for dashboards or notifications.

Key Learnings

  • How to structure user data with structs and mappings.
  • Implement time-based logic (weekly progress).
  • Create on-chain achievement systems.
  • Use events with indexed parameters for real-time tracking.

Next Steps

  • Integrate a frontend DApp to visualize workouts and achievements.
  • Mint NFT badges for milestones.
  • Add reward tokens for consistency.
  • Create leaderboards for global competition.

πŸ’‘ Takeaway: Solidity isn’t just for finance β€” you can build fitness trackers, games, and lifestyle apps on-chain using the same principles.

Top comments (0)