What it does:
Allows creators to sell access to digital content (videos, articles, courses) on a pay-per-view basis, collecting revenue automatically on-chain.
Why it matters:
Eliminates intermediaries, ensures instant payments to creators, prevents unauthorized access, and tracks viewership transparently.
How it works:
Creators register content with metadata and a per-view price
Users pay the required fee on-chain to unlock access
Smart contract tracks which addresses have access to the content
Access can be time-limited or permanent per payment
Revenue is collected and optionally split among multiple stakeholders
Content access history is auditable and tamper-proof
Integrates easily with NFTs or subscription models for premium content
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title PayPerViewContent
* @author Nam
* @notice Sell digital content access on a pay-per-view basis
*/
contract PayPerViewContent {
address public admin;
uint256 public contentCount;
struct Content {
string metadataHash; // IPFS or encrypted content reference
address payable creator;
uint256 price; // in wei per view
mapping(address => bool) viewers; // tracks who has access
}
mapping(uint256 => Content) public contents;
// -------------------- EVENTS --------------------
event ContentRegistered(uint256 indexed contentId, address indexed creator, uint256 price);
event ContentPurchased(uint256 indexed contentId, address indexed viewer, uint256 amount);
// -------------------- MODIFIERS --------------------
modifier onlyAdmin() {
require(msg.sender == admin, "Not admin");
_;
}
// -------------------- CONSTRUCTOR --------------------
constructor() {
admin = msg.sender;
}
// -------------------- CONTENT MANAGEMENT --------------------
function registerContent(string calldata _metadataHash, uint256 _price) external {
require(_price > 0, "Price must be >0");
contentCount += 1;
Content storage c = contents[contentCount];
c.metadataHash = _metadataHash;
c.creator = payable(msg.sender);
c.price = _price;
emit ContentRegistered(contentCount, msg.sender, _price);
}
// -------------------- PAY-PER-VIEW ACCESS --------------------
function purchaseContent(uint256 _contentId) external payable {
Content storage c = contents[_contentId];
require(msg.value == c.price, "Incorrect payment");
require(!c.viewers[msg.sender], "Already purchased");
c.viewers[msg.sender] = true;
c.creator.transfer(msg.value);
emit ContentPurchased(_contentId, msg.sender, msg.value);
}
function hasAccess(uint256 _contentId, address _user) external view returns (bool) {
return contents[_contentId].viewers[_user];
}
}
Build and Grow By Nam Le Thanh