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

# Council V1

> Council V1 contract ABI reference — elections, proposals, voting

## Contract Info

| Property    | Value                                                                  |
| ----------- | ---------------------------------------------------------------------- |
| **Address** | Per-token (check token's community page on [kas.fun](https://kas.fun)) |
| **Network** | Kasplex (see [Addresses](/contracts/addresses) for chain details)      |

<Info>
  Each graduated token has its own Council contract address. The address is not global — query it from the token's community page.
</Info>

## Election Functions

### startElection

Start a council election. Requires platform EIP-712 signature.

```solidity theme={null}
function startElection(address token, bytes signature) external
```

***

### voteElection

Vote for candidates. Tokens are locked until the election ends.

```solidity theme={null}
function voteElection(address token, ElectionVoteEntry[] votes) external
```

**ElectionVoteEntry:**

| Field       | Type    | Description                    |
| ----------- | ------- | ------------------------------ |
| `candidate` | address | Candidate address              |
| `amount`    | uint256 | Token amount to allocate (wei) |

***

### claimElectionTokens

Claim locked tokens after election ends. First caller triggers finalization.

```solidity theme={null}
function claimElectionTokens(address token) external
```

***

## Election Read Functions

### getElectionState

```solidity theme={null}
function getElectionState(address token) external view returns (ElectionState)
```

**Returns:**

| Field             | Type    | Description                  |
| ----------------- | ------- | ---------------------------- |
| `active`          | bool    | Election is running          |
| `endTime`         | uint256 | End timestamp (unix seconds) |
| `lastElectionEnd` | uint256 | Previous election end time   |
| `finalized`       | bool    | Results have been finalized  |
| `councilSize`     | uint256 | Number of seats              |
| `epoch`           | uint256 | Election epoch counter       |

***

### getCouncilMembers

```solidity theme={null}
function getCouncilMembers(address token) external view returns (address[])
```

***

### isCouncilMember

```solidity theme={null}
function isCouncilMember(address token, address account) external view returns (bool)
```

***

### getTop20Candidates

```solidity theme={null}
function getTop20Candidates(address token) external view returns (address[] candidates, uint256[] voteAmounts)
```

Returns candidates sorted by votes descending. Empty entries padded with `address(0)`.

***

### getCandidateVotes

```solidity theme={null}
function getCandidateVotes(address token, address candidate) external view returns (uint256)
```

***

## Governance Functions

### startGovernance

Start a governance round. Only callable by contract owner/manager.

```solidity theme={null}
function startGovernance(address token, uint256 proposalPhaseEnd, uint256 votingPhaseEnd) external
```

***

### createProposal

Create a proposal. Requires platform EIP-712 signature.

```solidity theme={null}
function createProposal(
    address token,
    bytes32 nonce,
    bytes signature,
    uint256[] optionCodes,
    uint256 endTime,
    uint8 proposalType
) external
```

| Parameter      | Type       | Description          |
| -------------- | ---------- | -------------------- |
| `token`        | address    | Token address        |
| `nonce`        | bytes32    | Unique nonce         |
| `signature`    | bytes      | Platform signature   |
| `optionCodes`  | uint256\[] | Option identifiers   |
| `endTime`      | uint256    | Voting end timestamp |
| `proposalType` | uint8      | 0 = General, 1 = Tax |

***

### voteProposal

Vote on a proposal by locking tokens.

```solidity theme={null}
function voteProposal(address token, uint256 proposalId, VoteEntry[] votes) external
```

**VoteEntry:**

| Field         | Type    | Description                        |
| ------------- | ------- | ---------------------------------- |
| `target`      | address | `address(0)` for general proposals |
| `optionIndex` | uint8   | Option index to vote for           |
| `amount`      | uint256 | Token amount to allocate (wei)     |

***

### finalizeProposal

Finalize a proposal after voting ends.

```solidity theme={null}
function finalizeProposal(address token, uint256 proposalId) external
```

***

### claimProposalTokens

Claim locked tokens after proposal ends. First caller triggers finalization.

```solidity theme={null}
function claimProposalTokens(address token, uint256 proposalId) external
```

***

## Governance Read Functions

### getCouncilState

```solidity theme={null}
function getCouncilState(address token) external view returns (CouncilState)
```

**Returns:**

| Field                  | Type    | Description                        |
| ---------------------- | ------- | ---------------------------------- |
| `currentProposalId`    | uint256 | Latest proposal ID                 |
| `treasuryBalance`      | uint256 | Treasury balance (wei)             |
| `governancePhase`      | uint8   | 0 = Idle, 1 = Proposal, 2 = Voting |
| `proposalPhaseEnd`     | uint256 | Proposal phase end timestamp       |
| `votingPhaseEnd`       | uint256 | Voting phase end timestamp         |
| `roundFirstProposalId` | uint256 | First proposal ID in current round |

***

### getProposal

```solidity theme={null}
function getProposal(address token, uint256 proposalId) external view returns (Proposal)
```

**Returns:**

| Field           | Type       | Description             |
| --------------- | ---------- | ----------------------- |
| `startTime`     | uint256    | Start timestamp         |
| `endTime`       | uint256    | End timestamp           |
| `finalized`     | bool       | Whether finalized       |
| `executed`      | bool       | Whether executed        |
| `proposalType`  | uint8      | 0 = General, 1 = Tax    |
| `nonce`         | bytes32    | Unique nonce            |
| `optionCount`   | uint256    | Number of options       |
| `winningOption` | uint256    | Winning option index    |
| `optionCodes`   | uint256\[] | Option code identifiers |

***

### getProposalOptionVotes

```solidity theme={null}
function getProposalOptionVotes(address token, uint256 proposalId) external view returns (uint256[])
```

Returns vote counts per option (array index = option index).

***

### getVoterOptionVotes

```solidity theme={null}
function getVoterOptionVotes(address token, uint256 proposalId, address voter) external view returns (uint256[])
```

Returns a voter's allocated tokens per option.

***

### getVoterLockedAmount

```solidity theme={null}
function getVoterLockedAmount(address token, uint256 proposalId, address voter) external view returns (uint256)
```

Returns total tokens locked by a voter in a proposal. Claimable after proposal ends.

***

## Tax Functions

### setTaxConfig

```solidity theme={null}
function setTaxConfig(address token, uint256 rate, uint8 purpose, address target) external
```

Only callable by owner/manager. Purpose: 0=None, 1=Burn, 2=Transfer, 3=CouncilTreasury.

***

### getTaxConfig

```solidity theme={null}
function getTaxConfig(address token) external view returns (TaxConfig)
```

**Returns:**

| Field     | Type    | Description                            |
| --------- | ------- | -------------------------------------- |
| `rate`    | uint256 | Tax rate (basis points)                |
| `purpose` | uint8   | 0=None, 1=Burn, 2=Transfer, 3=Treasury |
| `target`  | address | Tax recipient address                  |

***

### isTaxExempt

```solidity theme={null}
function isTaxExempt(address token, address account) external view returns (bool)
```

***

## Events

### Election Events

```solidity theme={null}
event ElectionStarted(address indexed token, uint256 endTime, uint256 councilSize)
event ElectionVoted(address indexed token, address indexed voter, uint256 totalLocked, address[] candidates, uint256[] amounts)
event ElectionFinalized(address indexed token, address[] councilMembers)
event ElectionTokensClaimed(address indexed token, address indexed voter, uint256 amount)
```

### Proposal Events

```solidity theme={null}
event ProposalCreated(address indexed token, uint256 indexed proposalId, bytes32 indexed nonce, address proposer, uint8 proposalType, uint256[] optionCodes, uint256 endTime)
event ProposalFinalized(address indexed token, uint256 indexed proposalId, uint256 winningOption, uint256 winningVotes)
```

## Full ABI (JSON)

<Accordion title="Council V1 ABI JSON">
  ```json theme={null}
  [
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "councilSize", "type": "uint256"}, {"internalType": "uint256", "name": "minInterval", "type": "uint256"}, {"internalType": "uint256", "name": "duration", "type": "uint256"}], "name": "initElectionConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "bytes", "name": "signature", "type": "bytes"}], "name": "startElection", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"components": [{"internalType": "address", "name": "candidate", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "internalType": "struct ICouncil.ElectionVoteEntry[]", "name": "votes", "type": "tuple[]"}], "name": "voteElection", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "claimElectionTokens", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalPhaseEnd", "type": "uint256"}, {"internalType": "uint256", "name": "votingPhaseEnd", "type": "uint256"}], "name": "startGovernance", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "bytes32", "name": "nonce", "type": "bytes32"}, {"internalType": "bytes", "name": "signature", "type": "bytes"}, {"internalType": "uint256[]", "name": "optionCodes", "type": "uint256[]"}, {"internalType": "uint256", "name": "endTime", "type": "uint256"}, {"internalType": "uint8", "name": "proposalType", "type": "uint8"}], "name": "createProposal", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}, {"components": [{"internalType": "address", "name": "target", "type": "address"}, {"internalType": "uint8", "name": "optionIndex", "type": "uint8"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "internalType": "struct ICouncil.VoteEntry[]", "name": "votes", "type": "tuple[]"}], "name": "voteProposal", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}], "name": "finalizeProposal", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}], "name": "claimProposalTokens", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "rate", "type": "uint256"}, {"internalType": "uint8", "name": "purpose", "type": "uint8"}, {"internalType": "address", "name": "target", "type": "address"}], "name": "setTaxConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "getElectionState", "outputs": [{"components": [{"internalType": "bool", "name": "active", "type": "bool"}, {"internalType": "uint256", "name": "endTime", "type": "uint256"}, {"internalType": "uint256", "name": "lastElectionEnd", "type": "uint256"}, {"internalType": "bool", "name": "finalized", "type": "bool"}, {"internalType": "uint256", "name": "councilSize", "type": "uint256"}, {"internalType": "uint256", "name": "epoch", "type": "uint256"}], "internalType": "struct ICouncil.ElectionState", "name": "", "type": "tuple"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "getCouncilMembers", "outputs": [{"internalType": "address[]", "name": "", "type": "address[]"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "address", "name": "account", "type": "address"}], "name": "isCouncilMember", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "getTop20Candidates", "outputs": [{"internalType": "address[]", "name": "candidates", "type": "address[]"}, {"internalType": "uint256[]", "name": "voteAmounts", "type": "uint256[]"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "address", "name": "candidate", "type": "address"}], "name": "getCandidateVotes", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "getCouncilState", "outputs": [{"components": [{"internalType": "uint256", "name": "currentProposalId", "type": "uint256"}, {"internalType": "uint256", "name": "treasuryBalance", "type": "uint256"}, {"internalType": "uint8", "name": "governancePhase", "type": "uint8"}, {"internalType": "uint256", "name": "proposalPhaseEnd", "type": "uint256"}, {"internalType": "uint256", "name": "votingPhaseEnd", "type": "uint256"}, {"internalType": "uint256", "name": "roundFirstProposalId", "type": "uint256"}], "internalType": "struct ICouncil.CouncilState", "name": "", "type": "tuple"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}], "name": "getProposal", "outputs": [{"components": [{"internalType": "uint256", "name": "startTime", "type": "uint256"}, {"internalType": "uint256", "name": "endTime", "type": "uint256"}, {"internalType": "bool", "name": "finalized", "type": "bool"}, {"internalType": "bool", "name": "executed", "type": "bool"}, {"internalType": "uint8", "name": "proposalType", "type": "uint8"}, {"internalType": "bytes32", "name": "nonce", "type": "bytes32"}, {"internalType": "uint256", "name": "optionCount", "type": "uint256"}, {"internalType": "uint256", "name": "winningOption", "type": "uint256"}, {"internalType": "uint256[]", "name": "optionCodes", "type": "uint256[]"}], "internalType": "struct ICouncil.Proposal", "name": "", "type": "tuple"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}], "name": "getProposalOptionVotes", "outputs": [{"internalType": "uint256[]", "name": "", "type": "uint256[]"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}, {"internalType": "address", "name": "voter", "type": "address"}], "name": "getVoterOptionVotes", "outputs": [{"internalType": "uint256[]", "name": "", "type": "uint256[]"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256", "name": "proposalId", "type": "uint256"}, {"internalType": "address", "name": "voter", "type": "address"}], "name": "getVoterLockedAmount", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}], "name": "getTaxConfig", "outputs": [{"components": [{"internalType": "uint256", "name": "rate", "type": "uint256"}, {"internalType": "uint8", "name": "purpose", "type": "uint8"}, {"internalType": "address", "name": "target", "type": "address"}], "internalType": "struct ICouncil.TaxConfig", "name": "", "type": "tuple"}], "stateMutability": "view", "type": "function"},
    {"inputs": [{"internalType": "address", "name": "token", "type": "address"}, {"internalType": "address", "name": "account", "type": "address"}], "name": "isTaxExempt", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": false, "internalType": "uint256", "name": "endTime", "type": "uint256"}, {"indexed": false, "internalType": "uint256", "name": "councilSize", "type": "uint256"}], "name": "ElectionStarted", "type": "event"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": false, "internalType": "address[]", "name": "councilMembers", "type": "address[]"}], "name": "ElectionFinalized", "type": "event"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": true, "internalType": "address", "name": "voter", "type": "address"}, {"indexed": false, "internalType": "uint256", "name": "totalLocked", "type": "uint256"}, {"indexed": false, "internalType": "address[]", "name": "candidates", "type": "address[]"}, {"indexed": false, "internalType": "uint256[]", "name": "amounts", "type": "uint256[]"}], "name": "ElectionVoted", "type": "event"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": true, "internalType": "address", "name": "voter", "type": "address"}, {"indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "ElectionTokensClaimed", "type": "event"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": true, "internalType": "uint256", "name": "proposalId", "type": "uint256"}, {"indexed": true, "internalType": "bytes32", "name": "nonce", "type": "bytes32"}, {"indexed": false, "internalType": "address", "name": "proposer", "type": "address"}, {"indexed": false, "internalType": "uint8", "name": "proposalType", "type": "uint8"}, {"indexed": false, "internalType": "uint256[]", "name": "optionCodes", "type": "uint256[]"}, {"indexed": false, "internalType": "uint256", "name": "endTime", "type": "uint256"}], "name": "ProposalCreated", "type": "event"},
    {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "token", "type": "address"}, {"indexed": true, "internalType": "uint256", "name": "proposalId", "type": "uint256"}, {"indexed": false, "internalType": "uint256", "name": "winningOption", "type": "uint256"}, {"indexed": false, "internalType": "uint256", "name": "winningVotes", "type": "uint256"}], "name": "ProposalFinalized", "type": "event"}
  ]
  ```
</Accordion>
