> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kas.fun/llms.txt
> Use this file to discover all available pages before exploring further.

# Election

> How council elections work on-chain

## Overview

Council elections allow token holders to vote for candidates. The top candidates (by vote amount) become council members. Voting requires **locking tokens** in the Council contract.

## Election Flow

<Steps>
  <Step title="Election Starts">
    An election is initiated (requires EIP-712 signature from the platform). The election has a fixed duration.
  </Step>

  <Step title="Voting Period">
    Token holders approve their tokens to the Council contract, then call `voteElection()` to vote for candidates. Tokens are locked until the election ends.
  </Step>

  <Step title="Election Ends">
    After `endTime`, anyone can call `claimElectionTokens()`. The first caller triggers finalization — top candidates become council members.
  </Step>

  <Step title="Claim Tokens">
    All voters call `claimElectionTokens()` to retrieve their locked tokens.
  </Step>
</Steps>

## Reading Election State

```javascript theme={null}
const council = new ethers.Contract(councilAddress, CouncilV1ABI, provider);

const state = await council.getElectionState(tokenAddress);

console.log("Active:", state.active);
console.log("End time:", new Date(Number(state.endTime) * 1000));
console.log("Finalized:", state.finalized);
console.log("Council size:", state.councilSize.toString());
console.log("Epoch:", state.epoch.toString());
```

### Election State Fields

| Field             | Type    | Description                                             |
| ----------------- | ------- | ------------------------------------------------------- |
| `active`          | bool    | Whether an election is currently running                |
| `endTime`         | uint256 | Election end timestamp (unix seconds)                   |
| `lastElectionEnd` | uint256 | When the last election ended                            |
| `finalized`       | bool    | Whether the current/last election results are finalized |
| `councilSize`     | uint256 | Number of council seats                                 |
| `epoch`           | uint256 | Election epoch counter                                  |

## Voting in an Election

<Warning>
  Before voting, you must **approve** the Council contract to transfer your tokens.
</Warning>

```javascript theme={null}
const tokenContract = new ethers.Contract(tokenAddress, [
  "function approve(address spender, uint256 amount) returns (bool)",
], signer);

const council = new ethers.Contract(councilAddress, CouncilV1ABI, signer);

// 1. Approve tokens
const amount = ethers.parseEther("10000");
await (await tokenContract.approve(councilAddress, amount)).wait();

// 2. Vote for candidates
// You can split your tokens across multiple candidates
const votes = [
  { candidate: "0xCandidate1...", amount: ethers.parseEther("6000") },
  { candidate: "0xCandidate2...", amount: ethers.parseEther("4000") },
];

const tx = await council.voteElection(tokenAddress, votes);
await tx.wait();
```

## Checking Candidates

```javascript theme={null}
// Get top 20 candidates sorted by votes (descending)
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])} votes`);
}

// Check a specific candidate's votes
const votes = await council.getCandidateVotes(tokenAddress, candidateAddress);
```

## Claiming Tokens After Election

After the election ends (`block.timestamp > endTime`):

```javascript theme={null}
// First caller triggers finalization + claims
// Subsequent callers just claim their tokens
const tx = await council.claimElectionTokens(tokenAddress);
await tx.wait();
```

## Reading Council Members

```javascript theme={null}
// After election is finalized
const members = await council.getCouncilMembers(tokenAddress);
console.log("Council members:", members);

// Check if an address is a council member
const isMember = await council.isCouncilMember(tokenAddress, someAddress);
```

## Events

| Event                                                           | Description                |
| --------------------------------------------------------------- | -------------------------- |
| `ElectionStarted(token, endTime, councilSize)`                  | Election begins            |
| `ElectionVoted(token, voter, totalLocked, candidates, amounts)` | A vote is cast             |
| `ElectionFinalized(token, councilMembers)`                      | Election results finalized |
| `ElectionTokensClaimed(token, voter, amount)`                   | Voter claims locked tokens |
