Skill-for-Skill Exchange Contract

What it does:
Facilitates peer-to-peer skill exchanges where users can trade services or skills securely on-chain without intermediaries.

Why it matters:
Enables trustless skill trading, tracks reputation and completion, automates agreements, and encourages collaboration in decentralized communities.

How it works:

  • Users register skills they offer and skills they seek

  • Smart contract matches users based on complementary skills

  • Agreements are locked in on-chain, optionally with escrowed tokens or time commitments

  • Completion verification triggers reward release or reputation updates

  • Integrates with Reputation-Based Access Control, AI Agent Payment, or Play-to-Earn Reward Engine

  • Dashboards track skills offered, exchanged, reputation gained, and completed transactions

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

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title SkillExchange
 * @author Nam
 * @notice Enables peer-to-peer skill swaps with optional escrow and reputation tracking
 */
contract SkillExchange is Ownable {

    struct UserSkill {
        string skillName;
        string skillLevel; // e.g., Beginner, Intermediate, Expert
        bool active;
    }

    struct Exchange {
        address userA;
        address userB;
        string skillA; // Skill offered by A
        string skillB; // Skill offered by B
        bool completedA;
        bool completedB;
        bool finalized;
    }

    mapping(address => UserSkill[]) public userSkills;
    Exchange[] public exchanges;

    mapping(address => uint256) public reputation; // basic reputation tracking

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

    event SkillRegistered(address indexed user, string skillName, string skillLevel);
    event ExchangeProposed(uint256 indexed exchangeId, address userA, address userB);
    event SkillCompleted(uint256 indexed exchangeId, address user);
    event ExchangeFinalized(uint256 indexed exchangeId);

    // -------------------- SKILL MANAGEMENT --------------------

    function registerSkill(string calldata _skillName, string calldata _skillLevel) external {
        userSkills[msg.sender].push(UserSkill({
            skillName: _skillName,
            skillLevel: _skillLevel,
            active: true
        }));

        emit SkillRegistered(msg.sender, _skillName, _skillLevel);
    }

    // -------------------- EXCHANGE MANAGEMENT --------------------

    function proposeExchange(address _userB, string calldata _skillA, string calldata _skillB) external {
        exchanges.push(Exchange({
            userA: msg.sender,
            userB: _userB,
            skillA: _skillA,
            skillB: _skillB,
            completedA: false,
            completedB: false,
            finalized: false
        }));

        uint256 exchangeId = exchanges.length - 1;
        emit ExchangeProposed(exchangeId, msg.sender, _userB);
    }

    function markSkillCompleted(uint256 _exchangeId) external {
        Exchange storage e = exchanges[_exchangeId];
        require(!e.finalized, "Already finalized");
        require(msg.sender == e.userA || msg.sender == e.userB, "Not participant");

        if (msg.sender == e.userA) e.completedA = true;
        if (msg.sender == e.userB) e.completedB = true;

        emit SkillCompleted(_exchangeId, msg.sender);

        // finalize exchange if both completed
        if (e.completedA && e.completedB) {
            e.finalized = true;
            reputation[e.userA] += 1;
            reputation[e.userB] += 1;
            emit ExchangeFinalized(_exchangeId);
        }
    }

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

    function getUserSkills(address _user) external view returns (UserSkill[] memory) {
        return userSkills[_user];
    }

    function getReputation(address _user) external view returns (uint256) {
        return reputation[_user];
    }

    function getExchange(uint256 _exchangeId) external view returns (Exchange memory) {
        return exchanges[_exchangeId];
    }
}