> ## 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.

# Proposals & Voting

> How to vote on community proposals

## Overview

After a council is elected, council members can create proposals. All token holders can vote on proposals by locking their tokens. After the voting period ends, results are finalized and winning options are determined.

## Governance Rounds

Governance operates in rounds with two phases:

```mermaid theme={null}
graph LR
    A["Proposal Phase<br/>Council creates proposals"] --> B["Voting Phase<br/>Token holders vote"]
    B --> C["Finalized<br/>Results determined"]
```

### Reading Governance State

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

const state = await council.getCouncilState(tokenAddress);

console.log("Phase:", state.governancePhase); // 0=Idle, 1=Proposal, 2=Voting
console.log("Proposal phase ends:", new Date(Number(state.proposalPhaseEnd) * 1000));
console.log("Voting phase ends:", new Date(Number(state.votingPhaseEnd) * 1000));
console.log("Current proposal ID:", state.currentProposalId.toString());
console.log("Treasury:", ethers.formatEther(state.treasuryBalance));
```

## Voting on a Proposal

<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 on proposal
// target: address(0) for general proposals
// optionIndex: index of the option you're voting for
// amount: tokens to allocate to this option
const votes = [
  {
    target: ethers.ZeroAddress,
    optionIndex: 0,  // first option
    amount: ethers.parseEther("10000"),
  },
];

const proposalId = 1; // on-chain proposal ID
const tx = await council.voteProposal(tokenAddress, proposalId, votes);
await tx.wait();
```

<Tip>
  You can split your tokens across multiple options in a single vote transaction.
</Tip>

## Reading Proposal Details

```javascript theme={null}
// Get proposal info
const proposal = await council.getProposal(tokenAddress, proposalId);

console.log("Start:", new Date(Number(proposal.startTime) * 1000));
console.log("End:", new Date(Number(proposal.endTime) * 1000));
console.log("Finalized:", proposal.finalized);
console.log("Type:", proposal.proposalType); // 0=General, 1=Tax
console.log("Options:", proposal.optionCodes);
console.log("Winning option:", proposal.winningOption.toString());

// Get vote counts per option
const optionVotes = await council.getProposalOptionVotes(tokenAddress, proposalId);
optionVotes.forEach((votes, i) => {
  console.log(`Option ${i}: ${ethers.formatEther(votes)} votes`);
});

// Get your own votes
const myVotes = await council.getVoterOptionVotes(tokenAddress, proposalId, myAddress);

// Check locked amount (claimable after proposal ends)
const locked = await council.getVoterLockedAmount(tokenAddress, proposalId, myAddress);
```

## Claiming Tokens After Voting

After the voting period ends:

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

## Tax Configuration

Tax proposals set the token's transaction tax. After a tax proposal is finalized and the winning option is applied:

```javascript theme={null}
const taxConfig = await council.getTaxConfig(tokenAddress);

console.log("Rate:", taxConfig.rate.toString()); // in basis points
console.log("Purpose:", taxConfig.purpose); // 0=None, 1=Burn, 2=Transfer, 3=Treasury
console.log("Target:", taxConfig.target);

// Check if an address is tax exempt
const exempt = await council.isTaxExempt(tokenAddress, someAddress);
```

| Purpose         | Value | Description                         |
| --------------- | ----- | ----------------------------------- |
| None            | 0     | No tax                              |
| Burn            | 1     | Tax tokens are burned               |
| Transfer        | 2     | Tax tokens sent to target address   |
| CouncilTreasury | 3     | Tax tokens sent to council treasury |

## Events

| Event                                                                                     | Description        |
| ----------------------------------------------------------------------------------------- | ------------------ |
| `ProposalCreated(token, proposalId, nonce, proposer, proposalType, optionCodes, endTime)` | Proposal created   |
| `ProposalFinalized(token, proposalId, winningOption, winningVotes)`                       | Proposal finalized |
