This is only an experiment. Assume all lrc-20s will have no value.
The idea is to create a locking-native fungible token protocol in the spirit of brc-20.
It uses 1sat ordinals for token ownership and locks to mint, and locks also for tickers and signalling generally.
There are 3 kinds of transactions:
- Deploy - Define a new lrc-20
- Mint - Create new tokens of a deployed lrc-20
- Transfer - Reassign lrc-20 tokens to another user
Transactions in lrc-20 use 1sat inscriptions to denote their operation.
Inscriptions follow the 1sat ordinals spec. Typically they will be 1SAT_P2PKH
scripts:
OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG
OP_FALSE OP_IF "ord" OP_1 <content-type> OP_0 <data> OP_ENDIF
The content-type is application/json
. The data is a valid JSON object.
In addition, mint transactions are required to have at least one sat lockup script. Mints must lock at least the amount defined in deploy to be valid. The order of outputs does not matter.
Combinations of deploys and transfers in a transaction are ok. If one lrc-20 operation is invalid, it does not invalidate the others. Mints however must always be in their own transaction.
- Json is encoded in utf-8
- Json spacing and the order of entries do not matter
- Strings are not case-sensitive. (HODL = hodl)
- Spacing within strings matters. ("lrc-20" != "lrc - 20 ")
- The user may add custom fields in addition to those required
- If an operation is invalid, its tokens are burned
Define a new lrc-20.
{
"p": "lrc-20",
"op": "deploy",
"tick": "hodl",
"max": 21000000,
"lim": 10000,
"sats": 100000000,
"blocks": 21000
}
Key | Required | JSON type | Description |
---|---|---|---|
p | yes | string | Protocol: "lrc-20" |
op | yes | string | Operation: "deploy" |
tick | yes | string | Ticker: 4-letter identifier of the lrc-20 |
max | yes | number | Max supply: Total number of tokens to be minted |
dec | no | number | Decimals: Decimal shift for display. Defaults to 0. |
lim | yes | number | Mint limit: Limit on tokens minted per user mint operation |
sats | yes | number | Lock amount: Minimum amount of satoshis locked to be a valid mint |
blocks | yes | number | Lock blocks: Minimum number of blocks locked to be a valid mint |
- The ticker is always 4 bytes encoded as utf-8
max
,dec
,limit
,sats
, andblocks
must all parse to non-negative integers- Compared to bsv-20,
max
,dec
, andlimit
are numbers, not strings, reducing ambiguity - Maximum supply cannot exceed 2^64 - 1
- Number of decimals cannot exceed 18
- Some JSON implementations like JavaScript's
JSON.parse
lose precision above 2^53. Using a library is recommended.
Mint a deployed lrc-20.
Important: Spending mint inscriptions without proper transfer inscriptions will result in a burn
{
"p": "lrc-20",
"op": "mint",
"id": "3b313338fa0555aebeaf91d8db1ffebd74773c67c8ad5181ff3d3f51e21e0000_1",
"amt": 10000
}
Key | Required | JSON type | Description |
---|---|---|---|
p | yes | string | Protocol: "lrc-20" |
op | yes | string | Operation: "mint" |
id | yes | string | Deploy id: <txid>_<vout> of the deploy inscription. vout is 0-indexed. |
amt | yes | number | Mint amount: Number of tokens to mint |
- Only one mint is allowed per tx otherwise all mints are invalid
amt
must parse to a non-negative integer- Compared to bsv-20,
amt
is always a number, not a string - If
amt
is more than the deploylim
, the operation is invalid - The first mint to exceed the maximum supply will receive the fraction that is valid. (ex. 21,000,000 maximum supply, 20,999,242 circulating supply, and 1000 mint inscription = 758 received)
- If two mints occur in the same block, prioritization is assigned via order they were confirmed in the block. (first to last).
- The number of blocks locked can only be determined once the tx is in a block. It is recommended users lock up for slightly longer than required in case the tx is not immediately confirmed.
Transfer a deployed lrc-20.
{
"p": "lrc-20",
"op": "transfer",
"id": "3b313338fa0555aebeaf91d8db1ffebd74773c67c8ad5181ff3d3f51e21e0000_1",
"amt": 10000
}
Key | Required | JSON type | Description |
---|---|---|---|
p | yes | string | Protocol: "lrc-20" |
op | yes | string | Operation: "transfer" |
id | yes | string | Deploy id: <txid>_<vout> of the deploy inscription. vout is 0-indexed. |
amt | yes | number | Transfer amount: Number of tokens to send |
- Tokens transfer like bitcoins from inputs to outputs
amt
must parse to a non-negative integer- Compared to bsv-20,
amt
is always a number, not a string - If
amt
is more than the remaining input tokens, that operation is invalid
Implied transfers are transactions that move tokens without an inscription. Under ordinal theory, this is allowed since an inscription is linked to its ordinal. The new output must be a 1sat ordinal. The moved inscription is invalid if it is consumed at all as part of an earlier transfer inscription.
The unambiguous identifier for an lrc-20 is its deploy txid
and vout
, not its ticker. Ticker duplicates are allowed by design. If an lrc-20 has an unpopular deploy config and nobody mints it, another lrc-20 should be able to take its ticker.
Ultimately wallets and exchanges will assign tickers, but it is strongly recommended they use locks to determine which deploy is the official one. The lrc-20 with the most total vibes across all transactions (ideally including social posts, likes, and transfers) should get the ticker.
Acquiring and retaining tickers has a game theory of its own. It encourage larger locks for mints and non-minimal locks on transfers. It also makes established tickers more valuable since they are unlikely to be successfully challenged. Challenging an lrc-20 for its ticker could start a locking arms race between communities which would be exciting.