๐Ÿ”ธBRC-1202: Voting

Secure voting standards for token gated voting and DAOs

Patches' twitter thread: https://twitter.com/TMCC_Patches/status/1672260099719692288


This document will go over the proposed methods of creating a token gated vote utilizing Ordinals. The JSON suggested in this document is a proposal to set a standard and guide on how token gated votes can be executed with Ordinals NFTs.


BRC-1202 is a standard to create fast, secure, and cheap vote tallying for the Ordinals protocol. This has already been executed in production as the first token gated vote for Ordinals.

You can read more about it here, and watch a video of the user experience below

Benefits of the standard:

  • Everything is inscribed on Bitcoin

  • All votes are verifiable down to the nanosecond of consensus

  • No front running or falsifying votes is possible

  • Each vote always costs $0.001

  • The vote takes 3-5 seconds to reach consensus

Why not do everything on Bitcoin directly?

  • Votes can be front ran

  • Costs are very high to inscribe every vote

  • Mempool delays can cause votes to not be posted before end of vote

How it works

  • Inscribe the ballot JSON to bitcoin

    • Points the tallyUri to a L2 for consensus. In production we used a Hedera Consensus Service topic Id for the L2

    • Defines the start and end times and ballot details

  • Have users log into your website with wallet

    • Validate the user holds the inscription Ids that are eligible for the vote

  • Show the ballot and let the user vote

  • Send authorization transaction to wallet

    • Verify after signature that the inscription Id is in that wallet

    • Write vote to the tallyUri

    • Display vote to user after confirmed

  • All users can vote until ballot end time is reached

  • After ballot ends, inscribe the final ballot results back on bitcoin

Function Definitions:

Ballot Creation

To initiate a vote, a ballot should be inscribed onto the Bitcoin Network. Using the first token gated vote as an example, we'll define the current attributes tied to the ballot JSON.

Creates a ballot for the vote to take place

Example Ballot:

	"p": "brc-1202",
	"type": "ballot-start",
	"id": "ballot-kidpepe-1",
	"title": "What is your favorite meme number?",
	"inscriptionIds": [], // optional restriction of eligable ids
	"tallyUri": "hcs://0.0.1350025", // location of tally data (hcs = hedera consensus service)
	"description": "Kid Pepe has teamed up with HGraph Punks to perform the first Ordinals token gated vote. Created by Turtle Moon & powered by Hgraph.io.",
	"scheme": "single-choice",
	"choices": ["420","69"],
	"startTimestamp": "1686610800000000000", // nanosecond unix timestamp
	"endTimestamp": "1687215600000000000",
	"tick": "kidpepe"

JSON format breakdown

Protocol Identifier

The "p" field serves as the identifier for the specific protocol or standard that the voting event follows.


The "type" field defines the specific type of BRC-1202 action taking place. There are three types:

  • ballot-start - The initial ballot inscription

  • vote - A vote tally

  • ballot-end - The end ballot inscription

Unique Ballot ID

The "id" field is used as a unique identifier for this voting event, differentiating it from all other events on the system.

Voting Event Title

The "title" field stores the human-readable title of the voting event, typically displayed to users in UI interfaces.

Eligibility Identifiers

The "inscriptionIds" field contains and array of unique identifiers of voters eligible for this event. If left empty, it implies unrestricted voting rights.

Data Storage Location

The "tallyUri" field is a URI specifying where the data related to the voting event is stored. This could reference various storage types, from blockchain consensus services to decentralized file systems.

Supported Layers:

MORE TO BE ADDED - Please submit pull requests to add L2 support

Event Description

The "description" field offers additional context or details about the voting event, which may include information on its purpose, involved parties, or application of results.

Voting Mechanism

The "scheme" field describes the voting mechanism in use. This could range from "single-choice" to "multiple-choice", or "ranked-choice", and dictates how users can cast their votes.


The "choices" field contains the available voting options for participants. The format of these options would be and array of strings.

Start Time and End Time

The "startTimestamp" and "endTimestamp" fields, denominated in nanosecond unix timestamps, mark the start and end of the voting period. Any vote recorded outside that window is considered invalid.

Market Identifier

The "tick" field functions as a unique identifier or 'tick' in markets or exchanges, used for tracking the event within a market environment.

Specific implementations may extend or modify this structure based on their unique needs.

Voting Creation & JSON Structure

After the ballot is inscribed on bitcoin, votes can be executed on a secure L2. Those votes are only valid if they are within the timestamps stated on the inscribed bitcoin vote. Below is the proposed format for votes on the ballot:

  "p": "brc-1202",
  "type": "vote",
  "inscriptionId": "05e2d05925eaa9ca8bbc066fe34f51bc90305246db8a68ededaf025d998580fei0",
  "choice": ["420"],
  "inscriptionNumber": 971947,
  "ballotId": "ballot-kidpepe-1",
  "accountId": "bc1p3fgqysn5z9ftd70kqpfydwxprmesha9c6qjkchfq4zel3s2j2xas"

Specific implementations may extend this structure based on their unique needs.

These votes should be recorded on a network that captures the timestamp easily, in this example we used Hedera Consensus Service.

Final Ballot Inscription

The final results need to be inscribed back onto the network so all actions are on chain.

Example Final Ballot:

	"p": "brc-1202",
	"type": "ballot-end",
	"id": "ballot-kidpepe-1",
	"title": "What is your favorite meme number?",
	"inscriptionIds": [], // optional restriction of eligable ids
	"tallyUri": "hcs://0.0.1350025", // location of tally data to verify results
	"description": "Kid Pepe has teamed up with HGraph Punks to perform the first Ordinals token gated vote. Created by Turtle Moon & powered by Hgraph.io.",
	"scheme": "single-choice",
	"choices": ["420","69"],
	"startTimestamp": "1686610800000000000", // nanosecond unix timestamp
	"endTimestamp": "1687215600000000000",
	"tick": "kidpepe",
	"votes": [
	"ballotStartInscriptionId": "dc0a3a47cd5aa3f615a7302a929fba693c2e88fe8dbce698ad6d0ff6c813840fi0"

New attributes for ballot-end:


The "votes" field contains the voting choices and their counts from valid votes. The format is an array of objects with choice and count.


The "ballotStartInscriptionId" field points to the initial ballot inscription to tether it to it's beginning point. Use inscription Id over number as index numbers are less accurate.

Last updated