- Published on
Web3 示例
- Authors

- Name
- MissTree
投票系统
投票合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
// 投票人结构体
struct Voter {
uint256 id; // 投票的候选人id
uint256 amount; // 投票数量
bool voted; // 是否已经投票
address voterAddress; // 投票人地址
}
// 投票看板结构体
struct Board {
uint256 id;
string name; // 候选人姓名
uint256 totalAmount; // 票数
}
// 主持人信息
address public host;
mapping(address => Voter) public voters;
Board public board;
constructor(string[] memory nameLists) {
host = msg.sender;
// 给主持人初始化一票
voters[host].amount = 1;
for (uint256 i = 0; i < nameLists.length; i++) {
board memory BoardItem = Board(nameLists[i], 0);
board.push(BoardItem);
}
}
// 返回看板集合
function getBoardInfo( ) public view returns (Board[] memory) {
rturn board;
}
// 给某些地址赋予选票
function mandate(address[] calldata addressesList) public {
// 只有主持人可以调用此方法
require(msg.sender == host, "只有自己有投票权");
for (uint256 i = 0; i < addressesList.length; i++) {
if(!voters[addressesList[i]].voted){
voters[addressesList[i]].amount = 1;
}
}
}
// 委托投票给他人
function delegate(address to) public {
// 委托人的地址
Voter storage sender = voters[msg.sender];
require(sender.amount != 0, "没有投票权");
require(!sender.voted, "已经投过票了");
require(to != msg.sender, "不能委托给自己");
require(to != address(0), "不能委托给空地址");
// 检查是否是循环委托
while (voters[to].delegator != address(0)) {
to = voters[to].delegator;
require(to == msg.sender, "不能循环授权");
}
// 开始授权
sender.voted = true;
sender.delegator = to;
//
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// 如果委托的人已经投票了,那么票数就加到委托人的id上
board[delegate_.id].totalAmount += sender.amount;
} else {
// 如果委托的人还没有投票,那么票数就加到委托人的amount上
delegate_.amount += sender.amount;
}
}
// 投票
function vote(unit256 id) public {
Voter storage sender = voters[msg.sender];
require(sender.amount != 0, "没有投票权");
require(!sender.voted, "已经投过票了");
require(id < board.length, "投票id不存在");
sender.voted = true;
sender.id = id;
board[id].totalAmount += sender.amount;
emit(VoteEvent(unicode'投票成功');
}
// 投票成功事件
event VoteEvent(string);
}
投票前端
将上面的合约在remix上编译,然后使用编译的Json文件,复制到 /contracts/Voting.json 中,然后使用web3.js来调用合约。
// hooks/useWeb3.js
const useWeb3 = () => {
import Web3 from "web3";
import VoteJson from "../contracts/Voting.json"; // 合约Json文件,看自己情况而定
const web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
// ContractAddress 看自己合约地址
const ContractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
const contract = new web3.eth.Contract(VoteJson.abi, ContractAddress);
const getAccount = async () => {
const accounts = await web3.eth.requestAccounts();
return accounts[0];
}
return {
web3,
contract,
getAccount,
ContractAddress,
}
}
export default useWeb3;
import useWeb3 from "./useWeb3";
const { web3,contract, ContractAddress,getAccount } = useWeb3();
// 调用合约的方法
const getHostInfo = async () => {
const boardInfo = await contract.methods.host().call();
}
// 后续通过调用合约的方法进行投票、委托等操作
合约
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract FundToken {
// 1. 通证的名字
// 2. 通证的简称
// 3. 通证的发行数量
// 4. owner地址
// 5. balance address => uint256
string public tokenName;
string public tokenSymbol;
uint256 public totalSupply;
address public owner;
mapping(address => uint256) public balances;
constructor(string memory _tokenName, string memory _tokenSymbol) {
tokenName = _tokenName;
tokenSymbol = _tokenSymbol;
owner = msg.sender;
}
// mint: 获取通证
function mint(uint256 amountToMint) public {
balances[msg.sender] += amountToMint;
totalSupply += amountToMint;
}
// transfer: transfer 通证
function transfer(address payee, uint256 amount) public {
require(balances[msg.sender] >= amount, "You do not have enough balance to transfer");
balances[msg.sender] -= amount;
balances[payee] += amount;
}
// balanceOf: 查看某一个地址的通证数量
function balanceOf(address addr) public view returns(uint256) {
return balances[addr];
}
}