Gonka GitHub Mirror · Discussion #1243

Руководство и управление финансированием проекта

Отдельная страница дискуссии с русским переводом и параллельным режимом RU / Original с точным сопоставлением предложений.

Как пользоваться: включите RU / Original и кликните по предложению — соответствующее предложение в другой колонке доскроллится и подсветится.
Discussion #1243

Руководство и управление финансированием проекта

Оригинал: Project funding governance and management

a-kuprin avatar
a-kuprinMaintainerАвтор
2026-05-25

Управление финансированием проекта

Резюме

В настоящее время существует потребность в организации, выделяющей средства из общественного пула, и в адекватных инструментах финансирования проектов.

Мы предлагаем смарт-контракт для управления финансированием проекта. Грантополучатель сначала готовит проект с указанием этапов, каждый из которых привязан к выплате в долларах США/GNK (оба можно использовать одновременно). Сообщество голосует за весь проект; средства переводятся в смарт-контракт; и отраслевой комитет, назначенный принимающей стороной, голосует по каждому достигнутому (или невыполненному) этапу. Отраслевые комитеты являются общими для всех грантов, но сообщество может назначать комитеты для конкретных этапов.

Фон

В дискуссиях столкнулись две точки зрения: одна о том, что надо раздавать «вертолетные деньги», а другая о том, что средства могут закончиться, и тогда хозяева потеряют все, включая смерть проекта. В результате большинство предложений отклоняются, а существующий бюджет не инвестируется. Тем не менее опасения принимающей стороны оправданы.

Есть даже мнение, что команде Core не хватает разработчиков и ее следует нанимать больше. Тем не менее, у сообщества есть бюджет, и каждый хозяин имеет не меньшее право голоса в управлении, но сообщество еще не полностью осознало это. У Gonka есть идеология, и она касается децентрализации — основная команда не должна быть центром, от которого все зависит. Перекладывать ответственность за разработку проекта на основную команду — это несколько незрелое поведение. Создание дорожной карты и движение к созданию Фонда — это признаки зрелого сообщества, которое может управлять своим собственным развитием. Майнеры — это серьезные люди с капиталом и опытом ведения бизнеса, которые владеют акционерным капиталом проекта (через GNK) и на практике формируют совет директоров, который не менее, а, возможно, и более ответственен, чем основная команда. Ведь майнеры вложили деньги и оборудование.

Проблема

При нынешней модели финансирования предложений отказ от всего является очень рациональной тактикой для хозяев. Если деньги выплачиваются вперед, есть огромный риск, что ничего не будет сделано, или сделано некачественно, или не то, что нужно. Хозяева несут этот риск. Если выплата осуществляется в GNK, токены выйдут на рынок и окажут давление на книгу заказов, снизив прибыльность хоста, которая уже находится на грани или превышает ее.

Если проект финансируется на основе постоплаты, грантополучатель рискует ничего не получить, потратив при этом ресурсы и деньги.

Разделение на этапы требует ручной организации и внимания организаторов к проекту — по сути, микроменеджмента со стороны совета директоров.

Решение

Грантополучатель сначала готовит проект с указанием этапов, каждый из которых привязан к выплате. USDT направляется на операционные расходы; GNK (в качестве капитала проекта) вознаграждает за вклад в развитие Gonka и может быть разблокирован через 1 или 2 года (сроки настраиваемы). Возможен не только потоковый вестинг, при котором GNK разблокируется ежедневно и может выйти на рынок: любой график разблокировки.

Хозяева, как совет директоров, голосуют за сам проект и назначают комитет, ответственный за его принятие. Выплата может осуществляться единовременно, но каждый этап должен быть проголосован комитетом, чтобы подтвердить, выполнил ли получатель гранта или не выполнил свои обязательства.

Например, проект может выделить 10 тысяч долларов США сразу, еще 10 тысяч при прохождении контрольной точки и 50 тысяч с двухлетней гарантией после завершения.

Дизайн

Реализовано как доска грантов контрактов CosmWasm в цепочке выводов/contracts/ (по аналогии с коммьюнити-продажей и пулом ликвидности), а также дополнительный вспомогательный прокси-сервер по передаче контрактов для блокировок GNK высотой блока. В экземпляре администратором контракта является модуль gov, поэтому обновления и параметры осуществляются только посредством голосования хоста.

Архитектура и интеграция

  • Источники финансирования: GNK — из x/distribution (пул сообщества) через MsgCommunityPoolSpend; USDT — из контракта на коммьюнити-продажу черезdraw_ibc. Грант-борд принимает оба актива по своему адресу.
  • Управление: все привилегированные действия (финансирование, остановка, изменения в комитете, настройка) происходят только из gov_authority, т.е. они требуют голосования хоста через x/gov .
  • Бухгалтерский учет: в контракте содержится tracked_balance[denom] и для каждого гранта выделено_* / потрачено_* . Инвариант: банковский баланс контракта по номиналу ≥ сумма зарезервированных средств для активных и недостаточно финансируемых грантов плюс ожидающие возмещения. Это не позволяет одному гранту расходовать средства другого.
  • Антипожертвование: любые средства, отправленные на адрес контракта вне формального потока, остаются за пределами tracked_balance и не относятся к грантам.

Жизненный цикл гранта

В гранте указано: Черновик → Недостаточно средств/Активен → Остановлен/Остановленвозвращен/Завершен.

Состояния Milestone: Ожидание, ExtensionVotePending, InReview, RetryVotePending, StopVotePending, Выпущено, Отклонено, Пропущено.

Последовательность действий: грантополучатель создает проект → принимает средства через правительство → автоматический этап (если таковой имеется) выплачивается немедленно → для других этапов грантополучатель представляет доказательства → голосование в комитете → выплата.

1. Проект гранта (грантополучатель)

  • CreateDraft — любой может создать черновик, вложив плату за установку в GNK. Плата отправляется в пул сообщества через MsgFundCommunityPool (антиспам, невозвратный).
  • За каждую оплату комиссии вы получаете пул из 10 кредитов для UpdateDraft. Когда кредиты исчерпаны, следующее обновление снова добавляет плату (10 кредитов минус 1 за текущий вызов = осталось 9).
  • Минимальная плата — min_setup_fee_ngonka (жесткий пол 10 GNK). Пока setup_fee < min, контракт считается неактивным.
  • Грантополучатель публикует текст проекта на GitHub (URL-адрес, закрепленный за фиксацией) и помещает Offer_url + Offer_hash (sha256 уценки) в черновик. Это связывает черновик внутри цепочки с описанием вне цепочки.
  • Описание каждой закрытой вехи находится в обсуждении GitHub (description_discussion_url) — для версии 1 это позволяет избежать раздувания состояния. v2 добавит Arweave для неизменяемого хранилища.
  • CloseDraft — закрыть драфт без возврата комиссии. Организаторы могут закрыть черновик через StopGrant.

Проект проверки:

  • Сумма вех равна Request_ngonka/required_usdt (рассчитывается по контракту).
  • Разрешается одна необязательная автоматическая веха с индексом == 0 в начале списка; закрытые этапы выполняются последовательно 1, 2, 3,… .
  • usdt_denom — точный номинал ваучера IBC, неизменяемый на протяжении всего срока действия гранта.
  • Комитет может быть отключен во время проекта — правительство назначает его позже через SetGrantCommittee/SetMilestoneCommittee.

2. Финансирование (Этап 1 — голосование принимающей стороны)

Хозяева голосуют за одно предложение правительства с тремя сообщениями в строгом порядке:

  • MsgCommunityPoolSpend — GNK из пула сообщества на адрес доски грантов.
  • MsgExecuteContract для продажи сообществу с помощьюdraw_ibc —USDT на адрес грантового совета.
  • MsgExecuteContract для предоставления доски с MarkFunded {grant_id, ngonka, usdt, config_hash} — должен быть последним.

Поведение MarkFunded:

  • Требуется info.sender == gov_authority иgrant.status == Draft .
  • Сверяет payload.config_hash на соответствие текущему config.config_hash. Если хосты передали UpdateConfig в том же окне, MarkFunded возвращается, и вся транзакция финансирования откатывается. Это гарантирует, что хосты проголосуют именно за тот шаблон, который будет выполняться.
  • Вычисляет delta_ngonka/delta_usdt как увеличение баланса контракта относительно tracked_balance (защита от приписания случайных переводов).
  • Если delta == запрошено → предоставить Active, устанавливаетсяfunded_at. Если дельта > запрошена → излишек возвращается в том же транзакцию (GNK → пул сообщества, USDT → продажа сообщества). Если дельта < запрошена → предоставить недостаточное финансирование, исправлено через правительство.

Шаблон предложения о финансировании возвращается запросом FundingProposalTemplate {grant_id} — всегда пересчитывается из текущей конфигурации и возвращает config_hash для встраивания в MarkFunded. Инструмент CLI Grantctl для предложения о финансировании записывает готовый JSON.

3. Авто-веха (индекс 0) – мгновенная выплата.

  • Дополнительная веха с индексом == 0 (не более одной, всегда первой) выплачивается внутри MarkFunded немедленно, без участия комитета и каких-либо доказательств.
  • Используется для: Грант по доверенности — одна авто-веха за 100% суммы; отражает сегодняшний поток MsgCommunityPoolSpend, но с учетом доски грантов и унифицированным потоком событий. авансовый транш, например индекс 0 = 20% ГНК по фонду, индекс 1..N = 80% через этапы.
  • Прокси-грант — одна авто-веха за 100% суммы; отражает сегодняшний поток MsgCommunityPoolSpend, но с учетом доски грантов и унифицированным потоком событий.
  • авансовый транш, например индекс 0 = 20% ГНК по фонду, индекс 1..N = 80% через этапы.
  • Автоматическая веха выплачивается только тогда, когда грант становится активным. Для недостаточного финансирования он остается в состоянии ожидания до тех пор, пока не будет полностью профинансирован.

4. Приемка этапа (Этап 2 — комитет)

Для каждой закрытой вехи (индекс ≥ 1):

  • Грантополучатель вызывает SubmitMilestoneEvidence { доказательство_uri, доказательство_хэш } . Milestone → InReview, таймер review_deadline = now + review_ period_секунды.
  • В контракте сохраняется снимок комитета (VOTE_SNAPSHOTS) — список участников и пороговое значение при открытии голосования.
  • Члены комитета называют VoteOnMilestone {да}.
  • Любой может вызвать ExecuteMilestoneRelease, когда: достигнуто пороговое значение yes_required = ⌈threshold_num × n / Threshold_den⌉ или пройдена review_deadline и результат не определен (автоматический выпуск).

порог yes_required = ⌈threshold_num × n/threshold_den⌉ достигнут, или

  • review_deadline прошел, результат не определен (автоматический выпуск).
  • Выплата: USDT — всегда моментально; GNK — немедленно, если Vesting_blocks == 0, иначе через вестинг-прокси с разблокировкой на current_height + Vesting_blocks. Заблокированные GNK не подлежат возврату по StopGrant.

Каскад отклонений (когда комитет голосует против). Следующий статус зависит от времени относительно доказательства_due_at:

  • Слишком много времени до срока → Отклонено, грантополучатель может подать заявку повторно.
  • Плотное окно до истечения срока → RetryVotePending (комитет голосует, разрешить ли еще одну попытку).
  • Уже просрочено → StopVotePending (комитет голосует за прекращение предоставления гранта).

Снимок комитета (шаг 7e). Голосование принимается только в том случае, если избиратель принадлежит snapshot.members ∩ current_committee.members . Пороги (yes_required,blocking_no) используют размер моментального снимка, а не текущего комитета. Это закрывает атаки на стирание голосов, перевес голосов и подтасовку голосов через UpsertCommittee в середине голосования.

Защита самостоятельных сделок. Если избиратель —grant.grantee, голосование автоматически отбрасывается с помощью события Committee_vote_dropped_self_deal.

Пустой комитет – это особенность. Если ни один комитет не примет решения по вехе — автоматически выпустите в review_deadline. Хосты могут намеренно полагаться на таймер.

Этапный заказ. Строго последовательно: веха k не может быть отправлена до тех пор, пока все вехи < k не станут завершающими ( Released / Skiped ). Параллельное рассмотрение не поддерживается в версии 1.

5. Таймеры и параметры (все в Config, только для правительства)

Все параметры являются общими для всего контракта; грантополучатель их не устанавливает. Они включены в config_hash, который привязывает предложение о финансировании к активной конфигурации.

Поток доставки:

  • RequestMilestoneExtension { предложенный_evidence_due_at } — получатель гранта может попросить продлить срок; комитет голосует через VoteOnMilestoneExtension. Утвердить → новое доказательство_due_at в пределах max_deadline_extension. Отклонено или не решено → предоставление грантов прекращается, GNK возвращается в пул сообщества.
  • ProcessDeliveryTimeouts — запуск (только для получателя гранта), запускает StopGrant, если срок истек + отсрочка передана без каких-либо доказательств и без активного голосования за продление. Никакого автоматического выпуска без доказательств — только остановка с возвратом средств.
  • ProcessMilestoneTimeouts — включение автоматического выпуска этапов в InReview с неопределенным результатом после review_deadline .

6. Дополнительная передача прав (vesting-proxy)

  • Минимальный контракт с замками высотой блока. Каждый замок хранит получателя, номинал, сумму, unlock_height,grant_id,milestone_index.
  • Жилет — может звонить только грант-совет. Заявить — любой, кто после unlock_height. AdminCancel — только для правительства.
  • Используется для GNK с Vesting_blocks > 0. USDT никогда не передается.
  • Почему бы не x/streamvesting: он принимает отправителей только из списка разрешений (gov/inference). Контракты не могут вызвать его без апгрейда цепочки. v2 – добавить доску грантов в AllowedExternalVestingSenders.

7. Управление комитетом и остановка (только для государственных органов)

  • UpsertCommittee — создать/заменить комитет (члены, порог). Увеличено членство_ревизия . Не трогает снимки (смещаются ручки пересечения).
  • SetGrantCommittee / SetMilestoneCommittee — переназначить комитет. Если это затронет какой-то этап голосования, снимки и голоса будут удалены.
  • StopGrant {refund_ngonka_to,refund_usdt_to} — остановить грант в любом из вариантов: Draft/Underfunded/Active. Возвращает unreleased_ngonka (пул сообщества по умолчанию) и unreleased_usdt. Неверный получатель → частичная выплата, остаток в pending_refund_*, завершено через CompleteRefund.
  • AdminReleaseMilestone / AdminSkipMilestone — экстренные рычаги.
  • RemoveCommittee и TopUpFunding — перенесены в версию 2.

8. Авторизация (обзор)

9. События и инструменты

  • Контракт генерирует структурированные события при каждом изменении состояния (grant_draft_created,grant_funded,milestone_evidence_submit,milestone_vote_cast,milestone_released{mode:approval|auto|auto_on_fund},grant_stopped, Committee_upserted, config_updated и т. д.) — для индексаторов и информационных панелей.
  • CLI Grantctl вместе с выводом: Draft validate — lint JSON Draft; funding-proposal --grant-id N — создать предложение правительства о финансировании из FundingProposalTemplate; manage-proposal {set-committee,set-milestone-committee,stop} — шаблоны предложений по управлению; milestone status/process-timeouts — мониторинг и тайм-аут кривошипов.
  • Draft validate — проверить черновик JSON;
  • funding-proposal --grant-id N — создать правительственное предложение по финансированию из FundingProposalTemplate;
  • manage-proposal {set-committee,set-milestone-committee,stop} — шаблоны предложений по управлению;
  • веха статус/процесс-таймауты — мониторинг и тайм-аут кривошипов.

Инструментарий не заменяет голосование хоста — он только удаляет ручные ошибки JSON/base64.

Русский перевод
a-kuprin avatar
a-kuprinMaintainerАвтор
2026-05-25

Управление финансированием проекта

Резюме

В настоящее время существует потребность в организации, выделяющей средства из общественного пула, и в адекватных инструментах финансирования проектов.

Мы предлагаем смарт-контракт для управления финансированием проекта. Грантополучатель сначала готовит проект с указанием этапов, каждый из которых привязан к выплате в долларах США/GNK (оба можно использовать одновременно). Сообщество голосует за весь проект; средства переводятся в смарт-контракт; и отраслевой комитет, назначенный принимающей стороной, голосует по каждому достигнутому (или невыполненному) этапу. Отраслевые комитеты являются общими для всех грантов, но сообщество может назначать комитеты для конкретных этапов.

Фон

В дискуссиях столкнулись две точки зрения: одна о том, что надо раздавать «вертолетные деньги», а другая о том, что средства могут закончиться, и тогда хозяева потеряют все, включая смерть проекта. В результате большинство предложений отклоняются, а существующий бюджет не инвестируется. Тем не менее опасения принимающей стороны оправданы.

Есть даже мнение, что команде Core не хватает разработчиков и ее следует нанимать больше. Тем не менее, у сообщества есть бюджет, и каждый хозяин имеет не меньшее право голоса в управлении, но сообщество еще не полностью осознало это. У Gonka есть идеология, и она касается децентрализации — основная команда не должна быть центром, от которого все зависит. Перекладывать ответственность за разработку проекта на основную команду — это несколько незрелое поведение. Создание дорожной карты и движение к созданию Фонда — это признаки зрелого сообщества, которое может управлять своим собственным развитием. Майнеры — это серьезные люди с капиталом и опытом ведения бизнеса, которые владеют акционерным капиталом проекта (через GNK) и на практике формируют совет директоров, который не менее, а, возможно, и более ответственен, чем основная команда. Ведь майнеры вложили деньги и оборудование.

Проблема

При нынешней модели финансирования предложений отказ от всего является очень рациональной тактикой для хозяев. Если деньги выплачиваются вперед, есть огромный риск, что ничего не будет сделано, или сделано некачественно, или не то, что нужно. Хозяева несут этот риск. Если выплата осуществляется в GNK, токены выйдут на рынок и окажут давление на книгу заказов, снизив прибыльность хоста, которая уже находится на грани или превышает ее.

Если проект финансируется на основе постоплаты, грантополучатель рискует ничего не получить, потратив при этом ресурсы и деньги.

Разделение на этапы требует ручной организации и внимания организаторов к проекту — по сути, микроменеджмента со стороны совета директоров.

Решение

Грантополучатель сначала готовит проект с указанием этапов, каждый из которых привязан к выплате. USDT направляется на операционные расходы; GNK (в качестве капитала проекта) вознаграждает за вклад в развитие Gonka и может быть разблокирован через 1 или 2 года (сроки настраиваемы). Возможен не только потоковый вестинг, при котором GNK разблокируется ежедневно и может выйти на рынок: любой график разблокировки.

Хозяева, как совет директоров, голосуют за сам проект и назначают комитет, ответственный за его принятие. Выплата может осуществляться единовременно, но каждый этап должен быть проголосован комитетом, чтобы подтвердить, выполнил ли получатель гранта или не выполнил свои обязательства.

Например, проект может выделить 10 тысяч долларов США сразу, еще 10 тысяч при прохождении контрольной точки и 50 тысяч с двухлетней гарантией после завершения.

Дизайн

Реализовано как доска грантов контрактов CosmWasm в цепочке выводов/contracts/ (по аналогии с коммьюнити-продажей и пулом ликвидности), а также дополнительный вспомогательный прокси-сервер по передаче контрактов для блокировок GNK высотой блока. В экземпляре администратором контракта является модуль gov, поэтому обновления и параметры осуществляются только посредством голосования хоста.

Архитектура и интеграция

  • Источники финансирования: GNK — из x/distribution (пул сообщества) через MsgCommunityPoolSpend; USDT — из контракта на коммьюнити-продажу черезdraw_ibc. Грант-борд принимает оба актива по своему адресу.
  • Управление: все привилегированные действия (финансирование, остановка, изменения в комитете, настройка) происходят только из gov_authority, т.е. они требуют голосования хоста через x/gov .
  • Бухгалтерский учет: в контракте содержится tracked_balance[denom] и для каждого гранта выделено_* / потрачено_* . Инвариант: банковский баланс контракта по номиналу ≥ сумма зарезервированных средств для активных и недостаточно финансируемых грантов плюс ожидающие возмещения. Это не позволяет одному гранту расходовать средства другого.
  • Антипожертвование: любые средства, отправленные на адрес контракта вне формального потока, остаются за пределами tracked_balance и не относятся к грантам.

Жизненный цикл гранта

В гранте указано: Черновик → Недостаточно средств/Активен → Остановлен/Остановленвозвращен/Завершен.

Состояния Milestone: Ожидание, ExtensionVotePending, InReview, RetryVotePending, StopVotePending, Выпущено, Отклонено, Пропущено.

Последовательность действий: грантополучатель создает проект → принимает средства через правительство → автоматический этап (если таковой имеется) выплачивается немедленно → для других этапов грантополучатель представляет доказательства → голосование в комитете → выплата.

1. Проект гранта (грантополучатель)

  • CreateDraft — любой может создать черновик, вложив плату за установку в GNK. Плата отправляется в пул сообщества через MsgFundCommunityPool (антиспам, невозвратный).
  • За каждую оплату комиссии вы получаете пул из 10 кредитов для UpdateDraft. Когда кредиты исчерпаны, следующее обновление снова добавляет плату (10 кредитов минус 1 за текущий вызов = осталось 9).
  • Минимальная плата — min_setup_fee_ngonka (жесткий пол 10 GNK). Пока setup_fee < min, контракт считается неактивным.
  • Грантополучатель публикует текст проекта на GitHub (URL-адрес, закрепленный за фиксацией) и помещает Offer_url + Offer_hash (sha256 уценки) в черновик. Это связывает черновик внутри цепочки с описанием вне цепочки.
  • Описание каждой закрытой вехи находится в обсуждении GitHub (description_discussion_url) — для версии 1 это позволяет избежать раздувания состояния. v2 добавит Arweave для неизменяемого хранилища.
  • CloseDraft — закрыть драфт без возврата комиссии. Организаторы могут закрыть черновик через StopGrant.

Проект проверки:

  • Сумма вех равна Request_ngonka/required_usdt (рассчитывается по контракту).
  • Разрешается одна необязательная автоматическая веха с индексом == 0 в начале списка; закрытые этапы выполняются последовательно 1, 2, 3,… .
  • usdt_denom — точный номинал ваучера IBC, неизменяемый на протяжении всего срока действия гранта.
  • Комитет может быть отключен во время проекта — правительство назначает его позже через SetGrantCommittee/SetMilestoneCommittee.

2. Финансирование (Этап 1 — голосование принимающей стороны)

Хозяева голосуют за одно предложение правительства с тремя сообщениями в строгом порядке:

  • MsgCommunityPoolSpend — GNK из пула сообщества на адрес доски грантов.
  • MsgExecuteContract для продажи сообществу с помощьюdraw_ibc —USDT на адрес грантового совета.
  • MsgExecuteContract для предоставления доски с MarkFunded {grant_id, ngonka, usdt, config_hash} — должен быть последним.

Поведение MarkFunded:

  • Требуется info.sender == gov_authority иgrant.status == Draft .
  • Сверяет payload.config_hash на соответствие текущему config.config_hash. Если хосты передали UpdateConfig в том же окне, MarkFunded возвращается, и вся транзакция финансирования откатывается. Это гарантирует, что хосты проголосуют именно за тот шаблон, который будет выполняться.
  • Вычисляет delta_ngonka/delta_usdt как увеличение баланса контракта относительно tracked_balance (защита от приписания случайных переводов).
  • Если delta == запрошено → предоставить Active, устанавливаетсяfunded_at. Если дельта > запрошена → излишек возвращается в том же транзакцию (GNK → пул сообщества, USDT → продажа сообщества). Если дельта < запрошена → предоставить недостаточное финансирование, исправлено через правительство.

Шаблон предложения о финансировании возвращается запросом FundingProposalTemplate {grant_id} — всегда пересчитывается из текущей конфигурации и возвращает config_hash для встраивания в MarkFunded. Инструмент CLI Grantctl для предложения о финансировании записывает готовый JSON.

3. Авто-веха (индекс 0) – мгновенная выплата.

  • Дополнительная веха с индексом == 0 (не более одной, всегда первой) выплачивается внутри MarkFunded немедленно, без участия комитета и каких-либо доказательств.
  • Используется для: Грант по доверенности — одна авто-веха за 100% суммы; отражает сегодняшний поток MsgCommunityPoolSpend, но с учетом доски грантов и унифицированным потоком событий. авансовый транш, например индекс 0 = 20% ГНК по фонду, индекс 1..N = 80% через этапы.
  • Прокси-грант — одна авто-веха за 100% суммы; отражает сегодняшний поток MsgCommunityPoolSpend, но с учетом доски грантов и унифицированным потоком событий.
  • авансовый транш, например индекс 0 = 20% ГНК по фонду, индекс 1..N = 80% через этапы.
  • Автоматическая веха выплачивается только тогда, когда грант становится активным. Для недостаточного финансирования он остается в состоянии ожидания до тех пор, пока не будет полностью профинансирован.

4. Приемка этапа (Этап 2 — комитет)

Для каждой закрытой вехи (индекс ≥ 1):

  • Грантополучатель вызывает SubmitMilestoneEvidence { доказательство_uri, доказательство_хэш } . Milestone → InReview, таймер review_deadline = now + review_ period_секунды.
  • В контракте сохраняется снимок комитета (VOTE_SNAPSHOTS) — список участников и пороговое значение при открытии голосования.
  • Члены комитета называют VoteOnMilestone {да}.
  • Любой может вызвать ExecuteMilestoneRelease, когда: достигнуто пороговое значение yes_required = ⌈threshold_num × n / Threshold_den⌉ или пройдена review_deadline и результат не определен (автоматический выпуск).

порог yes_required = ⌈threshold_num × n/threshold_den⌉ достигнут, или

  • review_deadline прошел, результат не определен (автоматический выпуск).
  • Выплата: USDT — всегда моментально; GNK — немедленно, если Vesting_blocks == 0, иначе через вестинг-прокси с разблокировкой на current_height + Vesting_blocks. Заблокированные GNK не подлежат возврату по StopGrant.

Каскад отклонений (когда комитет голосует против). Следующий статус зависит от времени относительно доказательства_due_at:

  • Слишком много времени до срока → Отклонено, грантополучатель может подать заявку повторно.
  • Плотное окно до истечения срока → RetryVotePending (комитет голосует, разрешить ли еще одну попытку).
  • Уже просрочено → StopVotePending (комитет голосует за прекращение предоставления гранта).

Снимок комитета (шаг 7e). Голосование принимается только в том случае, если избиратель принадлежит snapshot.members ∩ current_committee.members . Пороги (yes_required,blocking_no) используют размер моментального снимка, а не текущего комитета. Это закрывает атаки на стирание голосов, перевес голосов и подтасовку голосов через UpsertCommittee в середине голосования.

Защита самостоятельных сделок. Если избиратель —grant.grantee, голосование автоматически отбрасывается с помощью события Committee_vote_dropped_self_deal.

Пустой комитет – это особенность. Если ни один комитет не примет решения по вехе — автоматически выпустите в review_deadline. Хосты могут намеренно полагаться на таймер.

Этапный заказ. Строго последовательно: веха k не может быть отправлена до тех пор, пока все вехи < k не станут завершающими ( Released / Skiped ). Параллельное рассмотрение не поддерживается в версии 1.

5. Таймеры и параметры (все в Config, только для правительства)

Все параметры являются общими для всего контракта; грантополучатель их не устанавливает. Они включены в config_hash, который привязывает предложение о финансировании к активной конфигурации.

Поток доставки:

  • RequestMilestoneExtension { предложенный_evidence_due_at } — получатель гранта может попросить продлить срок; комитет голосует через VoteOnMilestoneExtension. Утвердить → новое доказательство_due_at в пределах max_deadline_extension. Отклонено или не решено → предоставление грантов прекращается, GNK возвращается в пул сообщества.
  • ProcessDeliveryTimeouts — запуск (только для получателя гранта), запускает StopGrant, если срок истек + отсрочка передана без каких-либо доказательств и без активного голосования за продление. Никакого автоматического выпуска без доказательств — только остановка с возвратом средств.
  • ProcessMilestoneTimeouts — включение автоматического выпуска этапов в InReview с неопределенным результатом после review_deadline .

6. Дополнительная передача прав (vesting-proxy)

  • Минимальный контракт с замками высотой блока. Каждый замок хранит получателя, номинал, сумму, unlock_height,grant_id,milestone_index.
  • Жилет — может звонить только грант-совет. Заявить — любой, кто после unlock_height. AdminCancel — только для правительства.
  • Используется для GNK с Vesting_blocks > 0. USDT никогда не передается.
  • Почему бы не x/streamvesting: он принимает отправителей только из списка разрешений (gov/inference). Контракты не могут вызвать его без апгрейда цепочки. v2 – добавить доску грантов в AllowedExternalVestingSenders.

7. Управление комитетом и остановка (только для государственных органов)

  • UpsertCommittee — создать/заменить комитет (члены, порог). Увеличено членство_ревизия . Не трогает снимки (смещаются ручки пересечения).
  • SetGrantCommittee / SetMilestoneCommittee — переназначить комитет. Если это затронет какой-то этап голосования, снимки и голоса будут удалены.
  • StopGrant {refund_ngonka_to,refund_usdt_to} — остановить грант в любом из вариантов: Draft/Underfunded/Active. Возвращает unreleased_ngonka (пул сообщества по умолчанию) и unreleased_usdt. Неверный получатель → частичная выплата, остаток в pending_refund_*, завершено через CompleteRefund.
  • AdminReleaseMilestone / AdminSkipMilestone — экстренные рычаги.
  • RemoveCommittee и TopUpFunding — перенесены в версию 2.

8. Авторизация (обзор)

9. События и инструменты

  • Контракт генерирует структурированные события при каждом изменении состояния (grant_draft_created,grant_funded,milestone_evidence_submit,milestone_vote_cast,milestone_released{mode:approval|auto|auto_on_fund},grant_stopped, Committee_upserted, config_updated и т. д.) — для индексаторов и информационных панелей.
  • CLI Grantctl вместе с выводом: Draft validate — lint JSON Draft; funding-proposal --grant-id N — создать предложение правительства о финансировании из FundingProposalTemplate; manage-proposal {set-committee,set-milestone-committee,stop} — шаблоны предложений по управлению; milestone status/process-timeouts — мониторинг и тайм-аут кривошипов.
  • Draft validate — проверить черновик JSON;
  • funding-proposal --grant-id N — создать правительственное предложение по финансированию из FundingProposalTemplate;
  • manage-proposal {set-committee,set-milestone-committee,stop} — шаблоны предложений по управлению;
  • веха статус/процесс-таймауты — мониторинг и тайм-аут кривошипов.

Инструментарий не заменяет голосование хоста — он только удаляет ручные ошибки JSON/base64.

Оригинал
a-kuprin avatar
a-kuprinMaintainerАвтор
2026-05-25

Project funding governance

Summary

At present, there is a need for an organization to allocate funds from the community pool and for adequate project-funding tools.

We propose a smart contract to govern project funding. The grantee first prepares a project with milestones, each tied to a USDT/GNK payout (both can be used at once). The community votes on the whole project; funds are moved into the smart contract; and an industry committee appointed by hosts votes on each milestone being met (or not met). Industry committees are shared across all grants, but the community can assign committees to specific milestones.

Background

In discussions, two views have clashed: one that “helicopter money” should be handed out, and another that funds can run out and then hosts lose everything , together with the death of the project. As a result, most proposals are rejected and the existing budget is not invested. Host concerns are nevertheless justified.

There is even a view that the Core team lacks developers and should hire more. Yet the community has a budget and every host has no less say in governance—but the community has not fully realized that. Gonka has an ideology, and it is about decentralization—the Core team must not be the center everything depends on. Shifting responsibility for project development onto the Core team is somewhat immature behavior. Creating a roadmap and moving toward a Foundation are signs of a mature community that can steer its own development. Miners are serious people with capital and business experience who hold project equity (via GNK) and, in practice, form a board of directors that is no less—and perhaps more—responsible than the Core team. After all, miners invested money and hardware.

Problem

Under the current proposal-funding model, rejecting everything is a very rational tactic for hosts. If money is paid upfront, there is a huge risk that nothing will be done, or done poorly, or not what was needed. Hosts bear that risk. If payout is in GNK, tokens will hit the market and pressure the order book, crushing host profitability that is already at or past the edge.

If a project is funded on a post-payment basis, the grantee risks receiving nothing while still spending resources and money.

Splitting into milestones requires manual organization and host attention to the project—effectively micromanagement by the board of directors.

Solution

The grantee first prepares a project with milestones, each tied to a payout. USDT is directed at operating expenses; GNK (as project equity) rewards contribution to Gonka’s development and can be unlocked after 1 or 2 years (timing is configurable). More than stream vesting—where GNK unlock daily and can reach the market—is possible: any unlock schedule.

Hosts, as the board of directors, vote on the project itself and appoint a committee responsible for acceptance. Payout can happen in one lump sum up front, but each milestone must be voted on by the committee to confirm whether the grantee fulfilled or failed obligations.

For example, a project might allocate 10k USDT immediately, another 10k on passing a milestone, and 50k with a 2-year vest on completion.

Design

Implemented as a CosmWasm contract grant-board in inference-chain/contracts/ (along the lines of community-sale and liquidity-pool ), plus an optional helper contract vesting-proxy for block-height GNK locks. On instantiate, the contract admin is the gov module so upgrades and parameters go only through host votes.

Architecture and integration

  • Funding sources: GNK—from x/distribution (community pool) via MsgCommunityPoolSpend ; USDT—from the community-sale contract via withdraw_ibc . Grant-board accepts both assets at its address.
  • Governance: all privileged actions (funding, stop, committee changes, config) come only from gov_authority —i.e. they require a host vote via x/gov .
  • Accounting: the contract holds tracked_balance[denom] and per grant allocated_* / spent_* . Invariant: the contract’s bank balance per denom ≥ sum of reserved funds for active and underfunded grants plus pending refunds. This prevents one grant from spending another’s funds.
  • Anti-donation: any funds sent to the contract address outside the formal flow stay outside tracked_balance and are not attributed to grants.

Grant lifecycle

Grant states: Draft → Underfunded / Active → Stopped / StoppedRefunded / Completed .

Milestone states: Pending , ExtensionVotePending , InReview , RetryVotePending , StopVotePending , Released , Rejected , Skipped .

Flow: grantee creates draft → hosts fund via gov → auto-milestone (if any) pays immediately → for other milestones grantee submits evidence → committee votes → payout.

1. Grant draft (grantee)

  • CreateDraft —anyone can create a draft by attaching a setup fee in GNK . The fee is sent to the community pool via MsgFundCommunityPool (anti-spam, non-refundable).
  • Each fee payment grants a pool of 10 credits for UpdateDraft . When credits are exhausted, the next update attaches the fee again (10 credits, minus 1 for the current call = 9 left).
  • Minimum fee— min_setup_fee_ngonka (hard floor 10 GNK). While setup_fee < min , the contract is considered inactive.
  • The grantee publishes the project text on GitHub (commit-pinned URL) and puts proposal_url + proposal_hash (sha256 of the markdown) in the draft. This binds the on-chain draft to the off-chain description.
  • Each gated milestone’s description lives in a GitHub Discussion ( description_discussion_url )—for v1 this avoids state bloat. v2 will add Arweave for immutable storage.
  • CloseDraft —close the draft without refunding the fee. Hosts can close a draft via StopGrant .

Draft validation:

  • Milestone amounts sum to requested_ngonka / requested_usdt (computed by the contract).
  • One optional auto-milestone with index == 0 at the start of the list is allowed; gated milestones run sequentially 1, 2, 3, … .
  • usdt_denom —exact IBC voucher denom, immutable for the grant’s lifetime.
  • A committee may be unset at draft time—gov assigns later via SetGrantCommittee / SetMilestoneCommittee .

2. Funding (Phase 1—host vote)

Hosts vote on a single gov proposal with three messages in strict order:

  • MsgCommunityPoolSpend —GNK from the community pool to the grant-board address.
  • MsgExecuteContract to community-sale with withdraw_ibc —USDT to the grant-board address.
  • MsgExecuteContract to grant-board with MarkFunded { grant_id, ngonka, usdt, config_hash } —must be last.

MarkFunded behavior:

  • Requires info.sender == gov_authority and grant.status == Draft .
  • Checks payload.config_hash against current config.config_hash . If hosts passed UpdateConfig in the same window, MarkFunded reverts and the entire funding transaction rolls back. This ensures hosts vote for exactly the template that will execute.
  • Computes delta_ngonka / delta_usdt as the increase in contract balance relative to tracked_balance (protection against attributing stray transfers).
  • If delta == requested → grant Active , funded_at is set. If delta > requested → surplus is returned in the same tx (GNK → community pool, USDT → community-sale). If delta < requested → grant Underfunded , remediated via gov.

The funding proposal template is returned by query FundingProposalTemplate { grant_id } —always recomputed from current config and returns config_hash to embed in MarkFunded . CLI tool grantctl funding-proposal writes ready JSON.

3. Auto-milestone ( index 0 )—instant payout

  • Optional milestone with index == 0 (at most one, always first) pays inside MarkFunded immediately , with no committee and no evidence.
  • Used for: Proxy grant —one auto-milestone for 100% of the amount; mirrors today’s MsgCommunityPoolSpend flow but with grant-board accounting and a unified event stream. Upfront tranche —e.g. index 0 = 20% GNK on fund, index 1..N = 80% via milestones.
  • Proxy grant —one auto-milestone for 100% of the amount; mirrors today’s MsgCommunityPoolSpend flow but with grant-board accounting and a unified event stream.
  • Upfront tranche —e.g. index 0 = 20% GNK on fund, index 1..N = 80% via milestones.
  • Auto-milestone pays only when the grant becomes Active . For Underfunded it stays Pending until fully funded.

4. Milestone acceptance (Phase 2—committee)

For each gated milestone ( index ≥ 1 ):

  • Grantee calls SubmitMilestoneEvidence { evidence_uri, evidence_hash } . Milestone → InReview , timer review_deadline = now + review_period_seconds .
  • Contract captures a committee snapshot ( VOTE_SNAPSHOTS )—member list and threshold at vote open.
  • Committee members call VoteOnMilestone { yes } .
  • Anyone can call ExecuteMilestoneRelease when: threshold yes_required = ⌈threshold_num × n / threshold_den⌉ is met, or review_deadline has passed and outcome is Undecided (auto-release).

threshold yes_required = ⌈threshold_num × n / threshold_den⌉ is met, or

  • review_deadline has passed and outcome is Undecided (auto-release).
  • Payout: USDT—always immediate; GNK—immediate if vesting_blocks == 0 , else via vesting-proxy with unlock at current_height + vesting_blocks . Locked GNK is not refundable on StopGrant .

Rejection cascade (when the committee votes no). Next status depends on time relative to evidence_due_at :

  • Plenty of time before due → Rejected , grantee may resubmit.
  • Tight window before due → RetryVotePending (committee votes whether to allow another attempt).
  • Already past due → StopVotePending (committee votes whether to stop the grant).

Committee snapshot (Step 7e). A vote is accepted only if voter ∈ snapshot.members ∩ current_committee.members . Thresholds ( yes_required , blocking_no ) use snapshot size, not the current committee. This closes vote-erase / vote-overweight / vote-stuffing attacks via mid-vote UpsertCommittee .

Self-deal protection. If the voter is grant.grantee , the vote is dropped silently with event committee_vote_dropped_self_deal .

Empty committee is a feature. If no committee resolves for a milestone—auto-release at review_deadline . Hosts may deliberately rely on the timer.

Milestone order. Strictly sequential: milestone k cannot be submitted until all milestones < k are terminal ( Released / Skipped ). Parallel review is not supported in v1.

5. Timers and parameters (all in Config , gov-only)

All parameters are contract-wide ; the grantee does not set them. They are included in config_hash , which binds the funding proposal to the active config.

Delivery flow:

  • RequestMilestoneExtension { proposed_evidence_due_at } —grantee may ask to extend the deadline; committee votes via VoteOnMilestoneExtension . Approve → new evidence_due_at within max_deadline_extension . Reject or Undecided → grant stops, GNK returns to the community pool.
  • ProcessDeliveryTimeouts —crank (grantee-only), runs StopGrant if due + grace passed with no evidence and no active extension vote. No auto-release without evidence —only stop with refund.
  • ProcessMilestoneTimeouts —crank to auto-release milestones in InReview with Undecided outcome after review_deadline .

6. Optional vesting ( vesting-proxy )

  • Minimal contract with block-height locks. Each Lock stores recipient , denom , amount , unlock_height , grant_id , milestone_index .
  • Vest —only grant-board may call. Claim —anyone after unlock_height . AdminCancel —gov only.
  • Used for GNK with vesting_blocks > 0 . USDT is never vested.
  • Why not x/streamvesting : it only accepts senders from an allow-list (gov/inference). Contracts cannot call it without a chain upgrade. v2—add grant-board to AllowedExternalVestingSenders .

7. Committee management and stop (gov-only)

  • UpsertCommittee —create/replace committee (members, threshold). Bumps membership_revision . Does not touch snapshots (intersection handles drift).
  • SetGrantCommittee / SetMilestoneCommittee —reassign committee. If a milestone in voting is affected—snapshots and votes are wiped.
  • StopGrant { refund_ngonka_to, refund_usdt_to } —stop grant in any of Draft / Underfunded / Active . Returns unreleased_ngonka (default community pool) and unreleased_usdt . Invalid recipient → partial payout, remainder in pending_refund_* , completed via CompleteRefund .
  • AdminReleaseMilestone / AdminSkipMilestone —emergency levers.
  • RemoveCommittee and TopUpFunding —deferred to v2.

8. Authorization (overview)

9. Events and tooling

  • The contract emits structured events on every state change ( grant_draft_created , grant_funded , milestone_evidence_submitted , milestone_vote_cast , milestone_released { mode: approval | auto | auto_on_fund } , grant_stopped , committee_upserted , config_updated , etc.)—for indexers and dashboards.
  • CLI grantctl alongside inferenced : draft validate —lint JSON draft; funding-proposal --grant-id N —generate funding gov proposal from FundingProposalTemplate ; manage-proposal {set-committee,set-milestone-committee,stop} —management proposal templates; milestone status / process-timeouts —monitoring and timeout cranks.
  • draft validate —lint JSON draft;
  • funding-proposal --grant-id N —generate funding gov proposal from FundingProposalTemplate ;
  • manage-proposal {set-committee,set-milestone-committee,stop} —management proposal templates;
  • milestone status / process-timeouts —monitoring and timeout cranks.

Tooling does not replace host voting—it only removes manual JSON/base64 errors.