Fan Voting on Content Direction
What it does:
Allows fans to vote on creative decisions such as story arcs, themes, formats, release schedules, or future content directions using on-chain voting.
Why it matters:
Deepens fan engagement, aligns creators with their audience, turns passive followers into stakeholders, and provides transparent, tamper-proof insight into audience preferences.
How it works:
-
Creators define content decisions as on-chain voting proposals
-
Fans gain voting power by holding tokens, NFTs, or active subscriptions
-
Each proposal has clear options, voting weights, and deadlines
-
Votes are recorded immutably on-chain and counted automatically
-
Results are visible in real time and cannot be manipulated
-
Creators can commit to executing winning outcomes publicly
-
Integrates with fan tokens, creator DAOs, and gated communities
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title FanVotingOnContentDirection
* @author Nam
* @notice On-chain fan voting for creator content decisions
*/
contract FanVotingOnContentDirection {
address public creator;
uint256 public proposalCount;
constructor() {
creator = msg.sender;
}
// -------------------- STRUCTS --------------------
struct Proposal {
string description;
string[] options;
uint256 deadline;
bool executed;
mapping(uint256 => uint256) votes; // optionIndex => vote count
mapping(address => bool) hasVoted;
}
mapping(uint256 => Proposal) private proposals;
mapping(address => uint256) public votingPower; // simple off-chain assigned power
// -------------------- EVENTS --------------------
event ProposalCreated(uint256 indexed proposalId, string description, uint256 deadline);
event Voted(uint256 indexed proposalId, address indexed voter, uint256 optionIndex, uint256 weight);
event ProposalExecuted(uint256 indexed proposalId, uint256 winningOption);
// -------------------- MODIFIERS --------------------
modifier onlyCreator() {
require(msg.sender == creator, "Not creator");
_;
}
// -------------------- VOTING POWER MANAGEMENT --------------------
// Can be wired to NFT / token balance in production
function setVotingPower(address _fan, uint256 _power) external onlyCreator {
votingPower[_fan] = _power;
}
// -------------------- PROPOSAL MANAGEMENT --------------------
function createProposal(
string calldata _description,
string[] calldata _options,
uint256 _votingDuration
) external onlyCreator {
require(_options.length >= 2, "Need multiple options");
proposalCount += 1;
Proposal storage p = proposals[proposalCount];
p.description = _description;
p.options = _options;
p.deadline = block.timestamp + _votingDuration;
emit ProposalCreated(proposalCount, _description, p.deadline);
}
// -------------------- VOTING --------------------
function vote(uint256 _proposalId, uint256 _optionIndex) external {
Proposal storage p = proposals[_proposalId];
require(block.timestamp < p.deadline, "Voting ended");
require(!p.hasVoted[msg.sender], "Already voted");
require(_optionIndex <p> 0, "No voting power");
p.votes[_optionIndex] += weight;
p.hasVoted[msg.sender] = true;
emit Voted(_proposalId, msg.sender, _optionIndex, weight);
}
// -------------------- EXECUTION --------------------
function executeProposal(uint256 _proposalId) external onlyCreator {
Proposal storage p = proposals[_proposalId];
require(block.timestamp >= p.deadline, "Voting ongoing");
require(!p.executed, "Already executed");
uint256 winningOption;
uint256 highestVotes;
for (uint256 i = 0; i <p> highestVotes) {
highestVotes = p.votes[i];
winningOption = i;
}
}
p.executed = true;
emit ProposalExecuted(_proposalId, winningOption);
}
// -------------------- VIEW HELPERS --------------------
function getProposal(uint256 _proposalId)
external
view
returns (
string memory description,
string[] memory options,
uint256 deadline,
bool executed
)
{
Proposal storage p = proposals[_proposalId];
return (p.description, p.options, p.deadline, p.executed);
}
function votesForOption(uint256 _proposalId, uint256 _optionIndex)
external
view
returns (uint256)
{
return proposals[_proposalId].votes[_optionIndex];
}
}