Council 选举允许代币持有者为候选人投票。得票最多的候选人成为 Council 成员。投票需要锁定代币到 Council 合约中。
选举流程
选举开始
选举被发起(需要平台的 EIP-712 签名)。选举有固定的持续时间。
投票期
代币持有者授权代币给 Council 合约,然后调用 voteElection() 为候选人投票。代币在选举结束前一直锁定。
选举结束
endTime 过后,任何人都可以调用 claimElectionTokens()。第一个调用者触发结算——得票最高的候选人成为 Council 成员。
领回代币
所有投票者调用 claimElectionTokens() 取回锁定的代币。
读取选举状态
const council = new ethers.Contract(councilAddress, CouncilV1ABI, provider);
const state = await council.getElectionState(tokenAddress);
console.log("进行中:", state.active);
console.log("结束时间:", new Date(Number(state.endTime) * 1000));
console.log("已结算:", state.finalized);
console.log("席位数:", state.councilSize.toString());
console.log("届期:", state.epoch.toString());
选举状态字段
| 字段 | 类型 | 说明 |
|---|
active | bool | 选举是否正在进行 |
endTime | uint256 | 选举结束时间戳(unix 秒) |
lastElectionEnd | uint256 | 上一次选举结束时间 |
finalized | bool | 当前/上次选举结果是否已结算 |
councilSize | uint256 | Council 席位数 |
epoch | uint256 | 选举届期计数器 |
在选举中投票
投票前,必须先 approve Council 合约转移你的代币。
const tokenContract = new ethers.Contract(tokenAddress, [
"function approve(address spender, uint256 amount) returns (bool)",
], signer);
const council = new ethers.Contract(councilAddress, CouncilV1ABI, signer);
// 1. 授权代币
const amount = ethers.parseEther("10000");
await (await tokenContract.approve(councilAddress, amount)).wait();
// 2. 为候选人投票
// 可以将代币分配给多个候选人
const votes = [
{ candidate: "0xCandidate1...", amount: ethers.parseEther("6000") },
{ candidate: "0xCandidate2...", amount: ethers.parseEther("4000") },
];
const tx = await council.voteElection(tokenAddress, votes);
await tx.wait();
查看候选人
// 获取前 20 名候选人,按得票数降序排列
const [candidates, voteAmounts] = await council.getTop20Candidates(tokenAddress);
for (let i = 0; i < candidates.length; i++) {
if (candidates[i] === ethers.ZeroAddress) break;
console.log(`${candidates[i]}: ${ethers.formatEther(voteAmounts[i])} 票`);
}
// 查询特定候选人的得票数
const votes = await council.getCandidateVotes(tokenAddress, candidateAddress);
选举结束后领回代币
选举结束后(block.timestamp > endTime):
// 第一个调用者触发结算 + 领回
// 后续调用者直接领回代币
const tx = await council.claimElectionTokens(tokenAddress);
await tx.wait();
查看 Council 成员
// 选举结算后
const members = await council.getCouncilMembers(tokenAddress);
console.log("Council 成员:", members);
// 检查某地址是否为 Council 成员
const isMember = await council.isCouncilMember(tokenAddress, someAddress);
| 事件 | 说明 |
|---|
ElectionStarted(token, endTime, councilSize) | 选举开始 |
ElectionVoted(token, voter, totalLocked, candidates, amounts) | 投出选票 |
ElectionFinalized(token, councilMembers) | 选举结果结算 |
ElectionTokensClaimed(token, voter, amount) | 投票者领回锁定代币 |