简单投票合约(Solidity示例)
投票是最常见的民主决策机制,而以太坊智能合约可以提供一个透明、防篡改的投票系统。
合约功能:
- 部署时创建多个候选人选项。
- 只有注册的投票者(地址)才能投票,且只能投一次票。
- 投票过程公开透明,结果实时可查,直到投票结束。
- 投票结束后,可以统计并公布各候选人的得票数。
Solidity代码简化示例:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleVoting {
// 候选人结构体
struct Candidate {
string name;
uint voteCount;
}
// 存储候选人,名字到索引的映射
mapping(string => uint) public candidateNames;
// 存储候选人列表
Candidate[] public candidates;
// 存储投票者,地址到是否已投票的映射
mapping(address => bool) public voters;
// 投票状态
bool public votingOpen = true;
// 构造函数,初始化候选人
constructor(string[] memory candidateList) {
for (uint i = 0; i < candidateList.length; i++) {
candidates.push(Candidate({
name: candidateList[i],
voteCount: 0
}));
candidateNames[candidateList[i]] = i;
}
}
// 投票函数
function vote(string memory candidateName) public {
require(votingOpen, "Voting is closed");
require(!voters[msg.sender], "You have already voted");
uint candidateIndex = candidateNames[candidateName];
require(candidateIndex < candidates.length, "Invalid candidate");
candidates[candidateIndex].voteCount++;
voters[msg.sender] = true;
}
// 关闭投票函数(通常由特定角色调用,或设定时间自动关闭)
function closeVoting() public {
votingOpen = false;
}
// 获取候选人票数
function getVoteCount(string memory candidateName) public view returns (uint) {
return candidates[candidateNames[candidateName]].voteCount;
}
}
解析:
struct Candidate:定义了候选人的数据结构,包含名字和票数。mapping(string => uint) public candidateNames:通过候选人名字快速找到其在数组中的索引。Candidate[] public candidates:动态数组存储所有候选人信息。mapping(address => bool) public voters:记录每个地址是否已投票,防止重复投票。constructor:合约部署时初始化候选人列表。vote:核心投票函数,进行权限检查后更新候选人票数和投票者状态。closeVoting:关闭投票,之后不能再投票。getVoteCount:查询指定候选人的当前票数。
这个例子展示了智能合约的基本要素:状态变量(存储数据)、函数(修改和读取数据)、访问控制(require语句)和逻辑封装。
代币合约(ERC20标准示例)
代币是以太坊上最广泛的应用之一,ERC20是以太坊上代币的通用标准,确保了不同代币之间的兼容性。
合约功能(遵循ERC20标准):
- 定义代币名称(Token Name)、符号(Symbol)、小数位数(Decimals)。
- 记录每个地址的代币余额(
mapping(address => uint256) balanceOf)。 - 支持代币转账(
transfer函数):从调用者地址向指定地址转移代币。 - 支持授权转账(
approve和transferFrom函数):地址A授权地址B从A账户中转移代币,常用于交易所或合约交互。 - 记录授权情况(
mapping(address => mapping(address => uint256)) allowance)。
Solidity代码简化示例(基于OpenZeppelin的ERC20模板):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_mint(msg.sender, 1000000 * 10**decimals()); // 初始发行100万个代币,考虑小数位数
}
}
解析:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";:引入OpenZeppelin库的ERC20标准实现,这是目前最安全、最广泛使用的ERC20合约模板。contract MyToken is ERC20:我们的代币合约继承自ERC20合约,自动获得了所有ERC20标准的功能。constructor(string memory name, string memory symbol) ERC20(name, symbol):构造函数,设置代币名称和符号,并调用父合约ERC20的构造函数。_mint(msg.sender, 1000000 * 10**decimals()):_mint是ERC20合约中的内部函数,用于增发代币,这里给合约部署者(msg.sender)初始发行100万个代币。