链上治理与内容共创:从Web2评论到DAO提案
2026年,内容创作的"范式"正在从"Web2评论"转向"DAO提案"。从"YouTube的评论区"到"DAO的治理论坛",从"点赞"到"投票",从"创作者决定"到"社区共创"——链上治理正在"重塑"内容创作的"权力"结构。这是"内容"的"民主化"革命——不是"创作者"决定"一切",而是"社区"共同"决定"。
第一幕:从"Web2评论"到"链上治理"
第一场:Web2的"评论"——"表面"的"参与"
Web2的"内容"参与方式:
- 评论:用户"评论"内容——"表达"意见、"分享"观点、"讨论"话题。
- 点赞:用户"点赞"内容——"表达"喜欢、"支持"创作者。
- 分享:用户"分享"内容——"传播"内容、"扩大"影响。
- 投票:平台"投票"——"YouTube"的"投票"功能、"Twitter"的"投票"功能。
第二场:Web2评论的"局限性"
Web2评论的"局限性":
- 表面参与:评论、点赞、分享——"表面"的"参与"——"没有"真正的"决策权"。
- 中心化控制:平台"控制"内容——"算法"决定"推荐"、"审查"决定"删除"。
- 价值流失:用户"贡献"价值——"内容"、"讨论"、"流量"——但"平台"获得"收益"。
第三场:从"评论"到"提案"——"DAO"的"治理"模式
DAO的"治理"模式:
- 提案(Proposal):社区成员"提出"提案——"内容"方向、"资金"分配、"规则"修改。
- 投票(Voting):Token持有者"投票"——"赞成"、"反对"、"弃权"。
- 执行(Execution):通过的提案"自动"执行——"智能合约"执行"决策"。
第二幕:内容DAO的"治理"架构
第一场:从"创作者DAO"到"内容DAO"——"类型"的"区分"
内容DAO的"类型":
- 创作者DAO:一个"创作者"的"DAO"——"粉丝"参与"治理"——"合作"、"收入"、"方向"。
- 内容DAO:一个"内容"的"DAO"——"社区"共同"创作"和"治理"——"Wiki"、"开源"、"媒体"。
- 平台DAO:一个"平台"的"DAO"——"用户"参与"治理"——"规则"、"算法"、"收入"。
第二场:从"提案"到"执行"——"治理"的"流程"
内容DAO的"治理"流程:
- 讨论阶段:社区成员在"论坛"讨论"提案"——"Discourse"、"Discord"、"Telegram"。
- 提案阶段:提案"正式"提交——"Tally"、"Snapshot"、"Governor"。
- 投票阶段:Token持有者"投票"——"代币"投票、"二次方"投票、"声誉"投票。
- 执行阶段:通过的提案"执行"——"智能合约"、"多签"、"时间锁"。
第三场:从"Web2评论"到"Web3提案"——"参与"的"升级"
Web2评论到Web3提案的"升级":
- 从"评论"到"提案":从"表达"意见到"提出"方案。
- 从"点赞"到"投票":从"表达"支持到"决策"。
- 从"分享"到"执行":从"传播"内容到"执行"决策。
- 从"平台"到"DAO":从"中心化"平台到"去中心化"组织。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract ContentDAO is AccessControl, ReentrancyGuard {
bytes32 public constant CREATOR_ROLE = keccak256("CREATOR_ROLE");
bytes32 public constant CURATOR_ROLE = keccak256("CURATOR_ROLE");
enum ProposalType {
CONTENT_DIRECTION, FUND_ALLOCATION, RULE_CHANGE, MEMBER_ADMISSION, COLLABORATION
}
enum ProposalStatus {
PENDING, ACTIVE, APPROVED, REJECTED, EXECUTED, CANCELLED
}
enum ContentCategory {
ARTICLE, VIDEO, MUSIC, NFT, PODCAST, EVENT, RESEARCH
}
struct Proposal {
uint256 proposalId;
address proposer;
string title;
string description;
string ipfsCID;
ProposalType propType;
ProposalStatus status;
uint256 forVotes;
uint256 againstVotes;
uint256 startTime;
uint256 endTime;
uint256 quorum;
bool executed;
}
struct ContentProject {
uint256 projectId;
string title;
string description;
address creator;
ContentCategory category;
uint256 fundingGoal;
uint256 totalFunded;
uint256[] proposalIds;
bool isActive;
}
struct Vote {
address voter;
uint256 proposalId;
bool support;
uint256 votingPower;
uint256 timestamp;
}
IERC20 public governanceToken;
uint256 public votingDelay = 1 days;
uint256 public votingPeriod = 7 days;
uint256 public quorumPercentage = 10;
uint256 public proposalCount;
uint256 public projectCount;
mapping(uint256 => Proposal) public proposals;
mapping(uint256 => ContentProject) public projects;
mapping(uint256 => mapping(address => Vote)) public votes;
mapping(address => uint256) public reputationScore;
mapping(address => uint256) public contributionCount;
event ProposalCreated(uint256 indexed proposalId, address indexed proposer, string title);
event VoteCast(uint256 indexed proposalId, address indexed voter, bool support, uint256 power);
event ProposalExecuted(uint256 indexed proposalId);
event ProjectCreated(uint256 indexed projectId, string title, address creator);
constructor(address _governanceToken) {
governanceToken = IERC20(_governanceToken);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(CREATOR_ROLE, msg.sender);
}
function createProposal(
string memory _title,
string memory _description,
string memory _ipfsCID,
ProposalType _propType
) external returns (uint256) {
require(bytes(_title).length > 0, "Title required");
proposalCount++;
proposals[proposalCount] = Proposal({
proposalId: proposalCount,
proposer: msg.sender,
title: _title,
description: _description,
ipfsCID: _ipfsCID,
propType: _propType,
status: ProposalStatus.ACTIVE,
forVotes: 0,
againstVotes: 0,
startTime: block.timestamp + votingDelay,
endTime: block.timestamp + votingDelay + votingPeriod,
quorum: 0,
executed: false
});
emit ProposalCreated(proposalCount, msg.sender, _title);
return proposalCount;
}
function castVote(uint256 _proposalId, bool _support) external nonReentrant {
Proposal storage proposal = proposals[_proposalId];
require(proposal.status == ProposalStatus.ACTIVE, "Proposal not active");
require(block.timestamp >= proposal.startTime, "Voting not started");
require(block.timestamp <= proposal.endTime, "Voting ended");
require(votes[_proposalId][msg.sender].timestamp == 0, "Already voted");
uint256 votingPower = governanceToken.balanceOf(msg.sender);
require(votingPower > 0, "No voting power");
votes[_proposalId][msg.sender] = Vote({
voter: msg.sender,
proposalId: _proposalId,
support: _support,
votingPower: votingPower,
timestamp: block.timestamp
});
if (_support) {
proposal.forVotes += votingPower;
} else {
proposal.againstVotes += votingPower;
}
emit VoteCast(_proposalId, msg.sender, _support, votingPower);
}
function executeProposal(uint256 _proposalId) external onlyRole(CURATOR_ROLE) {
Proposal storage proposal = proposals[_proposalId];
require(proposal.status == ProposalStatus.ACTIVE, "Not active");
require(block.timestamp > proposal.endTime, "Voting still active");
require(!proposal.executed, "Already executed");
uint256 totalVotes = proposal.forVotes + proposal.againstVotes;
uint256 totalSupply = governanceToken.totalSupply();
require(totalVotes * 100 >= totalSupply * quorumPercentage, "Quorum not met");
if (proposal.forVotes > proposal.againstVotes) {
proposal.status = ProposalStatus.APPROVED;
proposal.executed = true;
emit ProposalExecuted(_proposalId);
} else {
proposal.status = ProposalStatus.REJECTED;
}
}
function createContentProject(
string memory _title,
string memory _description,
ContentCategory _category,
uint256 _fundingGoal
) external onlyRole(CREATOR_ROLE) returns (uint256) {
projectCount++;
projects[projectCount] = ContentProject({
projectId: projectCount,
title: _title,
description: _description,
creator: msg.sender,
category: _category,
fundingGoal: _fundingGoal,
totalFunded: 0,
proposalIds: new uint256[](0),
isActive: true
});
emit ProjectCreated(projectCount, _title, msg.sender);
return projectCount;
}
function contributeToProject(uint256 _projectId) external payable nonReentrant {
ContentProject storage project = projects[_projectId];
require(project.isActive, "Project not active");
project.totalFunded += msg.value;
}
function getProposalVotes(uint256 _proposalId) external view returns (uint256 forVotes, uint256 againstVotes) {
Proposal storage proposal = proposals[_proposalId];
return (proposal.forVotes, proposal.againstVotes);
}
}
第三幕:内容共创的"案例"
第一场:从"Mirror"到"内容DAO"——"去中心化"的"内容平台"
Mirror是一个"去中心化"的内容平台:
- 写作:创作者"发布"文章——"链上"存储、"NFT"铸造、"Token"激励。
- 众筹:创作者"发起"众筹——"社区"支持、"Token"分配、"收入"共享。
- 治理:社区"投票"决定——"内容"方向、"资金"分配、"平台"规则。
第二场:从"Bankless"到"DAO媒体"——"去中心化"的"媒体"
Bankless是一个"DAO"驱动的"媒体"品牌:
- 内容社区:Bankless的"社区"成员"参与"内容的"创作"和"策展"。
- Token激励:BANK Token"激励"社区"贡献"——"写作"、"编辑"、"策展"。
- 治理参与:Token持有者"投票"决定"内容"方向——"焦点"主题、"嘉宾"邀请。
第三场:从"内容DAO"到"创作者经济"——"去中心化"的"创作者经济"
内容DAO在"创作者经济"中的"角色":
- 创作者与粉丝:创作者"发布"提案,粉丝"投票"决定——"内容"方向、"合作"项目。
- 创作者与赞助商:赞助商"赞助"提案——"Token"、"NFT"、"资金"。
- 创作者与平台:平台"治理"由DAO"决定"——"规则"、"算法"、"收入"分配。
import json
from typing import Dict, List, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta
from web3 import Web3
import hashlib
@dataclass
class Proposal:
proposal_id: int
title: str
description: str
proposer: str
proposal_type: str
status: str
for_votes: int
against_votes: int
created_at: datetime
voting_end: datetime
quorum: int
class ContentDAOClient:
def __init__(self, rpc_url: str, dao_address: str):
self.w3 = Web3(Web3.HTTPProvider(rpc_url))
self.dao_address = dao_address
self.proposals: Dict[int, Proposal] = {}
self.votes: Dict[int, Dict[str, Dict]] = {}
self.reputation: Dict[str, int] = {}
def create_proposal(
self,
title: str,
description: str,
proposal_type: str,
proposer: str
) -> Proposal:
proposal_id = len(self.proposals) + 1
proposal = Proposal(
proposal_id=proposal_id,
title=title,
description=description,
proposer=proposer,
proposal_type=proposal_type,
status='active',
for_votes=0,
against_votes=0,
created_at=datetime.now(),
voting_end=datetime.now() + timedelta(days=7),
quorum=0
)
self.proposals[proposal_id] = proposal
return proposal
def cast_vote(self, proposal_id: int, voter: str, support: bool, voting_power: int) -> Dict:
if proposal_id not in self.proposals:
raise ValueError("Proposal not found")
proposal = self.proposals[proposal_id]
if proposal.status != 'active':
raise ValueError("Proposal not active")
if datetime.now() > proposal.voting_end:
raise ValueError("Voting ended")
if proposal_id not in self.votes:
self.votes[proposal_id] = {}
if voter in self.votes[proposal_id]:
raise ValueError("Already voted")
self.votes[proposal_id][voter] = {
'support': support,
'voting_power': voting_power,
'timestamp': datetime.now().isoformat()
}
if support:
proposal.for_votes += voting_power
else:
proposal.against_votes += voting_power
return {
'proposal_id': proposal_id,
'voter': voter,
'support': support,
'voting_power': voting_power
}
def execute_proposal(self, proposal_id: int) -> Dict:
proposal = self.proposals[proposal_id]
if proposal.status != 'active':
return {'success': False, 'error': 'Not active'}
total_votes = proposal.for_votes + proposal.against_votes
if total_votes < proposal.quorum:
return {'success': False, 'error': 'Quorum not met'}
if proposal.for_votes > proposal.against_votes:
proposal.status = 'approved'
return {'success': True, 'result': 'approved'}
else:
proposal.status = 'rejected'
return {'success': True, 'result': 'rejected'}
def create_content_project(
self,
title: str,
description: str,
category: str,
creator: str,
funding_goal: int
) -> Dict:
project_id = hashlib.sha256(f"{title}{creator}{datetime.now()}".encode()).hexdigest()[:8]
project = {
'project_id': project_id,
'title': title,
'description': description,
'creator': creator,
'category': category,
'funding_goal': funding_goal,
'total_funded': 0,
'proposals': [],
'is_active': True,
'created_at': datetime.now().isoformat()
}
return project
def get_collaboration_score(self, address: str) -> Dict:
score = self.reputation.get(address, 0)
proposal_count = sum(1 for p in self.proposals.values() if p.proposer == address)
vote_count = sum(1 for v in self.votes.values() if address in v)
return {
'address': address,
'reputation_score': score,
'proposals_created': proposal_count,
'votes_cast': vote_count,
'collaboration_level': 'high' if score > 80 else 'medium' if score > 40 else 'low'
}
def suggest_content_direction(self, community_votes: Dict[str, int]) -> Dict:
total = sum(community_votes.values())
if total == 0:
return {'direction': 'unknown', 'confidence': 0}
directions = {
'educational': 0,
'entertainment': 0,
'news': 0,
'research': 0,
'collaboration': 0
}
for topic, votes in community_votes.items():
if topic in directions:
directions[topic] = votes / total * 100
best_direction = max(directions, key=directions.get)
return {
'direction': best_direction,
'confidence': directions[best_direction],
'all_directions': directions
}
dao = ContentDAOClient('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY', '0xDAO')
proposal = dao.create_proposal(
"Create a documentary series about DeFi",
"Proposal to fund a 5-part documentary series exploring DeFi protocols",
"content_direction",
"0xCreator"
)
print(f"Proposal #{proposal.proposal_id}: {proposal.title}")
第四幕:从"Web2评论"到"Web3提案"——"参与"的"未来"
第一场:从"评论"到"策展"——"内容"的"策展"经济
内容策展的"经济"模型:
- 策展人(Curator):用户"策展"内容——"推荐"、"评分"、"筛选"。
- 策展Token:策展人"获得"策展Token——"激励"策展"行为"。
- 策展DAO:策展人"组成"DAO——"共同"决定"内容"的质量和"方向"。
第二场:从"内容DAO"到"跨DAO协作"——"内容"的"跨组织"协作
跨DAO协作的"模式":
- 内容DAO与DeFi DAO:内容DAO"创作"DeFi"内容",DeFi DAO"赞助"内容"创作"。
- 内容DAO与NFT DAO:内容DAO"创作"NFT"内容",NFT DAO"发行"NFT"收藏"。
- 内容DAO与媒体DAO:内容DAO"创作"内容,媒体DAO"分发"内容。
第三场:从"Web2评论"到"Web3治理"——"参与"的"民主化"
内容参与"民主化"的"未来":
- 从"评论"到"决策":用户从"评论"内容到"决定"内容。
- 从"被动"到"主动":用户从"被动"消费到"主动"参与。
- 从"消费者"到"参与者":用户从"内容"消费者到"内容"参与者。
const { ethers } = require('ethers');
const axios = require('axios');
class ContentDAOGovernance {
constructor(providerUrl, daoAddress, governanceTokenAddress) {
this.provider = new ethers.providers.JsonRpcProvider(providerUrl);
this.daoAddress = daoAddress;
this.governanceTokenAddress = governanceTokenAddress;
this.proposals = new Map();
this.votes = new Map();
this.reputation = new Map();
}
async createProposal(title, description, proposalType, proposer) {
const proposalId = this.proposals.size + 1;
const proposal = {
id: proposalId,
title,
description,
proposer,
type: proposalType,
status: 'active',
forVotes: ethers.BigNumber.from(0),
againstVotes: ethers.BigNumber.from(0),
createdAt: Math.floor(Date.now() / 1000),
votingEnds: Math.floor(Date.now() / 1000) + 7 * 86400,
executed: false,
quorum: ethers.BigNumber.from(1000)
};
this.proposals.set(proposalId, proposal);
return proposal;
}
async castVote(proposalId, voter, support, votingPower) {
const proposal = this.proposals.get(proposalId);
if (!proposal) throw new Error('Proposal not found');
if (proposal.status !== 'active') throw new Error('Proposal not active');
const voteKey = `${proposalId}-${voter}`;
if (this.votes.has(voteKey)) throw new Error('Already voted');
const vote = {
voter,
proposalId,
support,
votingPower: ethers.BigNumber.from(votingPower),
timestamp: Math.floor(Date.now() / 1000)
};
this.votes.set(voteKey, vote);
if (support) {
proposal.forVotes = proposal.forVotes.add(votingPower);
} else {
proposal.againstVotes = proposal.againstVotes.add(votingPower);
}
return vote;
}
async executeProposal(proposalId) {
const proposal = this.proposals.get(proposalId);
if (!proposal) throw new Error('Proposal not found');
if (proposal.executed) throw new Error('Already executed');
const totalVotes = proposal.forVotes.add(proposal.againstVotes);
if (totalVotes.lt(proposal.quorum)) {
throw new Error('Quorum not met');
}
proposal.executed = true;
proposal.status = proposal.forVotes.gt(proposal.againstVotes) ? 'approved' : 'rejected';
return {
proposalId,
status: proposal.status,
forVotes: proposal.forVotes.toString(),
againstVotes: proposal.againstVotes.toString()
};
}
async createContentProject(title, description, category, creator, fundingGoal) {
const projectId = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(`${title}${creator}${Date.now()}`)
).slice(0, 10);
const project = {
projectId,
title,
description,
creator,
category,
fundingGoal: ethers.utils.parseEther(fundingGoal.toString()),
totalFunded: ethers.BigNumber.from(0),
proposals: [],
isActive: true,
createdAt: Math.floor(Date.now() / 1000)
};
return project;
}
async contributeToProject(project, amount) {
project.totalFunded = project.totalFunded.add(ethers.utils.parseEther(amount.toString()));
return project;
}
async getCommunitySentiment(proposalId) {
const proposal = this.proposals.get(proposalId);
if (!proposal) return { sentiment: 'unknown', confidence: 0 };
const totalVotes = proposal.forVotes.add(proposal.againstVotes);
if (totalVotes.isZero()) return { sentiment: 'no_votes', confidence: 0 };
const forPercentage = proposal.forVotes.mul(100).div(totalVotes).toNumber();
return {
sentiment: forPercentage > 66 ? 'strong_approval' : forPercentage > 50 ? 'approval' : 'rejection',
confidence: Math.abs(forPercentage - 50) * 2,
forPercentage
};
}
async calculateReputation(address) {
let score = this.reputation.get(address) || 0;
const userProposals = Array.from(this.proposals.values())
.filter(p => p.proposer === address);
const userVotes = Array.from(this.votes.values())
.filter(v => v.voter === address);
score += userProposals.length * 10;
score += userVotes.length * 5;
this.reputation.set(address, score);
return {
address,
score,
proposalsCreated: userProposals.length,
votesCast: userVotes.length,
level: score > 80 ? 'trusted' : score > 40 ? 'active' : 'newcomer'
};
}
}
const governance = new ContentDAOGovernance(
'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
'0xDAO',
'0xToken'
);
governance.createProposal(
'Fund a documentary about DeFi protocols',
'5-part documentary series exploring Aave, Compound, Uniswap',
'content_direction',
'0xCreator'
).then(p => console.log('Proposal:', p.id));
终场:从"评论"到"提案"——"内容"的"民主化"
从Web2的"评论"到Web3的"提案",从"点赞"到"投票",从"创作者决定"到"社区共创"——链上治理正在"重塑"内容创作的"权力"结构。这不是"技术"的"进步",而是"社会"的"变革"——内容创作的"民主化"。
在这个万物皆可Token化的时代,技术的迭代往往比镜头切换更快。作为北京城市学院2021级广播电视编导的毕业生,我始终在影像与区块链的交汇处寻找共鸣。感谢阅读,我是王森涛,让我们在视听与去中心化的世界里,继续探索。