투표 시스템
Savitri 거버넌스 투표 시스템은 토큰 가중 온체인 의사결정을 가능하게 합니다.
투표 유형
| 유형 | 의미 |
|---|---|
Yes | 제안 지지 |
No | 제안 반대 |
Abstain | 정족수에 산입되지만 승인에는 포함되지 않음 |
제안 생명 주기
생성 (+ 예치금)
│
검토 기간 (24시간)
│ Pending 상태, 투표 불가
▼
투표 기간 (기본 7일)
│ ActiveVoting 상태
▼
집계
├── 정족수 달성 + 승인 달성 → 승인됨
├── 정족수 달성 + 승인 미달 → 거부됨
└── 정족수 미달 → 거부됨 (참여 부족)
│
▼
실행 (승인된 경우)
정족수 및 승인
| 임계값 | 값 | 설명 |
|---|---|---|
| 정족수 | 10% | 총 투표 토큰의 참여 필요 |
| 승인 | 65% | 찬성표 비율 (기권 제외) |
계산
total_votes = yes_votes + no_votes + abstain_votes
quorum_met = total_votes >= (total_vote_supply * 0.10)
approval = yes_votes / (yes_votes + no_votes) >= 0.65
기권표는 정족수에 산입되지만 승인 계산에는 포함되지 않습니다.
투표 토큰 잠금
사용자가 투표할 때, 투표 토큰은 투표 기간 동안 잠금 처리됩니다. 이는 다음을 방지합니다:
- 이중 투표 (동일 토큰으로 여러 제안에 투표)
- 토큰 전송 후 다른 주소에서 재투표
투표 기간 종료 시 토큰이 잠금 해제됩니다.
예치금 메커니즘
제안 생성 시 예치금이 필요합니다 (스팸 방지):
- 제안이 정족수에 도달하면 예치금 반환 (결과와 무관)
- 제안이 정족수에 미달하면 예치금 삭감
제안 액션
| 액션 | 설명 |
|---|---|
SetParameter | 네트워크 매개변수 수정 |
TransferTreasury | 재무 자금 이체 |
UpgradeContract | 스마트 컨트랙트 업그레이드 |
SetFlPolicy | FL 훈련 매개변수 업데이트 |
ApproveFlModel | 프로덕션용 FL 모델 승인 |
AbortFlRound | FL 훈련 라운드 긴급 중단 |
SlashValidator | 불량 검증자 처벌 |
Custom | 사용자 정의 거버넌스 액션 |
투표 결과
pub struct VotingResult {
pub yes_votes: u64,
pub no_votes: u64,
pub abstain_votes: u64,
pub total_eligible: u64,
pub quorum_reached: bool,
pub approved: bool,
pub participation_rate: f64,
}
투표 토큰 분배
투표 토큰은 노드 참여를 통해 획득됩니다:
| PoU 레벨 | 점수 범위 | 에포크당 투표 토큰 |
|---|---|---|
| Bronze | 300-499 | 10 |
| Silver | 500-699 | 25 |
| Gold | 700-899 | 50 |
| Platinum | 900-1000 | 100 |
SDK를 통해
투표 표현
use savitri_sdk::{ContractClient, Wallet};
let contract = ContractClient::from_url_and_wallet(url, wallet)?;
let gov = contract.governance();
// 제안 #42에 찬성 투표
let tx = gov.vote(&governance_address, 42, true).await?;
// 반대 투표
let tx = gov.vote(&governance_address, 42, false).await?;
제안 상태 확인
let status = gov.get_proposal_status(&governance_address, 42).await?;
println!("Votes: {} for / {} against", status.votes_for, status.votes_against);
println!("Status: {} (executed: {})", status.status, status.executed);
승인된 제안 실행
승인된 제안의 실행은 누구든지 트리거할 수 있습니다:
let tx = gov.execute(&governance_address, 42).await?;
스토리지
| 컬럼 패밀리 | 키 | 값 |
|---|---|---|
CF_GOVERNANCE | proposal_id (u64 LE) | 제안 (bincode) |
CF_VOTE_TOKENS | address (32바이트) | 투표 토큰 잔액 |
타임라인
| 단계 | 기간 | 상태 |
|---|---|---|
| 검토 | 24시간 | Pending |
| 투표 | 7일 (설정 가능) | ActiveVoting |
| 실행 | 집계 후 즉시 | Approved → Executed |