拒绝 DAO 落地难!用代码把「去中心化治理」写进合约:DAO 全流程开发实录

0 阅读7分钟

前言

过往分享内容中,DAO 相关板块涉猎较少。本文将系统梳理 DAO 的核心理论体系,明确 DAO 的定义、功能价值、解决的核心问题与行业落地场景,并对其未来发展进行展望;同时完整拆解 DAO 相关智能合约开发、测试、部署的全流程实操,补齐 DAO 领域理论知识与工程实践的内容短板。

概述

DAO(去中心化自治组织)  是一种基于区块链技术的组织形式。它通过智能合约将组织的规则编码在链上,不依赖中心化管理层(如 CEO 或董事会),而是由社区成员共同管理和决策。

一、 DAO 是什么?(核心三要素)

我们可以将 DAO 理解为 “运行在互联网上的、拥有共同金库的自动化公司”

  • 去中心化 (Decentralized) :权力不集中在个人手中,而是分布在所有持有治理代币的参与者手中。
  • 自治 (Autonomous) :组织的规则(如资金拨付条件)写在代码里。一旦投票通过,智能合约会自动执行,无需人为操作。
  • 组织 (Organization) :一群拥有共同目标的人(开发者、投资者、艺术家等)聚集在一起。

二、 DAO 能做什么?(核心功能)

在 2026 年的背景下,DAO 的功能已经极度成熟:

  • 资产管理(金库) :共同管理一笔巨额资金(ETH、USDC、RWA 资产),用于投资、慈善或项目开发。
  • 集体决策:通过投票决定协议的升级方向、利润分配方案或社区规则。
  • 协同工作:全球不同背景的人通过 DAO 认领任务(Bounties),完成后自动获得报酬,无需签订传统劳动合同。
  • 身份验证:通过发放“灵魂绑定代币”(SBT),证明成员在组织内的贡献度和声誉等级。

三、 DAO 解决了什么问题?(核心痛点)

传统组织 (Web2/实体公司)DAO (Web3 模式)解决的问题
黑箱操作:高层决策不透明,资金去向不明。全流程透明:所有投票、资金流向在区块链上清晰可查。信任成本:无需信任个人,只需信任代码。
官僚低效:层层审批,跨境协作极其困难。代码即执行:投票通过即自动拨款,无缝跨国协作。效率与边界:打破地理限制,实现全球即时响应。
利益分配不均:大股东获利,基层员工贡献被忽视。贡献证明:按贡献(Token/NFT)分配收益,实现公平治理。激励不对等:将参与者从“打工人”变为“所有者”。
中心化审查:平台可随意封禁账户或没收资产。抗审查性:规则由社区决定,不受单一中心控制。自主权:保护参与者的资产和发言权。

四、 行业落地应用(2026 现状)

A. DeFi(去中心化金融)

  • 案例Uniswap 或 MakerDAO
  • 玩法:持有代币的成员投票决定协议的手续费比例、新增哪些资产作为抵押品。

B. DeSci(去中心化科学)

  • 案例VitaDAO
  • 玩法:科学家和资助者共同组成 DAO,绕过传统学术体制,资助长寿研究等前沿课题。研究成果(IP)归 DAO 所有。

C. 创作者与媒体 (Media DAO)

  • 案例BanklessDAO
  • 玩法:内容创作者共同拥有媒体品牌。DAO 成员投票决定报道方向,并根据文章质量或点击量自动从金库结算代币。

D. 物理资产与生活 (Network States)

  • 案例CityDAO
  • 玩法:成员共同出资在现实世界购买土地或房产。2026 年,通过 RWA(实物资产上链) ,DAO 成员可以直接在全球范围共有并经营实体资产(如共享办公空间)。

E. AI 治理 (AI DAO)

  • 案例SingularityNET
  • 玩法:人类通过 DAO 设定 AI 的伦理准则和发展方向,防止 AI 被单一巨头垄断,确保 AI 产生的收益惠及全体参与者。

五、 DAO 的未来

到 2026 年,DAO 不再是极客的实验,它成为了 “数字原生组织” 的标准。它不仅解决了信任问题,还通过 AI 代理 提升了治理速度,通过 法律合规化(如 MiCA 法案)实现了与现实世界的接轨。

六、智能合约落地全流程

智能合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; // 必须显式导入
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";

// 1. 投票代币合约
contract MyToken is ERC20, ERC20Permit, ERC20Votes {
    constructor() ERC20("MyDAO", "MDAO") ERC20Permit("MyDAO") {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }

    // OpenZeppelin V5 要求的重写
    function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Votes) {
        super._update(from, to, value);
    }

    function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }
}

// 2. 治理合约
contract MyGovernor is Governor, GovernorSettings, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction {
    constructor(IVotes _token)
        Governor("MyGovernor")
        GovernorSettings(1, /* 1 block voting delay */ 7200, /* ~1 day voting period */ 0)
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) // 4% 法定人数
    {}

    // 以下为 OpenZeppelin 插件组合所需的样板代码
    function votingDelay() public view override(Governor, GovernorSettings) returns (uint256) {
        return super.votingDelay();
    }

    function votingPeriod() public view override(Governor, GovernorSettings) returns (uint256) {
        return super.votingPeriod();
    }

    function quorum(uint256 blockNumber) public view override(Governor, GovernorVotesQuorumFraction) returns (uint256) {
        return super.quorum(blockNumber);
    }

    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
        return super.proposalThreshold();
    }
}

测试脚本

测试用例说明

  • 完成从提案到执行的完整生命周期
  • 如果赞成票不足,提案应当失败
import assert from "node:assert/strict";
import { describe, it, beforeEach } from "node:test";
import { network } from "hardhat";
import { keccak256, encodePacked, encodeFunctionData, decodeEventLog } from 'viem';

describe("MyDAO Governance (OZ V5 + Viem)", function () {
    let token: any;
    let governor: any;
    let publicClient: any;
    let testClient: any;
    let deployer: any, voter: any, proposer: any;

    beforeEach(async function () {
        // 1. 获取客户端
        const { viem } = await (network as any).connect();
        publicClient = await viem.getPublicClient();
        testClient = await viem.getTestClient();
        [deployer, voter, proposer] = await viem.getWalletClients();

        // 2. 部署合约 (使用完全限定名解决 HHE1001)
        token = await viem.deployContract("contracts/DAO.sol:MyToken", []);
        governor = await viem.deployContract("contracts/DAO.sol:MyGovernor", [token.address]);

        // 3. 初始资金准备
      const amount = 50000n * 10n ** 18n; 
        // 给投票者代币并委托(激活票权)
        await token.write.transfer([voter.account.address, amount]);
        await token.write.delegate([voter.account.address], { account: voter.account });
        
        // --- 重要:给 DAO 金库(Governor 合约)注资,否则 execute 会失败 ---
        await token.write.transfer([governor.address, amount]);

        // 4. 推进区块确保委托快照生效
        await testClient.mine({ blocks: 5 });
    });

    describe("Proposal Lifecycle", function () {
        it("应该完成从提案到执行的完整生命周期", async function () {
            // --- 1. 准备提案数据 ---
            const calldata = encodeFunctionData({
                abi: token.abi,
                functionName: 'transfer',
                args: [proposer.account.address, 100n]
            });
            const description = "Proposal #1: Support AI Research";
            const descHash = keccak256(encodePacked(['string'], [description]));

            // --- 2. 发起提案 ---
            const txHash = await governor.write.propose([
                [token.address], [0n], [calldata], description
            ], { account: proposer.account });
            
            const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
            
            // 健壮地从 logs 中提取 ProposalCreated 事件
            const event = decodeEventLog({
                abi: governor.abi,
                eventName: 'ProposalCreated',
                data: receipt.logs[0].data,
                topics: receipt.logs[0].topics,
            });
            const proposalId = (event.args as any).proposalId;

            // --- 3. 进入投票期 ---
            // 修复点:mine 2 个区块确保跨越 votingDelay 并进入 Active 状态
            await testClient.mine({ blocks: 5 });
            
            let state = await governor.read.state([proposalId]);
            assert.equal(Number(state), 1, "提案应处于 Active (1) 状态");

            // --- 4. 投票 (1 = For) ---
            await governor.write.castVote([proposalId, 1], { account: voter.account });

            // --- 5. 推进时间直到投票结束 ---
            // 超过 votingPeriod (7200 blocks)
            await testClient.mine({ blocks: 7205 }); 

            state = await governor.read.state([proposalId]);
            assert.equal(Number(state), 4, "提案应处于 Succeeded (4) 状态");

            // --- 6. 执行提案 ---
            await governor.write.execute([
                [token.address], [0n], [calldata], descHash
            ], { account: deployer.account });

            // --- 7. 最终验证 ---
            state = await governor.read.state([proposalId]);
            assert.equal(Number(state), 7, "提案应处于 Executed (7) 状态");
            
            const balance = await token.read.balanceOf([proposer.account.address]);
            assert.ok(balance >= 100n, "Proposer 应该收到了金库转账");
            
            console.log(`✅ 提案 ${proposalId.toString().slice(0,10)} 执行成功`);
        });

        it("如果赞成票不足,提案应当失败", async function () {
            const calldata = '0x';
            const description = "Fail Proposal";
            const tx = await governor.write.propose([[token.address], [0n], [calldata], description]);
            const receipt = await publicClient.waitForTransactionReceipt({ hash: tx });
            
            const event = decodeEventLog({
                abi: governor.abi, eventName: 'ProposalCreated',
                data: receipt.logs[0].data, topics: receipt.logs[0].topics 
            });
            const proposalId = (event.args as any).proposalId;

            await testClient.mine({ blocks: 2 });
            
            // 投反对票 (0 = Against)
            await governor.write.castVote([proposalId, 0], { account: voter.account });
            
            await testClient.mine({ blocks: 7205 }); 
            const state = await governor.read.state([proposalId]);
            assert.equal(Number(state), 3, "提案应处于 Defeated (3) 状态");
        });
    });
});

部署脚本

// scripts/deploy.js
import { network, artifacts } from "hardhat";
async function main() {
  // 连接网络
  const { viem } = await network.connect({ network: network.name });//指定网络进行链接
  
  // 获取客户端
  const [deployer] = await viem.getWalletClients();
  const publicClient = await viem.getPublicClient();
 
  const deployerAddress = deployer.account.address;
   console.log("部署者的地址:", deployerAddress);
  // 加载合约
  const TokenArtifact = await artifacts.readArtifact("contracts/DAO.sol:MyToken");
  const GovernorArtifact = await artifacts.readArtifact("contracts/DAO.sol:MyGovernor");

 const TokenHash = await deployer.deployContract({
    abi: TokenArtifact.abi,//获取abi
    bytecode: TokenArtifact.bytecode,//硬编码
    args: [],
  });
  const TokenReceipt = await publicClient.waitForTransactionReceipt({ hash: TokenHash });
  console.log("Token合约地址:", TokenReceipt.contractAddress);
  // 部署
  const GovernorHash = await deployer.deployContract({
    abi: GovernorArtifact.abi,//获取abi
    bytecode: GovernorArtifact.bytecode,//硬编码
    args: [TokenReceipt.contractAddress],
  });
   const GovernorReceipt = await publicClient.waitForTransactionReceipt({ hash: GovernorHash });
   console.log("Governor合约地址:", GovernorReceipt.contractAddress);
}

main().catch(console.error);

结语

至此,关于 DAO 从理论知识梳理到相关智能合约落地的全流程内容已全部完成。本文完整打通 DAO 理论体系与工程实践,补齐该领域知识与实操短板,为后续深入研究与落地开发奠定基础。