Skip to content

Instantly share code, notes, and snippets.

@Vladislav-Melenchuk
Created April 12, 2026 10:36
Show Gist options
  • Select an option

  • Save Vladislav-Melenchuk/b10c05224c49ebb48df00c2849f1a027 to your computer and use it in GitHub Desktop.

Select an option

Save Vladislav-Melenchuk/b10c05224c49ebb48df00c2849f1a027 to your computer and use it in GitHub Desktop.
HW_7_Fintech

1. Разработайте интерфейс IQuest, который определяет методы для управления квестами (например, startQuest, completeQuest, getReward). Затем создайте контракт QuestManager, который реализует этот интерфейс и управляет квестами для игроков. Реализуйте систему наград и уровней.

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

interface IQuest {
    function startQuest(uint256 questId) external;
    function completeQuest(uint256 questId) external;
    function getReward(uint256 questId) external view returns (uint256);
}

contract QuestManager is IQuest {
    struct Quest {
        bool started;
        bool completed;
        uint256 reward;
    }

    mapping(address => uint256) public level;
    mapping(address => mapping(uint256 => Quest)) public quests;

    event QuestStarted(address player, uint256 questId);
    event QuestCompleted(address player, uint256 questId);
    event RewardClaimed(address player, uint256 questId, uint256 reward);

    function startQuest(uint256 questId) external override {
        quests[msg.sender][questId].started = true;
        quests[msg.sender][questId].reward = (level[msg.sender] + 1) * 1 ether;

        emit QuestStarted(msg.sender, questId);
    }

    function completeQuest(uint256 questId) external override {
        require(quests[msg.sender][questId].started, "Not started");
        require(!quests[msg.sender][questId].completed, "Already completed");

        quests[msg.sender][questId].completed = true;
        level[msg.sender] += 1;

        emit QuestCompleted(msg.sender, questId);
    }

    function getReward(uint256 questId) external view override returns (uint256) {
        return quests[msg.sender][questId].reward;
    }

    function claimReward(uint256 questId) external {
        require(quests[msg.sender][questId].completed, "Not completed");

        uint256 reward = quests[msg.sender][questId].reward;
        quests[msg.sender][questId].reward = 0;

        (bool success, ) = payable(msg.sender).call{value: reward}("");
        require(success, "Transfer failed");

        emit RewardClaimed(msg.sender, questId, reward);
    }

    receive() external payable {}
}

2. Разработайте библиотеку ResourceUtils, которая содержит функции для управления игровыми ресурсами: распределение энергии, вычисление стоимости апгрейдов, оптимизация расхода золота. Затем создайте контракт ResourceManager, который использует эту библиотеку для управления ресурсами игроков.

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

library ResourceUtils {
    function energyDistribution(uint256 energy, uint256 users)
        internal
        pure
        returns (uint256)
    {
        if (users == 0) return 0;
        return energy / users;
    }

    function upgradeCost(uint256 baseCost, uint256 level)
        internal
        pure
        returns (uint256)
    {
        return baseCost * (level + 1) * (level + 1);
    }

    function optimizeGold(uint256 currentGold, uint256 spend)
        internal
        pure
        returns (uint256)
    {
        if (spend > currentGold) return 0;
        return currentGold - spend;
    }
}

contract ResourceManager {
    using ResourceUtils for uint256;

    mapping(address => uint256) public gold;
    mapping(address => uint256) public energy;
    mapping(address => uint256) public upgradeLevel;

    function addGold(uint256 amount) external {
        gold[msg.sender] += amount;
    }

    function addEnergy(uint256 amount) external {
        energy[msg.sender] += amount;
    }

    function distributeEnergy(uint256 users) external view returns (uint256) {
        return ResourceUtils.energyDistribution(energy[msg.sender], users);
    }

    function upgrade() external {
        uint256 cost = ResourceUtils.upgradeCost(100, upgradeLevel[msg.sender]);
        require(gold[msg.sender] >= cost, "Not enough gold");

        gold[msg.sender] = ResourceUtils.optimizeGold(gold[msg.sender], cost);
        upgradeLevel[msg.sender] += 1;
    }
}

3. Создайте базовый контракт WarriorGuild, который управляет регистрацией воинов. Затем создайте несколько подклассов: Knight, Mage и Assassin. Каждый из них должен наследовать WarriorGuild и добавлять уникальные способности, например, attack() с разными механиками урона.

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


contract WarriorGuild {

    struct Warrior {
        string name;
        uint256 power;
        bool registered;
    }

    mapping(address => Warrior) public warriors;

    event WarriorRegistered(address indexed user, string name, uint256 power);

    function register(string memory name, uint256 power) public virtual {
        require(!warriors[msg.sender].registered, "Already registered");

        warriors[msg.sender] = Warrior({
            name: name,
            power: power,
            registered: true
        });

        emit WarriorRegistered(msg.sender, name, power);
    }

    function isRegistered(address user) public view returns (bool) {
        return warriors[user].registered;
    }
}


contract Knight is WarriorGuild {

    function register(string memory name, uint256 power) public override {
       
        super.register(name, power + 20);
    }

    function attack(address target) public view returns (uint256 damage) {
        require(isRegistered(msg.sender), "Not registered");
        require(isRegistered(target), "Target not registered");

      
        damage = warriors[msg.sender].power + 30;
    }
}


contract Mage is WarriorGuild {

    function attack(address target) public view returns (uint256 damage) {
        require(isRegistered(msg.sender), "Not registered");
        require(isRegistered(target), "Target not registered");

       
        damage = warriors[msg.sender].power * 2;
    }
}


contract Assassin is WarriorGuild {

    function attack(address target) public view returns (uint256 damage) {
        require(isRegistered(msg.sender), "Not registered");
        require(isRegistered(target), "Target not registered");

        
        damage = warriors[msg.sender].power * 3;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment