Разработка квадратичного голосования (quadratic voting)
Quadratic voting решает фундаментальную проблему токен-взвешенного голосования: у кита 1000x токенов → 1000x влияния. QV устанавливает другое правило: сила голоса пропорциональна корню квадратному от потраченного ресурса. 100 голосовательных кредитов дают 10 единиц голосовой силы. 900 кредитов — 30. Для такой же силы, что 9 человек с 1 кредитом, нужно потратить 81 кредит.
Математика: влияние = √credits. Это делает экономически невыгодным доминирование одного участника по сравнению с широкой коалицией.
Теоретическая база
QV был предложен экономистами Эриком Познером и Гленом Вейлом в книге «Radical Markets». Intuition за механизмом: в стандартном голосовании 1 человек = 1 голос, но интенсивность предпочтений не учитывается. Тот, кому очень важен результат, и тот, кому безразлично, имеют одинаковый вес. QV позволяет выражать интенсивность через количество потраченных кредитов — это ближе к реальным экономическим предпочтениям.
Пример: 100 человек немного предпочитают вариант A. 10 человек очень хотят вариант B. В стандартном голосовании побеждает A. В QV, если каждый из 10 потратит 100 кредитов на B (сила = 10 × √100 = 100), они могут переголосовать коалицию из 100, каждый из которых потратил 1 кредит (сила = 100 × √1 = 100). При балансе предпочтений победит более интенсивно желаемый результат.
Системы голосовательных кредитов
Voice Credits модель
Стандартная схема: каждый участник получает фиксированный бюджет voice credits на период голосования. Кредиты не переносятся и не передаются — каждый период fresh allocation.
contract QuadraticVoting {
struct VotingRound {
uint256 startTime;
uint256 endTime;
mapping(uint256 => int256) optionVotes; // optionId => суммарные голоса (sqrt-взвешенные)
}
uint256 public constant CREDITS_PER_ROUND = 100;
// Потраченные кредиты участника в текущем раунде
mapping(address => mapping(uint256 => uint256)) public creditsSpent;
function vote(
uint256 roundId,
uint256 optionId,
uint256 credits, // credits to spend on this option
bool support
) external {
VotingRound storage round = rounds[roundId];
require(block.timestamp >= round.startTime && block.timestamp < round.endTime, "Round inactive");
uint256 totalSpent = creditsSpent[msg.sender][roundId] + credits;
require(totalSpent <= CREDITS_PER_ROUND, "Exceeds budget");
// QV: голосовая сила = sqrt(credits)
uint256 votes = sqrt(credits);
creditsSpent[msg.sender][roundId] = totalSpent;
if (support) {
round.optionVotes[optionId] += int256(votes);
} else {
round.optionVotes[optionId] -= int256(votes);
}
emit VoteCast(msg.sender, roundId, optionId, credits, votes, support);
}
// Integer square root (Babylonian method)
function sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
}
Токен-взвешенные кредиты
Альтернативная схема: кредиты пропорциональны балансу токенов (как в Gitcoin Grants). Держатель 1000 токенов имеет 1000 кредитов. Но голосовая сила всё равно √ от потраченных кредитов. Это даёт богатым участникам больше кредитов, но не линейное влияние.
Сравнение: при кредитах пропорциональных балансу и балансе 10,000 vs 100 (100x разница) — голосовая сила отличается в √100 = 10x, не в 100x. Это значительно лучше чем стандартное token-weighted.
Delegated QV
Участник может делегировать свои кредиты другому участнику. Делегат голосует пакетом кредитов, но всё равно применяется корневая функция к суммарным кредитам на каждый вариант от каждого первоначального владельца.
Важный нюанс: агрегация кредитов от делегатов должна сохранять информацию об источнике. Если просто суммировать кредиты делегатора в пуле делегата — теряется QV свойство.
// Правильная агрегация: каждый delegation entry отдельно
struct Delegation {
address delegator;
uint256 credits;
}
// Голосование делегата: применяет QV к каждому делегированию отдельно
function voteAsDelegate(
uint256 roundId,
uint256 optionId,
Delegation[] calldata delegations
) external {
int256 totalVotes = 0;
for (uint i = 0; i < delegations.length; i++) {
require(
delegatedCredits[delegations[i].delegator][msg.sender][roundId]
>= delegations[i].credits,
"Insufficient delegated credits"
);
totalVotes += int256(sqrt(delegations[i].credits));
}
rounds[roundId].optionVotes[optionId] += totalVotes;
}
Sybil resistance: главная проблема QV
QV полностью ломается без защиты от Sybil-атак. Один участник с 100 кредитами получает силу 10. Сто участников с 1 кредитом каждый получают суммарную силу 100. Разделив идентичность на N адресов, атакующий умножает свою силу в √N раз.
Proof of Humanity
Зарегистрированная уникальная личность в Proof of Humanity или Worldcoin получает 1 аллокацию кредитов. Не поддаётся Sybil — создать тысячу реальных людей нельзя.
Интеграция через on-chain проверку:
interface IProofOfHumanity {
function isRegistered(address _submissionID) external view returns (bool);
}
contract QVWithPoH {
IProofOfHumanity public poh;
function registerForRound(uint256 roundId) external {
require(poh.isRegistered(msg.sender), "Not registered in PoH");
require(!registeredForRound[roundId][msg.sender], "Already registered");
registeredForRound[roundId][msg.sender] = true;
creditsBalance[roundId][msg.sender] = CREDITS_PER_ROUND;
}
}
Проблема PoH: охват ограничен, регистрация занимает время, оспариваема. Для DAO с глобальной аудиторией — барьер входа.
Worldcoin World ID
Более масштабируемое решение. Iris scan → ZK proof уникальности. Верификация on-chain через семафор протокол без раскрытия личных данных.
import "@worldcoin/world-id-contracts/src/interfaces/IWorldID.sol";
import { ByteHasher } from "@worldcoin/world-id-contracts/src/helpers/ByteHasher.sol";
contract QVWithWorldID {
using ByteHasher for bytes;
IWorldID internal worldId;
uint256 internal groupId = 1; // Orb-verified
uint256 internal externalNullifierHash;
function registerWithWorldID(
address signal,
uint256 root,
uint256 nullifierHash,
uint256[8] calldata proof
) external {
// Верифицирует ZK proof уникальности
worldId.verifyProof(
root,
groupId,
abi.encodePacked(signal).hashToField(),
nullifierHash,
externalNullifierHash,
proof
);
require(!nullifierUsed[nullifierHash], "Already registered");
nullifierUsed[nullifierHash] = true;
// выдать кредиты
}
}
Stake-based anti-sybil
Для DeFi-oriented DAO: требовать stake токенов для участия. Создание многих Sybil аккаунтов становится дорогим. Комбинация с QV: stake определяет базовый кредит, но голосовая сила всё равно √ от потраченного.
Quadratic Funding (расширение QV)
Gitcoin использует QF (Quadratic Funding) — производную от QV. Это механизм для общественного финансирования: проекты получают matching funds пропорционально квадрату суммы квадратных корней от индивидуальных взносов.
Matching = (Σ √contribution_i)²
Пример: проект A получил 100 взносов по $1. Matching ∝ (100 × √1)² = 10,000. Проект B получил 1 взнос на $100. Matching ∝ (1 × √100)² = 100. При одинаковой сумме взносов проект с широкой поддержкой получает в 100x больше matching.
Gitcoin Grants реализовал это на Ethereum (Optimism для снижения gas costs). Это наиболее известная production реализация QV/QF в crypto.
Полная архитектура системы
On-chain компоненты
- QuadraticVoting.sol: core контракт с логикой кредитов и голосования
- IdentityRegistry.sol: связь адресов с верифицированными идентичностями (PoH/Worldcoin)
- VotingRoundFactory.sol: создание раундов с параметрами (duration, options, credit allocation)
Off-chain компоненты
Snapshot integration: большинство DAO используют Snapshot для off-chain QV голосований — бесплатно и без ограничений по числу участников. Snapshot поддерживает QV стратегию.
Results calculator: off-chain сервис для сложных QF расчётов, с последующей публикацией результатов on-chain.
Frontend: интерфейс, где участник видит свой бюджет кредитов, слайдеры для распределения по вариантам, live preview голосовой силы каждого решения.
Параметры и настройка
| Параметр | Рекомендация | Обоснование |
|---|---|---|
| Базовые кредиты | 99-100 | Удобный для √ расчётов |
| Длительность раунда | 7-14 дней | Время для осознанного участия |
| Перенос кредитов | Нет | Предотвращает накопление и атаки |
| Минимальный stake | 0.01-0.1% supply | Базовый anti-sybil без высокого барьера |
| Sybil protection | PoH + stake | Многоуровневая защита |
Ограничения и честный взгляд
QV не решает все проблемы governance. Слабые места:
Collusion: группа участников может координировать распределение кредитов для максимизации суммарного влияния. Это сложнее чем в стандартном голосовании, но не невозможно. MACI (Minimum Anti-Collusion Infrastructure) решает это через ZK cryptography.
Rational ignorance: большинство участников не будут тратить время на изучение 20 предложений в раунде. QV снижает стоимость игнорирования, но не устраняет её.
Оптимальная стратегия: математически оптимальная стратегия для участника — не очевидна. Это может снижать participation у нетехнических участников.
QV лучше подходит для ограниченных наборов вариантов (выбор приоритетов, распределение грантов) чем для бинарных да/нет решений по протоколу.
Разработка полной системы QV с PoH/Worldcoin интеграцией: 8-12 недель. Базовый on-chain QV без anti-sybil — 3-4 недели.







