0

// here is my contract

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

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;
        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        return c;
    }
}

contract ThetaVibes {
    using SafeMath for uint256; // Import SafeMath library
     mapping(address => uint256) public balances;
 struct Video {
        uint256 price;
        uint256 price48Hours;
        uint256 priceLifetime;
        mapping(address => bool) lifetimeAccess;
    }
    
      struct Channel {
        address payable owner;
        mapping(string => Video) videos;
        uint256 channelBalance;
        uint256 subscriptionPrice;
        mapping(address => bool) subscribers;
    }

        struct Subscription {
        bool isActive;
    }

    address payable contractOwnerAddress;

    constructor() {
        contractOwnerAddress = payable(msg.sender);
    }

    modifier onlyOwner() {
        require(msg.sender == contractOwnerAddress, "Only the contract owner can call this function.");
        _;
    }

    mapping(string => Channel) public channels;

    mapping(string => mapping(address => Subscription)) public subscriptions;


    event SubscriptionPurchased(string indexed channelId, address indexed subscriber);
    event VideoPurchased(string indexed channelId, string indexed videoId, address indexed purchaser, bool isLifetime);
    event ChannelOwnerWithdrawn(string indexed channelId, address indexed owner, uint256 amount);
    event ContractOwnerWithdrawn(address indexed owner, uint256 amount);
    event DepositMade(address indexed depositor, uint256 amount);
    event SubscriptionRemoved(string indexed channelId, address indexed subscriber);

  
    function createChannel(string memory channelId, uint256 subscriptionPriceTFuel) public {
        require(channels[channelId].owner == address(0), "Channel already exists");
        Channel storage newChannel = channels[channelId];
        newChannel.owner = payable(msg.sender);
        newChannel.subscriptionPrice = subscriptionPriceTFuel;
    }

function deposit() public payable {
    require(msg.value > 0, "Amount must be greater than zero");

    // Deduct gas fees from the deposited amount
    uint256 gasCost = gasleft() * tx.gasprice;
    uint256 depositedAmount = msg.value.sub(gasCost);

    balances[msg.sender] = balances[msg.sender].add(depositedAmount);

    emit DepositMade(msg.sender, depositedAmount);
}

function purchaseSubscriptionWithBalance(string memory channelId, address subscriber) public {
    Channel storage channel = channels[channelId];
    require(channel.owner != address(0), "Channel does not exist");
    require(!channel.subscribers[subscriber], "Already subscribed to the channel");

    uint256 gasCost = gasleft() * tx.gasprice;
    uint256 totalCost = channel.subscriptionPrice.add(gasCost); // Calculate total cost

    require(balances[subscriber] >= totalCost, "Insufficient balance to cover subscription and gas fees");

    channel.subscribers[subscriber] = true;
    emit SubscriptionPurchased(channelId, subscriber);

    uint256 contractOwnerShare = (channel.subscriptionPrice * 20) / 100;
    uint256 channelOwnerShare = channel.subscriptionPrice - contractOwnerShare;

    channel.channelBalance += channelOwnerShare;
    balances[subscriber] = balances[subscriber].sub(channel.subscriptionPrice); // Deduct subscription price from user's balance

    // Call a separate function for gas-heavy operations
    processGas(subscriber, gasCost);
}

function processGas(address subscriber, uint256 gasCost) internal {
    balances[subscriber] = balances[subscriber].sub(gasCost); // Deduct gas cost from user's balance
    // Additional gas-heavy operations can be performed here
}
  


      function renewSubscriptionWithBalance(string memory channelId, address subscriber) public onlyOwner {
        Channel storage channel = channels[channelId];
        require(channel.owner != address(0), "Channel does not exist");
        require(channel.subscribers[subscriber], "Subscriber is not subscribed to the channel");
        require(balances[subscriber] >= channel.subscriptionPrice, "Insufficient balance");

        channel.channelBalance += channel.subscriptionPrice; // Add subscription price to channel balance
        balances[subscriber] -= channel.subscriptionPrice; // Deduct subscription price from user's balance
      }


    function removeSubscription(string memory channelId, address subscriber) public onlyOwner {
        Channel storage channel = channels[channelId];
        require(channel.owner != address(0), "Channel does not exist");
        require(channel.subscribers[subscriber], "Subscriber is not subscribed to the channel");

        channel.subscribers[subscriber] = false; // Set subscriber status to false to remove subscription

        emit SubscriptionRemoved(channelId, subscriber);
    }
 

function updateSubscriptionPrice(string memory channelId, uint256 newPrice) public {
    Channel storage channel = channels[channelId];
    require(channel.owner == msg.sender, "Only the channel owner can update the subscription price");

    channel.subscriptionPrice = newPrice;
}

modifier onlyChannelOwner(string memory channelId) {
    require(channels[channelId].owner == msg.sender, "Only the channel owner can call this function.");
    _;
}

function createVideo(string memory channelId, string memory videoId, uint256 price48Hours, uint256 priceLifetime) public onlyChannelOwner(channelId) {
    Channel storage channel = channels[channelId];
    require(channel.videos[videoId].price48Hours == 0, "Video already exists");

    Video storage newVideo = channel.videos[videoId];
    newVideo.price48Hours = price48Hours * 1e18;
    newVideo.priceLifetime = priceLifetime * 1e18;
}
    
function purchaseVideoWithBalance(string memory channelId, string memory videoId, bool lifetimeAccess) public {
    Channel storage channel = channels[channelId];
    require(channel.owner != address(0), "Channel does not exist");
    require(channel.videos[videoId].price48Hours > 0, "Video does not exist");
    require(!channel.subscribers[msg.sender], "Subscribers cannot purchase videos from this channel");
    require(!channel.videos[videoId].lifetimeAccess[msg.sender], "Already purchased lifetime access to the video");

    uint256 videoPrice = (lifetimeAccess ? channel.videos[videoId].priceLifetime : channel.videos[videoId].price48Hours) / 1e18;

    require(balances[msg.sender] >= videoPrice, "Insufficient balance");

    if (lifetimeAccess) {
        channel.videos[videoId].lifetimeAccess[msg.sender] = true;
    }

    uint256 contractOwnerShare = (videoPrice * 20) / 100;
    uint256 channelOwnerShare = videoPrice - contractOwnerShare;

    channel.channelBalance += channelOwnerShare;
    balances[msg.sender] -= videoPrice;
    contractOwnerAddress.transfer(contractOwnerShare); // Transfer 20% to the contract owner
    emit VideoPurchased(channelId, videoId, msg.sender, lifetimeAccess);
}


    function channelOwnerWithdraw(string memory channelId) public {
        Channel storage channel = channels[channelId];
        require(channel.owner == msg.sender, "Only the channel owner can call this function");

        uint256 amount = channel.channelBalance;
        require(amount > 0, "No balance available for withdrawal");

        channel.channelBalance = 0;
        channel.owner.transfer(amount);
        emit ChannelOwnerWithdrawn(channelId, msg.sender, amount);
    }
    function isSubscriber(string memory channelId, address account) public view returns (bool) {
        return channels[channelId].subscribers[account];
    }


}
2
  • Please state clearly what you need instead of sharing a random contract with poor editing.
    – Torof
    Commented Oct 4, 2023 at 6:43
  • Thank You guiding, this my first time to asking question on this platform
    – Ilyas Khan
    Commented Oct 4, 2023 at 7:03

1 Answer 1

1

In general, in the Ethereum network, the price is paid by the one who initiated the transaction. The way around it (at the moment) are Meta-transactions + Gas Relayers

Meta-transactions allow users to sign messages (not transactions), which are then sent to a Gas Relay. After verifying these messages, the relay processes them as transactions on-chain and pays for the gas fees. The contract can then reimburse the relay or provide other compensations. This means from the user's perspective, they don't need to spend ETH, even though a transaction occurs on-chain. (Exactly what you are trying to do).

4
  • I have created function for consumer to deposited balance into contract, My goal is to deduct gas fee for purchasing subscription from his/her deposited balance as same as subscription is deducting from his/her balance, Can you explain is it possible ?
    – Ilyas Khan
    Commented Oct 4, 2023 at 7:00
  • @IlyasKhan you are confusing gas fees I guess. Gas fees is something paid for the transaction to execute. Please explain your question properly. Commented Oct 4, 2023 at 12:20
  • @ZartajAfser I am working on smart contract in which is almost same as virtual wallet user deposit into my contract and i am storing their balance into contract. I want to achieve when they transaction their gas cost would also be deduct from virtual wallet, Is it possible ?
    – Ilyas Khan
    Commented Oct 5, 2023 at 5:28
  • No, the gas cost is always deducted from the wallet that initiates a transaction. You can use meta transactions to make it gas less for the users and later deduct the price from their virtual wallet. Commented Oct 5, 2023 at 6:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.