> ## 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 合约 ABI 参考 — 选举、提案、投票

## 合约信息

| 属性     | 值                                             |
| ------ | --------------------------------------------- |
| **地址** | 每个代币独立（在 [kas.fun](https://kas.fun) 代币社区页面查看） |
| **网络** | Kasplex（见[合约地址](/zh/contracts/addresses)）     |

<Info>
  每个毕业代币都有自己的 Council 合约地址。地址不是全局的——请在代币的社区页面查询。
</Info>

## 选举函数

### startElection

发起 Council 选举。需要平台 EIP-712 签名。

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

***

### voteElection

为候选人投票。代币在选举结束前锁定。

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

**ElectionVoteEntry：**

| 字段          | 类型      | 说明            |
| ----------- | ------- | ------------- |
| `candidate` | address | 候选人地址         |
| `amount`    | uint256 | 分配的代币数量 (wei) |

***

### claimElectionTokens

选举结束后领回锁定代币。第一个调用者触发结算。

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

***

## 选举读函数

### getElectionState

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

**返回：**

| 字段                | 类型      | 说明            |
| ----------------- | ------- | ------------- |
| `active`          | bool    | 选举是否进行中       |
| `endTime`         | uint256 | 结束时间戳（unix 秒） |
| `lastElectionEnd` | uint256 | 上次选举结束时间      |
| `finalized`       | bool    | 结果是否已结算       |
| `councilSize`     | uint256 | 席位数           |
| `epoch`           | uint256 | 选举届期计数器       |

***

### 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)
```

返回按得票数降序排列的候选人。空位用 `address(0)` 填充。

***

### getCandidateVotes

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

***

## 治理函数

### startGovernance

开启治理周期。仅合约 owner/manager 可调用。

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

***

### createProposal

创建提案。需要平台 EIP-712 签名。

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

| 参数             | 类型         | 说明             |
| -------------- | ---------- | -------------- |
| `token`        | address    | 代币地址           |
| `nonce`        | bytes32    | 唯一 nonce       |
| `signature`    | bytes      | 平台签名           |
| `optionCodes`  | uint256\[] | 选项标识符          |
| `endTime`      | uint256    | 投票结束时间戳        |
| `proposalType` | uint8      | 0 = 通用, 1 = 税费 |

***

### voteProposal

通过锁定代币对提案投票。

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

**VoteEntry：**

| 字段            | 类型      | 说明                 |
| ------------- | ------- | ------------------ |
| `target`      | address | 通用提案用 `address(0)` |
| `optionIndex` | uint8   | 要投票的选项索引           |
| `amount`      | uint256 | 分配的代币数量 (wei)      |

***

### finalizeProposal

投票结束后结算提案。

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

***

### claimProposalTokens

提案结束后领回锁定代币。第一个调用者触发结算。

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

***

## 治理读函数

### getCouncilState

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

**返回：**

| 字段                     | 类型      | 说明                     |
| ---------------------- | ------- | ---------------------- |
| `currentProposalId`    | uint256 | 最新提案 ID                |
| `treasuryBalance`      | uint256 | 国库余额 (wei)             |
| `governancePhase`      | uint8   | 0 = 空闲, 1 = 提案, 2 = 投票 |
| `proposalPhaseEnd`     | uint256 | 提案阶段截止时间戳              |
| `votingPhaseEnd`       | uint256 | 投票阶段截止时间戳              |
| `roundFirstProposalId` | uint256 | 当前轮次第一个提案 ID           |

***

### getProposal

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

**返回：**

| 字段              | 类型         | 说明             |
| --------------- | ---------- | -------------- |
| `startTime`     | uint256    | 开始时间戳          |
| `endTime`       | uint256    | 结束时间戳          |
| `finalized`     | bool       | 是否已结算          |
| `executed`      | bool       | 是否已执行          |
| `proposalType`  | uint8      | 0 = 通用, 1 = 税费 |
| `nonce`         | bytes32    | 唯一 nonce       |
| `optionCount`   | uint256    | 选项数量           |
| `winningOption` | uint256    | 胜出选项索引         |
| `optionCodes`   | uint256\[] | 选项代码标识符        |

***

### getProposalOptionVotes

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

返回每个选项的得票数（数组索引 = 选项索引）。

***

### getVoterOptionVotes

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

返回投票者分配给每个选项的代币数量。

***

### getVoterLockedAmount

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

返回投票者在提案中锁定的代币总量。提案结束后可领回。

***

## 税费函数

### setTaxConfig

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

仅 owner/manager 可调用。Purpose: 0=无, 1=销毁, 2=转账, 3=国库。

***

### getTaxConfig

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

**返回：**

| 字段        | 类型      | 说明                    |
| --------- | ------- | --------------------- |
| `rate`    | uint256 | 税率（基点）                |
| `purpose` | uint8   | 0=无, 1=销毁, 2=转账, 3=国库 |
| `target`  | address | 税收接收地址                |

***

### isTaxExempt

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

***

## 事件

### 选举事件

```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)
```

### 提案事件

```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)
```

## 完整 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>
