ERC-20代币是一种代币标准,由V神于2015年6月提出此标准,由Fabian Vogelsteller(erc20及erc725作者,也是LUKSO Token 创始人)于2015年11月提交EIP-20。该标准允许开发者在以太坊区块链网络上开发属于自己的代币,该标准定义了开发者可以按照标准要求使用一些简单的功能如: - 设定代币名称 - 设定代币总量 - 规定小数点位数 - 规范如何批准代币交易 - 如何访问数据 - 允许查看各地址中erc20代币数目以及代币总量 - 一定条件下,允许第三方账户使用某账户中的代币资产 - 允许代币和兼容ETH的智能合约及钱包服务等第三方个体兼容 以及一些简单的函数功能等等。
- pragma solidity >=0.7.0 <0.9.0;
- ( ^& B. D& S+ _( n
- //投票实验3 u: W7 _$ R B7 [8 P# \) L
- contract Ballot{. h2 c0 c$ D# H$ R3 s1 T
-
- struct Voter{8 c3 d Z* A- z
- uint weight;//投票(单票)权重
- bool voted;//是否投过票,true为投过票,bool类型默认值为false
- address delegate;//想要委托投票的节点地址,address默认值为0x0# y0 E- J; J, L7 V" k
- uint vote;//想要投票的节点的索引值(被投票节点信息用一维数组proposals存储)
- }: H$ g" k7 Y1 G5 z& o6 X5 o6 J
- 9 \$ t/ d$ G! v3 ?2 L$ D
- struct Proposal{//被投票节点的相关参数
- bytes32 name;//被投票节点的姓名标识; q& l( X" } a) p! B
- uint voteCount;//累积被投票数
- }+ z g( j* ?4 F
- , c" T/ i# G2 m, i' A
- address public chairperson;//投票管理员地址
- mapping(address => Voter) public voters;//地址对投票节点的信息的映射
- Proposal[] public proposals;//一维数组存储被投票节点信息
-
- //构造方法、构造函数, F m2 Q8 {" H. t. ~( |& B0 W
- //solidity和其他语言不一样,构造函数仅在部署合约时调用一次,后续调用合约不调用其构造函数
- //且一个合约只能有一个构造函数,不能进行构造函数重载6 X0 ]' U) |6 n* t$ \9 M
- constructor(bytes32[] proposalNames) public{$ D1 N; }$ f$ r* d) \
- chairperson = msg.sender;//将第一次调用该合约的节点设置为管理员/ z1 @7 |; H# x4 N% G+ t* Z
- voters[chairperson].weight = 1;//将管理员投票权置为1
-
- for(uint i=0; i<proposalNames.length; i++){. Q# ~$ S- u' l; r$ M
- //将所有被投票人姓名初始化进一维数组proposals,并将其对应票数初始化为0票
- //.push(),括号中内容需要强调数据类型,eg:arr.push(uint(6));
- proposals.push(Proposal({
- name:proposalNames[i],* f# w# \( _, ~4 G# u2 k
- voteCount:0: i8 o& A$ l3 ^% U- H6 P. m
- }));+ |! k0 o, L+ Q: F& R- x4 w; R
- }; a4 T7 i+ A# J# r7 }
- }" D5 {. f- P9 z$ W7 x* v+ Y
- . m# L! g+ d9 q+ R4 b& W3 _9 n
- //由管理员授权可投票节点
- function giveRightToVote(address voter) public{1 a I; [6 ^' e( z1 k! B
- //require中判断条件为false时,输出字符串"xxx...",异常会被抛出,程序执行会被挂起,
- //未消耗的gas会被退回,合约状态会回退到初始状态
- require(8 }6 o! e% }) a$ ^7 _% b
- msg.sender == chairperson,"Only chairperson can give right to vote."5 b7 i% K% g; S% D) h) j3 Y; a: J; }
- );//执行此function的节点一定为管理员节点2 j) p- q4 i6 ~: v1 V! K
- require(
- !voters[voter].voted,"The voter already voted."& L' O+ }" [3 m. e+ `
- );//若voter没投过票) V# Q5 r3 f4 v7 {- n+ Y, r5 z, m
- require(voters[voter].weight == 0);
- //调用合约的人是管理员、待授权节点还没投过票、带授权节点投票权重为0时,进行授权
- voters[voter].weight = 1;//上述三个require()均成立时,授权票数
- }
- $ H! G* d9 i: x! X0 Z) M$ w0 j
- //投票授权
- function delegate(address to) public{
- Voter storage sender = voters[msg.sender];
- require(!sender.voted, "You already voted.");
- require(to != msg.sender,"Self-delegation is disallowed.");1 h: w/ U% n8 o8 ]7 g3 \3 c
- //sender满足的条件:要有投票权限、没有投过票、被授权节点不是自己8 j( e, \7 |# B1 x: e9 e
- ' {7 R+ M0 o7 O' J9 @! s
- //判断代理节点地址是否为空:address(0)或者address(0x0)
- while(voters[to].delegate != address(0)){0 Y% R. N. f) n8 A' {
- to = voters[to].delegate;//找到最终的代理节点
- require(to != msg.sender,"Found loop in delegation.");//若代理节点最终是自己则回退到初始状态
- }7 ^; l1 v# z3 M1 I
- ) k0 f! U' w' Z. X- l2 o
- sender.voted = true;//票权代理出去,状态改为已投票+ B% @3 a9 p& W7 V8 k
- sender.delegate = to;//票权代理地址3 ]0 f! Q) _. v6 U, @# u
- Voter storage delegate_ = voters[to];//取出代理节点状态
-
- //若代理节点已投过票,将新代理的票权投出去,反之则将代理节点票权加和# g+ o3 E" f& b' ]7 ~, m* w
- if(delegate_.voted){+ h5 N; V' k9 s& w/ }; L j @
- proposals[delegate_.vote].voteCount += sender.weight;
- }else{
- delegate_.weight += sender.weight;/ G6 t* h7 ^* X B, i% H# s
- }
- }
-
- function vote(uint proposal) public{8 o( `" A: @8 p! e' M0 G' P
- Voter storage sender = voters[msg.sender];//通过地址获取对应投票信息
- require(!sender.voted,"Already voted.");//若sender未投过票
- sender.voted = true;//更改投票状态为已投过票
- sender.vote = proposal;//保存已投票节点
- proposals[proposal].voteCount += sender.weight;//票权加和
- }; f% P( G% w3 b2 M. O4 {8 _
-
- //返回票数最多的节点在一维数组proposals中的索引5 O- _- @3 X. q( b4 a$ x% C1 f+ b
- function winningProposal() public view returns(uint winningProposal_){* @3 l; ?" _3 Q: ^
- uint winningVoteCount = 0;
solidity投票智能合约代码,亲测可用