Suggested modifications to the card specification + Asset Type and Network specifications

I think it would be helpful for the community to start discussing creating a specification around networks and asset types. The goal is to ensure that terminals follow the same specification when creating and validating phonons. My ideas are:

  • In the phonon specification:

    • rename the field “CurrencyType” to “AssetType”. I believe this name better represents the ability for phonons to manage digital assets such as NFTs.
    • Add the field “NetworkId”. A number that identifies which network the asset is located.
    • remove the “ValueBase” field. I believe this field should be removed to reduce storage needs. This is the responsibility of the terminal to manage.
  • Publish a network and asset type lists to a public github that map the “NetworkId” and “AssetType” fields of the phonon specification to readable names.

  • Publish a specification defining the expected tags for each asset type.

Examples

Network List

[
  { "id": 0, "name": "None" },
  { "id": 1, "name": "Phonon Network" },
  { "id": 2, "name": "Bitcoin" },
  { "id": 3, "name": "Ethereum" },
  { "id": 4, "name": "Ethereum Rinkeby" }
]

Asset type list

[
  { "id": 0, "name": "Phonon Native" },
  { "id": 1, "name": "Chain Native" },
  { "id": 2, "name": "ERC20" },
  { "id": 3, "name": "ERC721" }
]

Asset Type Specifications

Asset Type Expected Tags
ERC20 ContractAddress: string
ERC721 ContractAddress: string, TokenId: number

Using the above specifications, Dai across Ethereum and Ethereum Rinkeby would look like

Network Fields Tags
Ethereum NetworkId: 3, AssetType: 2 ContractAddress: 0x6b175474e89094c44da98b954eedeac495271d0f
Ethereum Rinkeby NetworkId: 4, AssetType: 2 ContractAddress: 0x0165b733e860b1674541bb7409f8a4743a564157
3 Likes

It might make sense to use the identifiers for each network that are already widely supported, like those listed here https://chainlist.org/

I’m not sure where the authoritative source for that data would be found, but I think that using something like that would be much easier than trying to maintain a list ourselves.

I dont believe that will work because we need to be able to assign an ID to non EVM networks. For example Phonon Network for native phonons.

@douglance.eth, after thinking about your comment for a while I think we could use three attributes identify a phonon’s type

NetworkTypeId - Phonon, Bitcoin, EVM…
ChainId - Can be null. For EVM it would match https://chainlist.org/ as you suggested.
AssetTypeId - Native, ERC20, ERC721

NetworkTypeId ChainId AssetTypeId
Native Phonon Phonon(0) null Native(0)
BTC Bitcoin(1) null Native(0)
ETH EVM(2) 1 Native(0)
Arbitrum ETH EVM(2) 42161 Native(0)
DAI on ETH EVM(2) 1 ERC20(1)
DAI on Arbitrum EVM(2) 42161 ERC20(1)

@hinchy : we’ve discussed offline, and this makes sense to me, categorically.

One clarification regarding the data structures within the categories (and apologies if as presented the definition is self evident, and I’m just ignorant of the syntax). Would NetworkTypeID and AssetTypeId be strictly integers? For example, DAI on ETH. If I printed its NetworkTypeId, ChainID and AssetTypeID, would it print 2,1,1? And then we would have a map or something that would tell us which type it is (in this case ERC20)? Or is there a datatype that represents two dimensions?

Yeah so DAI on ETH would be 2, 1, 1. It is then up to the terminal to know that an AssetTypeId of 1 represents an ERC20 and that it needs to extract the contract address from the phonon’s metadata. Let me know if this doesn’t answer your question.

Yup. Strap me in. Ready for launch. By the way I think @deviator plans to chime in this week sometime.

1 Like

I like the 2nd iteration the best. because when users redeem their backed assets to chain, we would need the chain ID to know which to interact with.

Any for Bitcoin’s situation:
Bitcoin
Bitcoin Cash
Bitcoin Satoshi’s Vision
In my opinion should all be separate and not listed like chain IDs

1 Like

So in general I’m massively in favor of the general idea of this proposal.

I’ll start with a description of the relevant fields from the current Phonon spec data structure to provide some context as to the differences between this proposal and what’s currently implemented. I’m describing the current master branch of the phonon-client repo here, I suspect the phonon-network specification may be a little out of date.

We currently have the following:
CurrencyType: A uint16 identifier for the type of blockchain asset.
ChainID: An int identifier for the specific blockchain instance to contact
Denomination: The value in chain base units contained within this phonon

Current examples of CurrencyType are the following, from model/phonon.go:

type CurrencyType uint16

const (
	Unspecified CurrencyType = 0x0000
	Bitcoin     CurrencyType = 0x0001
	Ethereum    CurrencyType = 0x0002
	EthereumERC721 CurrencyType = 0x0003
	EthereumERC20 CurrencyType = 0x0004
)

So as compared to the proposal above this data structure basically comprises a combination of NetworkTypeId and AssetTypeID within one identifier. A uint16 gives us 65536 potential contract types across all blockchains that we could support.

The reason I like this as one field instead of two, is that this field is the data that must be used by the client to provide instructions on how to process the phonon during on chain interactions, e.g. deposit, validate, and redeem. Since ETH and ERC20 require distinct processing instructions, they would have distinct CurrencyTypes in this model.

I guess I could see grouping all contracts from a single chain type together, because then you could provide a class that handles that chain, sharing some common functionality even among distinct contract types, but in practice that can also be accomplished by assigning multiple CurrencyType’s to be handled by one ChainService. Either way, you have to have some internal logic and switching on ID to handle different contract types on the same chain, or contract types vs native.

In a nutshell, I’m not sure it’s worth incurring the cost of the code change on the card to split CurrencyType into two fields, because I don’t think it allows us to simplify the code any further. I’m willing to change my mind if there’s some benefit I’m not thinking of here.

However, I definitely like the name AssetType better than CurrencyType, so I am in favor of switching that name throughout the codebase. As hinchy mentioned, it describes the potential for NFTs and other types of assets much better.

On chainID, this basically provides an ID that can be used as a switch to use different endpoints in the ChainService implementation, I think we’re in total agreement on the necessity of this field. This was added along with the initial redeem functionality several weeks ago.

On ValueBase aka Denomination, this field is currently included in every phonon because it theoretically allows the card to process the value to do filtering as a performance optimization before returning results to the terminal. This isn’t currently implemented but could be important when there are large numbers of phonons on cards.

It is not ideal that these bytes can be wasted on valueless AssetTypes. In practice though, even ERC721 NFT phonons will have an ETH balance tied to the same key used to pay gas during contract calls, so I expect this not to go to waste very often, plus it’s only 2 bytes, so there are other places to optimize first.

Keeping the uint16 CurrencyType, now renamed AssetType, this makes the requirement for defining a new Phonon Asset the following, which is very similar to what was proposed above.

AssetType: A 2 byte ID used by the client for selecting an appropriate chainService when interacting with this phonon on chain.
AssetName: A human readable name for the asset
Tags: Data additional to the standard phonon fields needed for interacting with this asset type.

All phonons would also have the standard on card data fields including ChainID, PubKey, and Denomination.

A ChainService implementation for this new type would then have to implement parsing the extended tags, connecting to the correct endpoints for each chainID, and processing Deposit, Redeem, and Validate for this asset type.

2 Likes

Thanks for the in depth reply @deviator.

Thats fair. I think the main advantage is instead of having to map Ethereum & EthereumERC721 & EthereumERC20 to “EVM” you only need to map the one networkTypeId. This is work that will be duplicated across every terminal. That being said I have no idea of the effort involved. Totally agree it might not be worth the effort.

Gotcha. I think I got confused between Value Exponent and Value Base. When filtering phonons is Value Exponent required?

Yes ValueBase and ValueExponent are both required. It’s a little data structure we cooked up to store values as efficiently as possible while allowing for enough granularity for effective fixed denomination transactions.

Basically the Denomination (made of up Base and Exponent) is given by this equation:

(ValueBase * 10 ^ ValueExponent)

Filtering on card can be done without reconstructing the actual number, since Javacard has difficulty representing values this large which would usually be handled by a BigNumber library of some kind in higher level languages.

Card will likely filter like this:

if TargetExponent > ValueExponent { 
  Target is greater 
} else if TargetExponent < ValueExponent {
  Target is less 
} else if TargetExponent == ValueExponent {
  compare the base
  (repeat structure with TargetBase and ValueBase)
 }
1 Like