3、智能合约基础:Solidity语言入门、Remix IDE使用、智能合约编译与部署、与DAO相关的合约模式
好,咱们进入正题。这一章是DAO开发的地基。说白了,不懂智能合约,后面所有关于DAO的治理、投票、金库管理都是空中楼阁。我个人习惯把这一章叫做「从零到一写合约」,因为我会带你亲手写一个能跑的合约,再把它部署到链上。
你想想看,DAO本质上就是一组智能合约的集合。所以,咱们得先把单个合约玩明白。
3.1 Solidity语言入门:别怕,它没那么玄乎
Solidity是啥?它是以太坊上写智能合约的主流语言。语法上跟JavaScript有点像,但又有自己的脾气。我第一次接触时也觉得别扭,尤其是那个address类型和msg.sender,当时老搞混。
咱们先看一个最简单的合约骨架:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleDAO {
// 状态变量
address public owner;
uint256 public proposalCount;
// 构造函数
constructor() {
owner = msg.sender;
}
// 修饰符
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
// 事件
event ProposalCreated(uint256 indexed id);
// 函数
function createProposal() public onlyOwner {
proposalCount++;
emit ProposalCreated(proposalCount);
}
}
这里有几个关键点,我重点说一下:
- 状态变量:存在链上的数据,永久保存。比如
owner和proposalCount。 - 构造函数:部署时只执行一次。我习惯在这里初始化管理员地址。
- 修饰符:
onlyOwner这种,用来做权限控制。DAO里到处都是这玩意儿。 - 事件:链上日志,前端可以监听。嗯,调试时特别好用。
3.2 Remix IDE使用:浏览器里的开发利器
别急着装什么VSCode插件。刚开始,我强烈建议你用Remix IDE。它就是个网页版IDE,打开浏览器就能用。地址是 remix.ethereum.org,你搜一下就有。
为什么推荐它?因为零配置。你不需要装Node.js、不需要配Hardhat,直接写代码、编译、部署一条龙。我记得我第一次在Remix上部署合约时,点一下按钮就成功了,那种感觉——嗯,很爽。
基本操作流程:
- 左侧文件浏览器,新建一个
.sol文件。 - 把上面的代码粘贴进去。
- 切换到「Solidity Compiler」标签,点编译。
- 切换到「Deploy & Run Transactions」标签,选环境(比如JavaScript VM,这是本地模拟链)。
- 点「Deploy」,搞定。
3.3 智能合约编译与部署:从字节码到链上
编译,就是把Solidity代码变成字节码。Remix里点一下编译按钮,底下会出现ABI和Bytecode。ABI是接口描述,前端调用合约时需要它。Bytecode就是部署到链上的二进制代码。
部署时,你会遇到一个概念叫Gas。每次操作都要付燃料费。我刚开始总是不理解,为什么改个数字也要花钱?后来想通了——你是在占用全球计算机的资源,当然要付费。
部署流程其实就三步:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 编译 | 生成ABI和Bytecode |
| 2 | 签名 | 用私钥签署交易 |
| 3 | 广播 | 发送到网络,等待确认 |
在Remix里,这些步骤被简化了。你只需要点一下「Deploy」,剩下的它帮你搞定。但你要理解背后发生了什么——你的钱包签名了一笔交易,矿工把它打包进区块,然后你的合约就有了一个地址。
require,导致合约上线后被人钻了空子。嗯,那晚我睡得特别晚。
3.4 与DAO相关的合约模式:投票、治理、金库
好,前面都是基础。现在咱们聊聊DAO里常用的合约模式。说白了,DAO就是一群人通过合约做决策。那合约得支持哪些功能?
3.4.1 投票模式
最简单的投票,就是每个人投一票,按票数决定。但DAO里通常用代币加权投票——你持有的代币越多,投票权重越大。
核心代码大概长这样:
contract SimpleVote {
mapping(address => uint256) public votes;
uint256 public totalVotes;
function vote(uint256 _amount) public {
// 假设用户有代币,这里简化处理
votes[msg.sender] += _amount;
totalVotes += _amount;
}
function getVotePower(address _voter) public view returns (uint256) {
return votes[_voter];
}
}
当然,真实项目里不会这么简单。你会用到ERC20Votes这种标准实现,它内置了委托投票和快照功能。我建议你直接继承OpenZeppelin的合约,别自己造轮子。
3.4.2 治理模式
治理就是提案的创建、投票、执行流程。典型的模式叫Compound Governor。它把治理拆成几个阶段:
- 提案创建:任何人(或满足条件的人)可以发起提案。
- 投票期:持币人投票,通常持续几天。
- 执行期:投票通过后,等待一段时间才能执行。
- 执行:调用目标合约的函数。
为什么要等执行期?为了防止恶意提案被立即执行。嗯,这是安全设计上的一个经典考量。
3.4.3 金库模式
DAO的钱,通常放在一个多签钱包或时间锁合约里。时间锁的意思是,任何操作都要延迟一段时间才能执行。比如,治理投票通过了,但资金要等48小时后才能转出。
我参与过一个项目,金库用的是Gnosis Safe。它支持多签——比如5个多签人里,3个人同意才能转账。这种模式在DAO里非常常见。
3.5 小结:动手写一个迷你DAO合约
说了这么多,不如动手试试。我建议你打开Remix,写一个包含以下功能的合约:
- 一个
owner,部署时设置。 - 一个
propose函数,只有owner能调用。 - 一个
vote函数,任何人都能投票(每人一票)。 - 一个
execute函数,投票通过后执行。
别怕写错。写合约就像学骑车,摔几次就熟了。我第一次写的投票合约,连require都没加,结果一个人能投一万次。嗯,那是我最难忘的一次debug。
下一章,咱们会深入讲ERC20代币与DAO的关系。你会看到,代币不只是用来炒的,它还是DAO里的投票权。准备好了吗?