Serialized Tokens

There have been a few conversations in the past on slack about serialized tokens and how they could be accomplished. Unfortunately, all of that conversation history is lost. I think it is time to capture this idea in a forum post and get feedback from the community.

The general idea is to be able to assign each token a unique ID which is tracked through the tokens lifecycle.

Example Use


Joe the artist creates a new piece of artwork called “DigitalCurrency”.
Joe now wants to sell the ‘original’ artwork as well as 300 ‘prints’.
Joe also wants his buyers to be able to proove they legally own the artwork by giving them a digital token with the purchase.

Joe registers the JOESART asset
Joe registers the JOESART.DigitalCurrency subasset and indicates he wants serialized tokens
Joe issues 300 JOESART.DigitalCurrency tokens to represent his 300 prints.

When Joe sells the original artwork to a buyer, he also transfers ownership of the JOESART.DigitalCurrency to the buyer.

When Joe sells any of his 300 prints, he also sends the buyer a JOESART.DigitalCurrency token

The ‘original’ artwork owners can now proove they are the legal owner by checking that the owner owns the JOESART.DigitalCurrency asset on the blockchain

The ‘print’ artwork owners can now proove they are the legal owners by checking that the owner has the serialized token in their address.


I believe that the following sections of CP would need to be updated to accomplish this:

Balances

  • add a ‘token_ids’ field to the balances table to track token id(s)

Issuances

  • Adds unique_id TEXT field to ‘assets’ table (NULL=not serialized)
  • Add ‘serialized tokens’ option to first issuance only
    • If issuing supply, set unique_id to # of tokens issued
      • Create/Update record in balances table to indicate serial range (ex: ASSET | ADDRESS | 1-100)
    • If NOT issuing supply, set unique_id to 0 (indicates serialized, but none issued yet)
  • When additional supply is issued
    • Increase unique_id value by issuance amount
    • Create/Update record in balances table to indicate serial range (ex: ASSET | ADDRESS | 101-200)

###Sends
send.compose

  • Check if asset has serialized tokens… if YES:
    • Require user to specify unique token id(s) (also support specifying a range of ids)
    • Check balances table and verify user has control of the tokens with the specified id(s)… if YES
      • Send token and embed unique token id(s) into transaction (possibly in memo field?)

send.parse

  • Check balances table and verify that source has control of the tokens with the specified id(s)… if YES
    • Update balances table to REMOVE specified id(s) from the SOURCE address (ASSET | SOURCE)
    • Update balances table to ADD specified id(s) to the DESTINATION address (ASSET | DESTINATION)

###Orders

  • Require users to specify token id(s) when listing an order for a serialized token
  • ???

##Questions

  • Should there be a limit on how many serialized tokens should be issued?
  • Should there be an XCP fee per serialized token issued? (there is definitely a higher operational cost)

I look forward to hearing some feedback :slight_smile:

4 Likes

I like this.

I believe it best to add a serial field to the assets table and extend the asset_longname.

Say I issue 100 of JOESART.print. In the database, 100 assets are created. In the assets table, they look like this:

[
  {"asset_name": "A95428956661682000", "asset_longname": "JOESART.print#1", "serial": 1},
  {"asset_name": "A95428956661682001", "asset_longname": "JOESART.print#2", "serial": 2},
  {"asset_name": "A95428956661682002", "asset_longname": "JOESART.print#3", "serial": 3}
  // etc...
  {"asset_name": "A95428956661682100", "asset_longname": "JOESART.print#100", "serial": 100}
]

Notice that the # in the longname is an invalid standard subasset character.

Now each asset can be dealt with by it’s numerical asset name. By doing it this way, each serialized token can enjoy the full functionality of any asset. We don’t need to change any of the code or messages that deal with assets by name.

All we need to do is add methods of issuing and sending groups of assets. The issuance message needs to be a new message type (issue serialized asset). Serialized assets must be indivisible.

For the sends, We can either create a new type of send message. Or… we can modify/extend CIP 10 to support serialized assets. I like the modifying/extending CIP 10 because I think the typical use case will be sending non-sequential serial numbers (e.g. #52, #64 and #99).

For the API methods, we can specify asset ranges and groups with a simple selection language: JOESART.print#20-30,55 means serials #20 - #30 (inclusive) and #55.

Should there be a limit on how many serialized tokens should be issued?

Yes. But it should be really high. Maybe 2^32 (4 billion).

Should there be an XCP fee per serialized token issued? (there is definitely a higher operational cost)

Yes, but it should be really low. I’d say 0.001 XCP per token. This is 100 XCP ($1,000-$2,000 ish) for 100,000 tokens.

I’d be thrilled if someone burns $10,000 of XCP to create 1 million serialized Counterparty tokens and actually uses them on the Counterparty platform.

2 Likes

Interesting… this is an entirely different method of serializing tokens than I was talking about… I greatly appreciate the feedback :slight_smile:

Now some random thoughts.

Now each asset can be dealt with by it’s numerical asset name. By doing it this way, each serialized token can enjoy the full functionality of any asset.

Your approach seems to issue an unique asset for every token… which IMO adds some additional complexities/confusion around asset/token ownership. The issues/questions I have currently are.

  1. Only works on subassets currently (could prolly be tweaked to work with named assets)
  2. Are you just issuing an asset with no supply? or with 1 token?
  3. If your NOT issuing supply on the token, then users are NOT able to sell their token on the DEX
    • Users can only list individual tokens for sale on the DEX, not asset ownership.
  4. If you ARE issuing supply on the token (1 token per asset), then users CAN sell their token on the DEX, but the asset ownership would remain under the control of the seller
  • This leads to situations where a TOKEN can be bought on the DEX by user A, but the token is still legally “owned” by the asset owner User B…
  1. Would very rapidly explode the # of assets (something I am VERY strongly against)

It seems like this is a quick stab at trying to shoe-horn serialized tokens into the existing system, vs designing a actual tracking system for serialized tokens like my proposal.

My approach seems to me to keep things pretty straightforward, uses a single asset, and tracks the serial number for each token/supply.

Can you explain to me in detail what about my proposal is difficult to accomplish? Perhaps I can change it a bit to make it easier to integrate :slight_smile:

Appreciate the feedback :slight_smile:

Each serialized token would be treated like a special subasset in the database. The supply of that individual subasset would be locked at 1. So JOESART.print#1 would have a supply of 1 and would map to a unique numerical asset ID.

I’m not sure what the confusion is here, but this is how it works with numerical assets mapped to serialized tokens:

JOESART.print#1 can be sold on the DEX just like any other asset or subasset. It would be a separate order than JOESART.print#2 You cannot list 10 JOESART.print for sale on the DEX.

Tracking individual serialized tokens will eat up database space no matter how you do it. I expect we can optimize the space used with either approach.

  1. Adding a ‘token_ids’ to the balances table to track token ids would be inefficient. To look up who owns JOESART.print#175 would require a text matching search on the token_ids column of all balance rows that match JOESART.print. This could be optimized with a second lookup table, but that means all balance lookups would become cross-table joins.

  2. DEX functionality would require message type (consensus) changes. Every DEX order and match message would require a new message format to support the inclusion of a serial number (or numbers).

  3. Send functionality would require message type (consensus) changes. Every send would require a a new message format to support the inclusion of a serial number (or numbers). Both CIP 9 sends and the standard sends would need to change.

  4. More than just the balances table needs to change. Many SQLite queries would need to change. Many (all?) places where an “asset” is referred to in the database would now need to refer to both an asset and a serial number (credits, debits, etc). This would end up being much less efficient than just making the assets individual numerics and using the queries we already have.

In my opinion tracking serial number assignments in a column or another table will not work well. The entire database structure of Counterparty assumes each asset has a unique id. Trying to change that at a fundamental level will make the codebase less efficient, harder to maintain and more prone to errors.

We can accomplish everything we want here by just using the existing database structure.

Adding more assets to the assets table is better than adding another table or column to track serial numbers. It is better now and when it comes time to optimize in the future, it will be better then because we can optimize one simple thing instead of two complicated things.

I’m not sure what the confusion is here, but this is how it works with numerical assets mapped to serialized tokens:

JOESART.print#1 can be sold on the DEX just like any other asset or subasset. It would be a separate order than >JOESART.print#2 You cannot list 10 JOESART.print for sale on the DEX.

My confusion is around who actually owns the physical good legally? Your method does allow for someone to sell a TOKEN on the DEX, but as I mentioned above… who owns the physical good legally? The person who owns the TOKEN, or the person who owns the ASSET? See the confusion?

  • User A registers JOESART.print#1 serialized token… which is an asset

  • User A lists the JOESART.print#1 TOKEN for sale on the DEX

  • User B buys JOESART.print#1 TOKEN from the DEX

  • User A now owns the JOESART.print#1 asset ownership

  • User B now owns the JOESART.print#1 token

Which one is the actual owner of the physical good? The owner of the token or the owner of the asset?

Tracking individual serialized tokens will eat up database space no matter how you do it. I expect we can optimize the space used with either approach.

Agreed. Thanks for the detailed feedback on this… I understand a bit more now why it would be a big undertaking :slight_smile:

We can accomplish everything we want here by just using the existing database structure.

Almost… see above questions about who is legal owner of the artwork? The owner of the TOKEN or the owner of the ASSET? We need it to be 100% clear who is the legal owner of the token and by extension, the physical good.

Perhaps the “owner” issue could be solved by making the numeric asset ownership non-transferrable? Then there is no confusion, as the legal owner of the artwork would be the holder of the TOKEN. Thoughts?

Each serial number is an individual asset.

In your example, User B is now the owner. JOESART.print#1 is held exclusively in User B’s address.

User A is still the original issuer of JOESART.print#1 in the history, but User A does not own JOESART.print#1 anymore. User A can now issue JOESART.print#100, but user A can not issue another JOESART.print#1.

I think ownership transfer is still ok. User A could transfer ownership of JOESART.print to User C. But no one could ever issue another JOESART.print#1 and User B would still own it.

Think of serialized tokens like sub-sub-assets if that helps.

1 Like

Thanks again for the reply :slight_smile:

I have no issue with allowing the transfer of the JOESART.print asset… Joe should be able to continue issuing as many serialized JOESART.print tokens as he wants and send to whomever he wants.

My concern is with allowing the transfer of the JOESART.print#1 asset (A434324324234352) to User C.

User A issued JOESART.print#1 asset/token in the history (no big deal)
User B is owner of JOESART.print#1 token and legal owner of physical goods/artwork
User C is owner of JOESART.print#1 asset (A434324324234352)

User C could now scam users by saying he owns the artwork and could point to his ownership of the JOESART.print#1 asset (A434324324234352) as proof.

User C could also change the asset description on JOESART.print#1 (A434324324234352) to “fake art, don’t buy me” and damage User B’s ability to sell the artwork/token in the future.

Having one user hold the single token, and another user hold asset ownership is confusing to me.

Can you think of any use-cases where it would be desirable to have a single token with different asset owner and token holder?

Just eyeballing it, I would say the Sub-Sub-asset makes the most logical sense, as far as implementing a serialized option on sub-asset token issuance. I for one think it is a valuable enhancement, that goes a long way toward the KISS method that will bring in wider user interest from people running local use benefits, pop-up events, and ground floor endeavors that need a basic set of tools to tokenize sales.

What would be the impact, if any, of the either of the following?

Sub-sub-asset: COMICON.Ticket.1234, COMICON.Ticket.1235
v.
Sub-asset: COMICON.Ticket1234, COMICON.Ticket1235

What would be the impact, if any, of the either of the following?

Sub-sub-asset: COMICON.Ticket.1234, COMICON.Ticket.1235
v.
Sub-asset: COMICON.Ticket1234, COMICON.Ticket1235

FYI… the current subasset implementation already allows you to register COMICCON.TICKET.AS.MANY.LEVELS.DEEP.AS.YOU.WANT.UP.TO.250.CHARACTERS
:slight_smile:

Right, inarticulate expression on my part. I meant to specify that the serialization option on sub-sub-asset creation could be numerical digits only instead of a mixed alphanumeric serial number. However, in hindsight that may not meet user needs, like a need for a month of issuance as the serialization, 27JULY17.01, 27JULY17.02, with two sublevels vs 27JULY1701, 27JULY1702 with one sublevel.

I am envisioning that the UI could have the subasset creation and an additional box to create any serialization, but only utilizing the subasset fee for both actions. Otherwise, good or bad, there would have to be two issuances with additional fees. One for the subasset and one for the serialization. I guess both could be an option the users could exploit as they see fit.

Am I way off?

I believe this would be a new transaction type which would only require one BTC transaction, but would result in issuing many numeric assets, each with 1 indivisible token, and the supply locked.

I’d love it if the asset issuing authority for serialized assets was not able to be split from the base or “master” asset. That would seem to solve this issue.

1 Like

Actually, each serialized token will be issued in a LOCKED state with a count of 1. So, the issuing authority can’t be transferred. Only the master asset issuing authority can ever be transferred.

This reminds me that we should specify that if the master asset is LOCKED, serialized token issuance for that master asset should be disallowed.

Issuing authority can be transferred post lock, and tokens can be updated post lock. All lock does is prevent further tokens being issued.

Right?

I like the idea but will play devil’s advocate for now:

  • Has any real project voiced any real interest in this?
  • Why not just use a script to issue, say, 300 numeric assets, each with one indivisible token? Sure it takes 300 btc tx fees, but isn’t this a welcome anti-spam measure anyway?
  • Or, of course, if willing to pay 300x0.25 XCP fee can do this with subassets
  • Deweller’s technical outline is impressive but won’t the ease of issuing so many assets make too high a DB impact?
  • If asset ownership (issuance right) vs token ownership causes confusion, one can always lock the issuance at zero and have the transferable issuance right signal ownership.
  • Alternatively; issue one token and transfer the issuance right to a burn address.
  • Tokenly is interested in this for token.fm and our other projects in a variety of ways.
  • We actually had intended to do exactly this, but there are downsides - Mostly in that these assets won’t be grouped at the protocol level, so compatibility will be limited outside of Tokenly’s ecosystem (Or whomever creates that script and does the front-end work to support it)
  • 300 subassets would run, at current prices, about $975 in BTC tx fees and XCP fees, vs. maybe $250 in btc tx fees alone with a non-protocol level system - That is too much if we want people to use this rather than just building non-standard layer 2 systems to accomplish this same thing. I like the .001XCP per unique.
  • Every time an asset moves from one address to another, you’re increasing the size of the database almost as much as you are by creating a unique token type. If counterparty is going to succeed, it’s going to get a lot bigger and companies/projects using it will have to become more efficient at dealing with counterparty as it grows.
  • I don’t think this is a real concern? We’ve literally never had anyone we deal with get confused between someone who owns the token vs. having a zero balance but issuing authority.

This would have been a good use case for EVM smart contacts.

I think this approach is fine and lightweight.

Though @deweller approach works, I too have this gag reflex when I see too many assets being created for things like this. But it would work so I cannot technically argue against it unless it is proven to cause performance problems in the long run.

@deweller can you go a little deeper as to why you think your approach is better than @jdogresorg’s ?
What is the big benefit, if any? Just a design preference?

Thanks!

My main reason is that is significantly simpler to implement using numerical assets. Very few parts of the system need to change.

@jdogresorg’s approach is probably how you would do it if you were starting from scratch. But the amount of complexity with that approach now is prohibitively large in my opinion.

Bringing this topic back to the table as I’m working now on non fungibles.

As @deweller said, the best approach is to issue numerics with asset_longtext for serialized assets. I’m creating a system where the user buys a non fungible token and my current implementation follows these steps:

  • When payment for a specific token is received, issue the token as a subassets. Emission of 1 non divisible token of the form PARENT.number
  • When the subasset gets confirmed, send the token to the buyer. Ownership also gets transferred.

We won’t be locking issuance as we’d like some peeps to issue copies of their serialized assets if they want, so yeah this could be optional.

Analyzing this, as @sull said this could be a perfect fit for a VM on-chain, even with high tx fees, as it would lower the BTC tx fees considerably into just one step.

1 Like