以太坊智能合约实例解析,从简单投票到代币发行

来源:投稿时间:2026-02-28 23:30点击:11

简单投票合约(Solidity示例)

投票是最常见的民主决策机制,而以太坊智能合约可以提供一个透明、防篡改的投票系统。

合约功能:

  1. 部署时创建多个候选人选项。
  2. 只有注册的投票者(地址)才能投票,且只能投一次票。
  3. 投票过程公开透明,结果实时可查,直到投票结束。
  4. 投票结束后,可以统计并公布各候选人的得票数。

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标准):

  1. 定义代币名称(Token Name)、符号(Symbol)、小数位数(Decimals)。
  2. 记录每个地址的代币余额(mapping(address => uint256) balanceOf)。
  3. 支持代币转账(transfer函数):从调用者地址向指定地址转移代币。
  4. 支持授权转账(approvetransferFrom函数):地址A授权地址B从A账户中转移代币,常用于交易所或合约交互。
  5. 记录授权情况(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万个代币。decimals()通常返回18,表示代币可分割到小数点后18位,所以实际发行量是 1000000 * 10^18 个最小单位。

这个例子展示了智能合约的标准化和可复用性,开发者无需从头实现复杂的代币逻辑,只需基于标准库进行少量定制即可。


简单众筹合约(Crowdsourcing示例)

众筹是一种向大众募集资金的方式,智能合约可以确保资金使用的透明度和项目方的履约能力。

合约功能:

  1. 设定众筹目标金额(goal)和截止时间(deadline)。
  2. 投资者(支持者)可以向合约地址发送以太币(ETH)进行支持。
  3. 如果众筹成功(在截止时间前达到或超过目标金额),项目方可以提取筹集到的资金。
  4. 如果众筹失败,投资者可以申请退还其支持的ETH。

Solidity代码简化示例:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleCrowdfunding {
    address public creator;
    uint public goal;
    uint public deadline;
    mapping(address => uint) public contributions;
    bool public fundingSuccessful;
    bool public fundsClaimed;
    event Funded(address indexed backer, uint amount);
    event CreatorWithdrawn(uint amount);
    event Refunded(address indexed backer, uint amount);
    constructor(uint _goal, uint _durationInDays) {
        creator = msg.sender;
        goal = _goal * 1 ether; // 假设goal是以太,乘以1 ether转换为wei
        deadline = block.timestamp + _durationInDays * 1 days;
    }
    function fund() public payable {
        require(block.timestamp < deadline, "Deadline passed");
        require(msg.value > 0, "Must send ETH");
        contributions[msg.sender] += msg.value;
        emit Funded(msg.sender, msg.value);
    }
    function withdrawFunds() public {
        require(msg.sender == creator, "Only creator can withdraw");
        require(block.timestamp >= deadline, "Deadline not reached");
        require(!fundsClaimed, "Funds already claimed");
        if (address(this).balance >= goal) {
            fundingSuccessful = true;
            payable(creator).transfer(address(this).balance);
            emit CreatorWithdrawn(address(this).balance);
        }
        fundsClaimed = true;
    }
    function refund() public {
        require(block.timestamp >= deadline, "Deadline not reached");
        require(!fundingSuccessful, "Funding successful, no refund");
        require(contributions[msg.sender] > 0, "No contribution to refund");
        uint amount = contributions[msg.sender];
        contributions[msg.sender] = 0;
        payable(msg.sender).transfer(amount);
        emit Refunded(msg.sender, amount);
    }
}

解析:

  • creator:项目方创建者地址。
  • goal:众筹目标金额(以wei为单位)。
  • deadline:众筹截止时间戳。
  • contributions:记录每个投资者的贡献金额。
  • fundingSuccessful:标记众筹是否成功。随机配图
li>
  • fund():投资者调用此函数发送ETH,并记录贡献。
  • withdrawFunds():项目方在截止时间后调用,如果达到目标则提取资金。
  • refund():投资者在截止时间后且众筹失败时调用,取回其贡献的ETH。
  • event:用于记录链上重要操作,方便外部应用监听
  • 标签:

    上一篇
    下一篇