SprotoPaywall

Description:

Smart contract deployed on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

interface IERC20 {
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
}

contract SprotoPaywall {
    IERC20 public immutable sprotoToken;
    address public owner;
    
    // 10,000 $SPROTOSTORIES tokens (10,000 * 10^18)
    uint256 public constant SCENE_PRICE = 10000000000000000000000; // 10^22 wei
    
    event ScenePaid(address indexed user, uint256 indexed sceneIndex, uint256 amount, uint256 timestamp);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    constructor(address _tokenAddress) {
        require(_tokenAddress != address(0), "Invalid token address");
        sprotoToken = IERC20(_tokenAddress);
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }
    
    function payForScene(uint256 sceneIndex) external {
        // Check balance first (prevents failed transfers)
        uint256 balance = sprotoToken.balanceOf(msg.sender);
        require(balance >= SCENE_PRICE, "Insufficient token balance");
        
        // Check allowance
        uint256 allowance = sprotoToken.allowance(msg.sender, address(this));
        require(allowance >= SCENE_PRICE, "Insufficient allowance. Approve tokens first.");
        
        // Transfer tokens from user to contract/owner
        bool success = sprotoToken.transferFrom(msg.sender, owner, SCENE_PRICE);
        require(success, "Token transfer failed");
        
        // Emit payment event for verification
        emit ScenePaid(msg.sender, sceneIndex, SCENE_PRICE, block.timestamp);
    }
    
    function withdrawTokens(uint256 amount) external onlyOwner {
        require(amount > 0, "Amount must be greater than 0");
        uint256 contractBalance = sprotoToken.balanceOf(address(this));
        require(contractBalance >= amount, "Insufficient contract balance");
        
        bool success = sprotoToken.transferFrom(address(this), owner, amount);
        require(success, "Withdrawal failed");
    }
    
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Invalid new owner");
        require(newOwner != owner, "New owner must be different");
        
        // Check-effects-interactions: Update state before emitting event
        address oldOwner = owner;
        owner = newOwner;
        
        emit OwnershipTransferred(oldOwner, newOwner);
    }
    
    // View function to check if user can afford payment
    function canAffordPayment(address user) external view returns (bool) {
        uint256 balance = sprotoToken.balanceOf(user);
        uint256 allowance = sprotoToken.allowance(user, address(this));
        return balance >= SCENE_PRICE && allowance >= SCENE_PRICE;
    }
}

Tags:
addr:0xd99500f72ecb2bd3d09de067be9149feb5c8adbd|verified:true|block:23736127|tx:0x19f204f7b358ccd0f24d653f2bed584a77fcdc28e7c9a9f88041ba03d8ff701d|first_check:1762419394

Submitted on: 2025-11-06 09:56:34

Comments

Log in to comment.

No comments yet.