Normative specification
TAP on Doge specification
Rules for reading and writing TAP messages on Dogecoin mainnet. Rules are numbered so they can be cited. "Must" is a requirement; a message that breaks a must is not a TAP message and creates no state.
- Document v1.0.0
- Chain Dogecoin mainnet
- Protocol tag
tap - Client of record
ord-dogecoin
1. Scope and conformance
- S-1
This document describes TAP on Dogecoin mainnet only. Dogecoin testnet and regtest are not covered, and no Bitcoin Universe product indexes TAP on them.
- S-2
The protocol rules originate with the Dogecoin TAP specification published by Trac Systems. Where this document adds detail, that detail comes from the behaviour of ord-dogecoin, the Doginals client the specification names as the standard TAP operates against.
- S-3
Where a rule reflects a Bitcoin Universe indexing decision rather than the protocol itself, it is labelled Universe decision. An implementation may differ on those points and still be a conforming TAP indexer.
- S-4
TAP externally mirrors DRC-20: the same three token operations exist with the same meaning. An implementation that already indexes DRC-20 conforms to the external half of TAP by changing the protocol tag it matches and the operation names it accepts, and by implementing the balance model in section 7.
2. The Doginals envelope
Dogecoin has no Taproot and no segregated witness, so the Bitcoin inscription envelope does not exist here. A Doginals inscription is a sequence of push data in the signature script of the first input of a transaction, and it may continue across several transactions.
- E-1
An inscription is read from the signature script of input 0 only. A well formed envelope in any later input must be ignored.
- E-2
The signature script must decode entirely as push operations. The recognised forms are the zero push (opcode
0x00), the small integer pushesOP_1throughOP_16(0x51to0x60, yielding values 1 to 16), direct pushes of 1 to 75 bytes, andOP_PUSHDATA1,OP_PUSHDATA2, andOP_PUSHDATA4. Any other opcode ends the decode and the transaction carries no inscription. - E-3
The script must yield at least three push values. The first must be exactly the three bytes
ord. Anything else is not an inscription. - E-4
The second push is the piece count. It is decoded as an unsigned little-endian integer of at most 8 bytes; an empty push decodes to 0. A piece count of 0 is invalid and the transaction carries no inscription.
- E-5
The third push is the content type, taken as raw bytes. For a TAP message this is a text content type such as
text/plain;charset=utf-8. - E-6
The body follows as alternating pairs of a countdown value and a chunk. Before each pair the countdown value must equal the current piece count minus one, exactly. It is decoded by the same integer rule as E-4. A mismatch stops the body accumulation at that point.
- E-7
Body chunks are at most 520 bytes each. The body is the concatenation of the chunks in the order encountered.
- E-8
When a transaction's pushes are exhausted and the count has not reached zero, parsing continues into the next transaction of the reveal chain. The first push of that transaction's input 0 must be the next countdown value; if it is not, the whole inscription is invalid, not merely truncated.
- E-9
If the chain of transactions ends while the count is still above zero, the inscription is partial. A partial inscription creates no inscription and therefore no TAP message. There is no recovery: the remaining pieces cannot be supplied later.
- E-10
Once the count reaches zero, any remaining pushes are read pairwise as fields. A field key must be exactly one byte; a longer key ends field parsing. Key
11is the delegate field, whose value is an inscription id in binary form. Fields are not part of a TAP payload and TAP indexers ignore them. - E-11
Universe decision. Dogecoin mainnet inscriptions are indexed from block height 4,600,000. Content before that height is not indexed as an inscription.
- E-12
Universe decision.
ord-dogecoinconfigures no inscription content size limit for Dogecoin mainnet. The practical ceiling is set by transaction relay policy and by what you are willing to pay, not by the indexer.
A Bitcoin ord envelope opens with OP_FALSE OP_IF and closes with OP_ENDIF. OP_IF is not a push opcode, so under E-2 a script containing it decodes to nothing at all. Tooling ported from Bitcoin without changing the carrier produces transactions that confirm, cost full Dogecoin fees, and inscribe nothing.
3. Payload encoding
- P-1
A TAP message is the inscription body interpreted as UTF-8 text containing exactly one JSON object. A JSON array, a bare JSON value, or trailing content after the object is not a TAP message.
- P-2
The object must carry
"p"with the exact lowercase string valuetap. Surrounding whitespace is not trimmed for you;" tap"is not"tap". - P-3
The object must carry
"op"with one of the eleven operation names in section 6. There is no baremint,transfer,deploy, orsend: every token operation name is prefixed. - P-4
Fields an operation does not define are ignored. An indexer must not fail a message because it carries an extra field, and must not infer meaning from one.
- P-5
Amounts (
amt,max,lim) are decimal strings: digits, with at most one., no sign, no exponent, no separators, no unit. The published privileged mint example uses a JSON number foramt; a string is the form every other example uses and the only form that carries a large supply without loss. - P-6
Tickers are compared case-insensitively. A leading
-marks a ticker reached through a cursed inscription and is a distinct ticker from the same name without it. - P-7
Ticker length is measured in Unicode symbols, not bytes. Until block 5,487,639 a ticker must be exactly 3 symbols or between 5 and 32 symbols. From block 5,487,639 onward, 1 to 32 symbols are allowed. This is a widening of DRC-20's fixed 4 letter tickers.
- P-8
Universe decision. A deployment's declared decimal scale is accepted in the range 0 through 18 inclusive. Decimal-form amounts are converted to atomic integers using that scale without floating-point arithmetic. Activity for a ticker whose deployment has not been observed is held rather than scaled with a guessed scale.
- P-9
Every address in a payload must be a valid Dogecoin mainnet address in base58check form. See section 4.
4. Identifiers
- I-1
An inscription id is the 64 character lowercase hex transaction id of the reveal transaction followed by
iand the index, for example825e287b…a3dci0. Fields that reference another inscription (trade,elem,dep,prv,cancel,redeem.auth) take the inscription id, never the inscription number. - I-2
A ticker identifies a deployment. Tickers are unique across the protocol; the first valid
token-deployfor a ticker owns it and later deployments of the same ticker are invalid. - I-3
A Dogecoin mainnet address is base58check encoded and decodes to 25 bytes: a one byte version, a 20 byte hash, and a 4 byte double-SHA256 checksum. Version
0x1eis pay-to-public-key-hash and renders with a leadingD. Version0x16is pay-to-script-hash and renders with a leading9orA. - I-4
Dogecoin has no bech32 or bech32m address form and no separate ordinals address role. One payment address receives both DOGE and inscriptions. The Bitcoin lowercasing rule for
bc1addresses has no counterpart here; Dogecoin base58 addresses are case-sensitive and must be used exactly as written. - I-5
Universe decision. The Bitcoin Universe Dogecoin marketplace surface accepts only version
0x1epay-to-public-key-hash addresses for its actions, and rejects a0x16pay-to-script-hash address as the wrong form. The protocol itself does not impose that restriction.
5. Tapping
Tapping is TAP's approval step and the source of its name. An inscription is tapped by sending it, after it confirms, from the address that holds it back to that same address.
- T-1
A tap is a transaction that spends the inscription's output and pays it to the same address that held it. Any other destination is an ordinary transfer of the inscription and does not tap it.
- T-2
The operations requiring a tap are
token-send,block-transferables,unblock-transferables,token-tradein all three of its forms, and the creation and cancellation forms oftoken-authandprivilege-auth. - T-3
token-deploy,token-mint,token-transfer,dmt-deploy, anddmt-minttake effect on the inscription's own confirmation and are never tapped. - T-4
A signed
token-authredeem is authorised by its signature rather than by ownership, so anyone may inscribe it and no tap is required. - T-5
Conditions are evaluated at tapping time, not at inscribing time. A
token-sendwhose sender had the balance when inscribed but not when tapped has its unfunded items skipped.
6. Operations
6.1 token-deploy
{
"p": "tap",
"op": "token-deploy",
"tick": "tap",
"max": "21000000",
"lim": "1000"
}
- D-1
tickandmaxare required.limis optional; without it the whole maximum supply may be minted in one mint. - D-2
A deployment for a ticker that already has a valid deployment is invalid and creates nothing.
- D-3
An optional
prvholds the inscription id of an active privilege authority. Only that authority may then say which address is allowed to mint. The authority cannot overridemax,lim, or the ticker. - D-4
If
prvnames an inscription that is not a valid, uncancelled privilege authority at the deploying height, the deployment fails.
6.2 token-mint
{
"p": "tap",
"op": "token-mint",
"tick": "tap",
"amt": "1000"
}
- M-1
tickandamtare required. The ticker must already be deployed. - M-2
amtmust not exceed the deployment'slim, and the mint must not take total minted supply pastmax. Behaviour when a mint would crossmaxfollows the deployment's remaining supply: the excess is not minted. - M-3
Minted amounts credit the address holding the mint inscription's output.
- M-4
If the deployment carries
prv, the mint must carry aprvobject holding the authority'ssig,hash,address, andsalt. The address in that object is the only address permitted to mint, and it must be a Dogecoin mainnet address. A mint from any other address fails and the authority must reissue with a fresh salt, because hashes are unique across the whole protocol state.
6.3 token-transfer
{
"p": "tap",
"op": "token-transfer",
"tick": "tap",
"amt": "100"
}
- X-1
tickandamtare required. There is no recipient field. This operation parks an amount; the recipient is chosen later, by sending the resulting inscription in an ordinary Dogecoin transaction. - X-2
On confirmation,
amtmoves from the holder's available balance into transferable balance. The inscription is now a live transfer inscription. - X-3
When the transfer inscription is sent to another address, the amount leaves the sender's transferable balance and credits the recipient's available balance. The inscription is then consumed and cannot move tokens again.
- X-4
A
token-transferfor more than the holder's available balance is invalid and parks nothing. - X-5
If the receiving address has tapped
block-transferables, an incoming inscribe transfer is skipped and credits nothing. Transfer inscriptions that were already live stay usable.
6.4 token-send
{
"p": "tap",
"op": "token-send",
"items": [
{ "tick": "tap", "amt": "10000", "address": "DHZqJo3DUyhQsrdR3Kcs8xvfaMzPkzE5gP" },
{ "tick": "-tap", "amt": "500", "address": "D5djC8ayTw5dixq1bKGHABLE8KPN9MrF4C" }
]
}
- N-1
itemsis a non-empty array. Each item requirestick,amt, andaddress. There is no limit on the number of items, and tickers may be mixed freely. - N-2
The inscription must be inscribed to the sender's own address and then tapped. Only on tapping do the sends execute.
- N-3
token-sendis atomic on syntax: if any item is syntactically invalid at inscribing time, the whole inscription is invalid. - N-4
token-sendis not atomic on semantics: at tapping time each item is evaluated individually, and items that fail (insufficient funds, an invalid amount, a wrong data type) are skipped while the rest execute. - N-5
Each item spends available balance only, which is total balance minus the amount parked in live transfer inscriptions.
- N-6
Recipient addresses must be trimmed and must be valid Dogecoin mainnet addresses. See the note in section 10 about the address wording inherited by the published specification text.
6.5 block-transferables and unblock-transferables
{ "p": "tap", "op": "block-transferables" }
- B-1
Both operations carry no fields beyond
pandop, and both must be inscribed to the acting address and tapped. - B-2
While blocked, incoming inscribe transfers to that address are skipped and no subsequent
token-transferto it succeeds. Transfer inscriptions already live remain valid and usable. - B-3
This exists to stop grief attacks against addresses that operate token authorities, where an authority redeems tokens out of its own account and an unexpected inbound transfer would disturb its accounting.
6.6 token-trade
Three forms share the operation name and are distinguished by their fields.
Create, as seller
{
"p": "tap", "op": "token-trade", "side": "0",
"tick": "tap", "amt": "1",
"accept": [ { "tick": "buidl", "amt": "0.1" } ],
"valid": "5900000"
}
- R-1
All of
side,tick,amt,accept, andvalidare required.sideis the string"0"for the seller. - R-2
validis a Dogecoin block height and must be in the future, inclusive, when the buyer taps. A trade is invalid once the current block exceeds it. Because Dogecoin blocks arrive about once a minute, a window expressed in blocks is roughly one tenth the wall clock duration the same number would give on Bitcoin. - R-3
Tickers in
acceptmust be unique. Where a ticker repeats, only the first entry is indexed. - R-4
Every accepted ticker must be deployed at the moment the trade is filled, and the seller must own the offered amount in available balance at that moment.
- R-5
The inscription must be tapped by the seller to open the trade.
Cancel, as seller
{ "p": "tap", "op": "token-trade", "side": "0", "trade": "<inscription id>" }
- R-6
tradeholds the inscription id of the trade, not its number. Cancellation succeeds only if the cancelling address owns that trade inscription, and must be tapped. Once cancelled, the trade can never be filled.
Fill, as buyer
{
"p": "tap", "op": "token-trade", "side": "1",
"trade": "<inscription id>",
"tick": "buidl", "amt": "0.1",
"fee_rcv": "<Dogecoin address>"
}
- R-7
All fields except
fee_rcvare required.sideis the string"1". - R-8
tickandamtmust match exactly one entry of the referenced trade'sacceptarray. The buyer fills exactly one accepted token, never all of them. - R-9
When
fee_rcvis present it must be a valid Dogecoin address, and a fixed 0.3% fee in the purchased token is charged to the buyer on top of the purchase amount. The fee applies only where the amount and its decimal scale allow 0.3% to be expressed; otherwise the fee is zero. - R-10
The fill must be tapped by the buyer. A fill tapped after
validhas passed fails. - R-11
A fill succeeds only if every condition holds and all balances credit correctly: the accepted token and its exact amount to the seller, the offered token to the buyer, and the fee, if any, to the fee receiver.
6.7 token-auth
A token authority is a third party that signs redeem messages. Anyone may inscribe a signed redeem, and the authorised tokens move. The protocol never learns why: the authority's logic stays off chain. Signatures are secp256k1.
- A-1
The creation form carries
sig(withv,r,s),hash,salt, andauth, an array of deployed tickers. An emptyautharray authorises every token the authority's account holds. - A-2
The public key is recovered from
hash. To verify, theautharray is JSON-stringified and hashed together withsaltassha256(auth + salt). Thesaltexists so the resulting hash cannot collide. - A-3
hashmust never have been used before anywhere in the protocol state. A reused hash invalidates the message. - A-4
Creation is atomic: if
authis non-empty, every ticker in it must be deployed at inscribing time. The authority address need not hold the tokens at creation, though it must at redeem time. - A-5
A creation must be tapped by the authority address.
- A-6
The redeem form carries
sig,hash,salt, and aredeemobject holdingitems(eachtick,amt,address),auth(the authority's inscription id), anddata, which must be present and may be empty. - A-7
A redeem verifies when both public keys match, both hashes are valid, the referenced authority is not cancelled, and every ticker in
itemsappears in the originalauthlist. The tokens then move exactly astoken-sendmoves them, including the available-balance rule. No tap is required. - A-8
The cancellation form carries
cancel, the inscription id of an existing uncancelled authority, and must be tapped by the authority address. After cancellation no redeem against that authority ever executes again.
6.8 privilege-auth
A privilege authority gates who may mint a deployment, and records signed statements that a given file hash belongs to a given address. It is the mechanism behind whitelists, launchpads, and provenance for off-chain content.
- V-1
The creation form carries
sig,hash,salt, and anauthobject, and must be tapped. - V-2
A deployment references an authority through
prv. A mint against such a deployment carries aprvobject with the authority's signature and the permitted minting address, as in M-4. - V-3
The hashed verification form carries
prv(the authority's inscription id),address,verify(a sha256 digest of file contents),col(a collection name, at most 512 Unicode symbols, present but possibly empty), andseq. - V-4
seqmust be a JSON unsigned integer no larger than 9007199254740991. Passingseqas a string fails the verification. This is the one place in TAP where a string form is explicitly rejected, and it is the opposite of the convention for amounts. - V-5
Different authorities may make conflicting statements about the same hash. There is no arbitration in the protocol: a project must publish its authority inscription id off chain, and that published id is the source of truth for its collection.
- V-6
The cancellation form carries
canceland must be tapped. After it, no further mints or verifications managed by that authority take effect, which is how a collection is finalised. - V-7
Salts should be deterministic, such as an inscription id, rather than random, when the authority needs to be able to reindex its own history.
6.9 dmt-deploy and dmt-mint
{
"p": "tap",
"op": "dmt-mint",
"tick": "dogenat",
"blk": 5000000,
"dep": "825e287bb7dd163ed633110e31bc6abb6c80815ca68b7dd3cc71d729ecaaa3dci0"
}
- G-1
Digital Matter Theory tokens derive their mintable amounts from block data rather than from a free choice of amount. TAP on Dogecoin supports element fields 4 (block height), 10 (nonce), and 11 (bits).
- G-2
dmt-deployrequireselem(the element inscription id),tick, anddt. It may carryprv. - G-3
dmt-mintrequirestick,blk(the block height being minted), anddep(the deployment inscription id). Each block height may be minted once per deployment. - G-4
Until Dogecoin block 5,497,099, element field numbers and the
blkvalue were interpreted with JavaScriptparseIntrules, which stop at the first non-digit. From block 5,497,100 onward both must be precise. Writeblkas a JSON integer. - G-5
TAP indexers on Dogecoin must also index Dogemap exactly as the bitmap specification defines, substituting the name
dogemapthroughout.
7. State model
Every address holds three quantities per ticker. Two are stored and the third is derived.
- W-1
Available is what a new operation may spend. Transferable is what is parked in live transfer inscriptions. Total is their sum.
- W-2
Operations that spend available balance only:
token-transfer,token-send, atoken-authredeem, and the seller side oftoken-trade. - W-3
A transfer inscription has exactly two states: live, and consumed. It is consumed the first time it is sent to a different address, and it can never move tokens again.
- W-4
Messages are applied in confirmation order. Within a block, they are applied in the order the block orders the transactions.
- W-5
State is a pure function of the confirmed chain. Two indexers reading the same chain to the same height must produce the same balances. Where they do not, one of them is wrong; the chain is not ambiguous.
8. Activation heights
| Height | Change | Source |
|---|---|---|
4,600,000 | First Dogecoin mainnet height at which inscriptions are indexed. | ord-dogecoin, Universe decision |
4,771,259 | Ord wallet 1.0.1 behaviour becomes required. This is also the beginning of Dogemap. | Dogecoin TAP specification |
5,487,639 | Ticker lengths widen from "3, or 5 to 32" to "1 to 32" Unicode symbols. | Dogecoin TAP specification |
5,497,100 | DMT element field numbers and the blk value must be precise. Below this height they are read with JavaScript parseInt rules. | Dogecoin TAP specification |
The TAP protocol follows ord wallet releases conservatively rather than adopting every release, and announces supported upgrades with a grace period so indexers can prepare. An indexer that silently tracks the newest ord release is not conforming.
9. Invalid conditions
Each of these produces no state change. Nothing partial is applied and nothing is queued for later.
| Condition | Rule |
|---|---|
| The envelope is in an input other than input 0. | E-1 |
The signature script contains a non-push opcode, including a ported OP_FALSE OP_IF envelope. | E-2 |
The first push is not exactly ord, or the piece count is zero. | E-3, E-4 |
| A countdown value does not equal the current piece count minus one. | E-6 |
| The reveal chain ends before the countdown reaches zero. | E-9 |
| The body is not valid UTF-8 JSON, or is not a single object. | P-1 |
p is not exactly tap, or op is not one of the eleven names. | P-2, P-3 |
| An amount is not a plain decimal string, or a ticker breaks the length rule for its height. | P-5, P-7 |
| An address is not a valid Dogecoin mainnet address. | P-9, I-3 |
| A ticker is deployed twice. | D-2 |
A mint exceeds lim, or a transfer exceeds available balance. | M-2, X-4 |
| An internal operation is never tapped, or is sent to an address other than its own. | T-1, T-2 |
A trade is filled after valid, or filled for a token not in accept. | R-2, R-8 |
| An authority hash has been used before, or the referenced authority is cancelled. | A-3, A-7 |
seq is passed as a string in a hashed verification. | V-4 |
10. Defects in the published specification text
The Dogecoin TAP specification was derived from the Bitcoin TAP document, and three Bitcoin artefacts survived the derivation. They are documented here so an implementer reading the upstream text is not misled, and so a reader can tell a documentation artefact from a protocol rule.
- Q-1
The
token-sendsection states that recipient addresses "must be valid Bitcoin addresses" and adds a rule about lowercasing addresses that begin withbc1. On Dogecoin the recipient must be a valid Dogecoin mainnet address, and there is no bech32 form to lowercase. Dogecoin base58 addresses are case-sensitive; changing their case invalidates the checksum. - Q-2
Every address in the published examples is a Bitcoin bech32 or bech32m address. Read them as placeholders. A payload built by copying one of those examples verbatim sends to an address that cannot exist on Dogecoin.
- Q-3
The privilege authority section states an activation "block height 841682". That is a Bitcoin height, and Dogecoin passed 841682 many years before inscriptions existed on it. Treat privilege authorities as available on Dogecoin over the whole indexed range and confirm the intended activation with the protocol authors before relying on a boundary there.
The validator implements the rules on this page, including the address checks in Q-1 and Q-2. It runs entirely in your browser.