FA2.1 / FA3 - It's time

Yeah that would be great, if so it would be nice if it has support for multiple royalty receivers, ie, split royalties.

2 Likes

We need a token standard for token issuance on sidechains and layer2 protocols that are to be introduced.

Since most of the derivatives contracts have maturity periods, it would be great if we have a token standard for tokens with an expiry. ( So the burn will happen automatically on the expiry date/block thus preventing the accidental burning of tokens)

Wrangling metadata on-chain can be awkward with present standards and Michelson language features. Many NFT projects default to putting metadata on IPFS - makes sense if the NFT is signing a large JPEG that you’re storing on IPFS anyway, but makes less sense for things that can live on-chain like procedurally generated works (cf artblocks.io on Eth) - where introducing an IPFS dependency is undesirable.

One thing that I have struggled with building my contract, for example, is how to assemble JSON on chain. Currently I am basically preparing fragments of JSON off-chain and assembled a JSON string in the view from fragments with roll-your-own nat to string / address to string code.

This part of an NFT standard needs to be fully generatable in a view IMO - that means improved language support from Michelson for building JSON strings (see my post in Research and Development), or a move away from (nested) JSON structures as the metadata format.

6 Likes

Hi, there also needs to be a clear way to identify the kind of Token the contract is dealing with (Fungible, Not fungible, Hybrid, …).

We have had the issue in a recent project where an exchange contract needs to decide on which (fungible) side of the offer fees are taken. Since now everything is FA2 it is hard to decide.

It could be solved with a kind of “magic number” a bit similar to IEP165

2 Likes

I have two suggestions:

1 - token standards on Tezos should be approached in a more modular fashion. FA is a beast right now, and if each iteration leads to more features, then FA4 or FA5 will be massive and impossible to maintain. Rather, these ideas should be built out in a modular fashion. For example: let’s say royalties is important, that should be a single focus, and it should not require a whole new FA version, but instead a set of functions that can be optionally attached to the base FA standard if the developer chooses. This is something I’ve been enjoying about ETH/Solidity.

2 - I feel royalties specifically are important, as Tezos has been a chain that is primarily NFT and art/creator centric compared to others that might be more about DeFi/games/etc. So I think it’s worth putting energy into solving royalties specifically, rather than trying to solve all the problems at once.

To solve royalties in a way that covers a wide range of uses, I would propose something similar to EIP2981, but providing multiple beneficiaries/splits. For example, royalties on each resale could be distributed to 5 different charities, each weighted differently. This should be on-chain, to facilitate on-chain splitting, rather than in metadata/JSON.

An example of how it could look, but in Sol:

And like rognierbenoit suggests, there should be a simple way for contracts to detect whether a token supports this interface.

I think a good first step would be to define a simple example of how this would look in a token, and show how a marketplace (like alternative to HEN Marketplace contract) could take advantage of it, rather than relying on their own royalty stores.

10 Likes

KStasii from Madfish did an interesting blogpost about a new token standard:

There are almost no projects built on the blockchain that can be developed without tokens integration. They are essential entities in the crypto world. Different chains create their own token standards that match their peculiarities the best. The token standard design impacts how quickly the system can grow and how quickly other protocols can be implemented.

This article describes two Tezos token standards, their strengths and weaknesses, and how their limitations can be addressed.

FA1.2

FA1.2 is the oldest token standard that was developed at the dawn of the Tezos ecosystem and proposed in the TZIP-7. It was designed as the closest analog of ERC20, with the smallest adoption to the platform reality.

The standard defines the rules for smart contracts that represent the ledger for single assets and the entrypoints to interact with them.

There are 2 regular methods and 3 view methods mentioned in the TZIP:

(address :spender, nat :value)                %approve
(address :from, (address :to, nat :value))    %transfer
(view (address :owner, address :spender) nat) %getAllowance
(view (address :owner) nat)                   %getBalance
(view unit nat)                               %getTotalSupply

approve allows the spender to spend value tokens. Only the owner can allow someone to spend their tokens, which may not fit in with someone’s business logic.

transfer allows the transfer of assets from one account to another; however, only one transfer can be made per call, which makes multi-transfers expensive.

The view functions are simple methods that, instead of updating something in the contract, create the operation that sends the response to another contract. Only the total supply and the user’s balance and allowance can be requested in the standard way.

So, the standard has many disadvantages:

  • Only single assets are supported;
  • There is no way to implement custom logic for the approval (e.g. when it can only be done by the contract admin);
  • There is no storage specification;
  • View methods are just the methods that return operations (fake views);
  • Batch transfers aren’t supported;
  • here is a lack of infinite approvals;
  • Metadata isn’t specified in the standard.

FA2

FA2, introduced in TZIP-12, was designed to mitigate some of the above issues. The standard is very adaptable and allows the creation of single and multi-assets, and fungible, non-fungible, collectible, or hybrid tokens.

There are 2 regular methods and 1 view method specified in the TZIP:

(list %transfer
  (pair
    (address %from_)
    (list %txs
      (pair
        (address %to_)
        (pair
          (nat %token_id)
          (nat %amount)
        )
      )
    )
  )
)
(list %update_operators
  (or
    (pair %add_operator
      (address %owner)
      (pair
        (address %operator)
        (nat %token_id)
      )
    )
    (pair %remove_operator
      (address %owner)
      (pair
        (address %operator)
        (nat %token_id)
      )
    )
  )
)
(pair %balance_of
  (list %requests
    (pair
      (address %owner)
      (nat %token_id)
    )
  )
  (contract %callback
    (list
      (pair
        (pair %request
          (address %owner)
          (nat %token_id)
        )
        (nat %balance)
      )
    )
  )
)

transfer allows the transfer of assets from one account to another. Batch transfers are supported: a few assets can be transferred from a few senders to many receivers.

update_operators allows the spender to spend any amount of the tokens of some user. Many approvals can be done per transaction.

balance_of is a callback view to receive the balances of some users. The operation can return the balances of many tokens and users.

The standard also describes the token metadata format. The balance update rules are also mentioned but are not obligatory.

Although the standard is more complete than FA1.2, there are still some disadvantages:

  • Only infinite approval is supported;
  • There is no storage specification;
  • View methods are just the methods that return operations (fake views);
  • There are no views for supply metrics.

Protocol Changes

There were a few cool perks introduced in Hangzhou.

Timelock allows the user to send a transaction whose content won’t be seen for some time. Michelson on-chain views makes view-only interactions between contracts easier. The global constants table allows some Micheline expressions to be stored globally and then be found by the hash and used by any contract.

So, it would be nice to reflect these changes in the token standard.

Discussion

As the key solution to approach the protocol changes and dev experience improves, the new token standard can be considered. The main discussion around it takes place on Agora. However, it is not very active.

Long story short, it has been proposed that the standard should have the following features:

  • Supports transfer_and_call mechanics;
  • Supports views;
  • Has the global table of constants;
  • Specifies and has views for supply metrics;
  • Supports finite allowances;
  • Supports tokens with expiries;
  • Supports non-transferable token functionality;
  • Integrates tickets;
  • Implements privacy features;
  • Supports upgradeability mechanics;
  • Supports allowance for flash-loans and subscription models;
  • Is compatible with state-channels, ZK-rollups, and optimistic Rollups;
  • Has optional royalties support;
  • Integrates TZIP-17.

Essentially, an all-in-one token.

I also tried conducting a survey on the dev slack channel and only got 5 eye reactions () and no responses (what engagement, lol). So, I ended up discussing it with the MadFish team.

The main goal was to ascertain whether there are any issues relating to token standards that make development painful and hence, whether there is a need to create a new standard. Finally, we agreed that the main problem is the views that aren’t really views but rather methods with callbacks. We deserve true views integration but developing a new token standard and integrating it into the existing infrastructure seems to be too tricky.

Suggestions

In my opinion, the standard should be as simple as possible and shouldn’t cover everything in the world. It should only specify the payment and assets management logic and be easily extendable by other standards. So, the specification for flash-loans, privacy, tickets, obligatory TZIP-17 integration, royalties support, etc., seems to be redundant in the token standard and should be proposed in separate TZIPs.

I like the idea of creating a new perfect token standard, which would basically be an improved FA2 token with true views and some obligatory cool perks, but I consider this to be unrealistic.

What seems to be realistic is a standard that extends the FA2. This means that new TZIPs can be proposed that can be followed in future FA2 tokens. The tokens that will be implemented according to it will be still compatible with all protocols that support FA2. Let’s look at the additional features.

Compatible with FA2

All the requirements for the FA2 standard must be implemented.

Extended with obligatory views

The views are referring to the views introduced in Hangzhou

The token that supports the new standard must implement the balance_of view with the same signature as the method balance_of . get_total_supply returns the number of tokens currently in circulation. get_max_supply returns Some(max_supply) if the token supply is capped and None otherwise. get_supported_standards returns all the supported standards; it can be used to ensure that the token supports tickets, permits, or the flash loan standard.

Enable transfer and call functionality

Support is the method that allows a user to transfer tokens and then “notify” another contract. The method “implementation” resembles %transfer with the only difference being an extra parameter %callback – the entry point of another contract that will be called.

(pair %transfer_and_call (contract %callback unit)
  (list %transfers
     (pair (address %from_)
           (list %txs (pair (address %to_) (pair (nat %token_id) (nat %amount)))))))

Support finite allowance

The token must implement the %approve method that allows it to give the approval to spend a fixed amount of tokens. The method works for all types of tokens (fungible, NFT, collectibles). The method must not fail if the approved amount is higher than 1 in the case of NFTs.

(list %approve (or (pair %add_operator
     (address %owner)
     (pair (address %operator) (pair (nat %token_id) (nat %amount))))
  (pair %remove_operator
     (address %owner)
     (pair (address %operator) (pair (nat %token_id) (nat %amount))))))

Summary

In summary, I believe that we need a new standard that would extend the TZIP-12 and make it more dev-friendly.

The main features that should be introduced are:

  • Support of views:
    • balance of the user
    • user operators
    • total supply
    • max supply
    • supported standards
  • Support of transfer_and_call mechanics
  • Support of finite allowance.

Actually, as far as the standard goes, it is pretty simple. Someone can create a tool that wraps the existing FA2 tokens into the FA2 that implements the new standard. So, the new protocols will only need to work with the newest tokens.

6 Likes

I agree completely! Storing JSON metadata on-chain is very awkward at the moment (especially with nested JSON), and likely one of the reasons it is so rarely used. Views do seem like a nice solution here?

1 Like

FA God-mode - Full custom foreign accept/reject logic for the transfer operation

I have given some thought to how to implement a sort of “god-mode” for token minters/rights administrators, while at the same time making transactions relatively safe for buyers.

This is how I imagine it could work:

  • An FA contract entry-point e.g. %transfer_fa3 would take a new list parameter - expected_ops - which represents the operations that the caller expects the contract to perform.
  • The purpose of expected_ops is to implement a handshake between caller and callee to determine whether or not they agree on the operations.
  • To determine if the expected_ops list is correct %transfer_fa3 would call a view on a contract that implements the verification logic. (The contract and view is configured by the token rights administrator.).
  • On approval from the foreign view %transfer_fa3 adds the operations in expected_ops.

So far this should be enough as long as the front-end knows the logic of the foreign contract view. However, to implement fully customizable logic I propose the following:

  • To ‘learn’ the requirements of the custom logic the %transfer_fa3 entry-point has another boolean parameter simulate_transfer, which is also passed on to the custom view.
  • In simulation mode the foreign contract view must build a string of the expected operations, put it on the stack and end execution using a FAILWITH.

The FAILWITH reveals what operations the custom logic expects. It is then up to the UX/UI to display that to the user in a readable format. In an advanced UI implementation the front-end could initiate an unpermissioned simulation.

Some backwards compatibility would be possible through a wrapper contract or entry-point that emits the correct expected_ops - however in this implementation the contract operations are emitted by %transfer_fa3 which is non-compliant.

There are a couple of catches; mainly that the rights of the buyer/collector may not be obvious. He/She can see what he needs to pay to obtain the token, but can not see the requirements of a second transfer. One consequence could be ‘cursed tokens’ which you can not remove from your wallet, so the FA contract should always allow burning the token. Another consequence is that the token owner may be limited by the contract in where/to whom he can sell the token. I propose that there is a configurable time period, maybe up to a maximum of 75 years after minting, whereafter the token owner can freely trade and transfer his tokens anywhere. There are probably many more concerns about the buyers that should be visible in the token contract through permission bits; however that is a topic for a deeper discussion as there a lot of details I have omitted.

There are a lot of things that need to be worked out for this scheme to work, for now I would be interested to hear what people think about the core idea?

This is to put the power in the hands of the token creators and let them decide how their token is used. All in the spirit of decentralization.

2 Likes

Thanks @KStasi for this summary , we needed it!

Concerning the transfer_and_call I have the impression that two things are missing:

  • a data field in bytes format to be able to tell the target contract why it is being called
  • the target contract must receive all the information about the transfer that led to the callback.

On the topic of the new specification, which I will call FA++, so we don’t mix it up with the FA3 in my previous post, and that we have an independent conversation.

I fully agree with the point on @mattdesl about modularity.
There are many issues with a standard that will contains all possible functionality. First of all, the standard will need to be updated every time one of the functionality needs to evolve. We may end up with a lot of standards, which is not good.
The standard will be more complicated to understand and implement.
And, when I will provide the implementation on Ligo, I expect users to just copy-paste the implementation in their project, or import the library. Then either they deploy it as is, with all the features that he doesn’t need. Or remove them/tweak them but then not be compliant with the standard anymore.

To sum up there is no “one token fits all need” and for this reason I think FA++ should be highly modular.
FA++ will just contains the minim for a token. That is a ledger and a tranfer entrypoint. possibly an on-chain view for the balance and token but that could be in other standards.
For the ledger, I’m not sure if we should have three possible types like in FA2 or only one. I think if we have one it will be suboptimal for anything other than multi-asset, or describe the ledger in separate standards, then they will be nothing left in FA++.
(notice that currently the transfert entrypoint is suboptimal in single-asset or NFT but is necessary to make all FA2 compatibles).

Then all other functionality, that is operators, on-chain views, integration view tickets, transfert and call, etc … could be in separate standard that are “plug-in” to FAx standards. A token would then be an union of those standards. And each standard could evolve independantly. Which means FA++ would probably stay around for a while.

For the modularity to works well, we probably have to pay attention about compatibility. Thus, FA++ should include what is needed to conect a token to a DEX.
So I believe only Transfer entrypoint and a few views. Maybe the Metadata? I would prefer metadata to be part of a separate specification like in FA2.

What do you guys think about this ?

1 Like

Hello guys,
I’m joining the discussion late. There are some interesting points raised here.

A point that has not been addressed yet is the deprecation of FA1.2?. A quick look over the standard leads to believe that FA1.2 is for FT and FA2 is for NFT, leading dev to create new FA1.2 token which I think is bad. People should use exclusively FA2. However some people prefer the FA1.2 due to the possibility to delegate only part of their stack to an operator while in FA2, we always delegate all of our stacks.

To avoid people using FA1.2 we may want to add this in a future FA2.1.

The other point is that the callback entrypoint should be replaced with views. Interacting with “Michelson view entrypoints” or “callback entrypoint” leads to potential vulnerability due to reentrance issues and exposure of an entrypont for the callback, that could be call by an implicit account.
For this reason, I believe that we want to upgrade FA2 quickly before any other discussion about a new standard. Just for people to stop using this.
This would be FA2.1. There may be some compatibility issues between FA2.1 and FA2 due to this last change. Then we may want to call it FA3 to signal this.

However, I want this change to be integrated quickly and I belive everybody would agree that using views instead of callback is a better design. And I also agree that we want a new standard with the other mentioned functionalty. Thus if we call this token FA3, I believe views won’t be integrated quickly because the community will discuss about the integration on these new functionality.

To sum up, I lack experience to have a clear opinion on weither such token should be FA2.1 or FA3, as their is pros and cons with both naming. Your opinion on this would be appreciated.

2 Likes

Major issue for wallets at the minute is lack of standardisation around metadata. Wallet users want to do all kinds of searching, sorting, grouping, filtering etc of tokens and NFT’s. But to this day the main indexers still don’t have a means of even saying if a token is an NFT or not. Wallets have to relying on hacky code and exception lists, while indexers are putting hardcoded data into their databases to manually “fix” such issues. This is not sustainable and causes a lot of delays in certain projects becoming fully supported.

With multiple “types” of tokens now possible, we need a standardised way to denote what they are (e.g. “token”, “liquidity token”, “nft”).

We need standardised ways to name different things. Have a look at any ETH wallet, you will see NFT’s grouped into sections like “Rarible” with a raribale company logo next to it, that users can expand. These are all hardcoded in tezos apps because theres no easy way to fetch these things. Sometimes you will get lucky and find a project that does expose these things, but it can’t be relied on unless everyone does it.

When discussing standards, the top priority needs to be talking to the major indexers and the major wallets to see what they and their users need. Making a new standard/features is meaningless unless it can be integrated in the way users want to use it

4 Likes

You right @simonmcl . The goal of standardization is to make it easy for wallet and dex to access any token and get metadata on them. We should have it accessible on the contract. I am thinking we need a place for constant on a Michelson contract. To identify data easily but also have the guarantee that they won’t be overwritten

1 Like

I upvote it. It’s great. When will we submit a new FA standard? I think it’s time to do it. The fake on-chain view on FA2 is not acceptable. We need improve it now.

1 Like

I dont know the current status about a new Token standard. If it is actually work in progress or nothing yet just talk on Agora? @veqtor started this thread maybe he knows more

Please don’t ruin FAs with all this bloat. You all are not looking for new “FA” standards but for new NFT-supporting TZIPs. Which is fine. Put them in TZIPs, another “FA” will be a huge pain in the ass for current and future Tezos developers.

Having to support both FA1.2 and FA2 is already a pain. Adding another or even FA2.1 will be worse. FA2 is fine for simple tokens as it is, FA1.2 is essentially rekt imo and shouldn’t be used, but new apps still choose it because of loose and unclear messaging from top devs.

What you really want is new TZIP standards. Look at Uniswap for example, they still exclusively deal with simple ERC-20s. As a DEX developer, I agree and will likely never support any “financial assets” past FA2 unless I really have to. Financial assets should be as simple as possible to allow for more complex interaction in base layer protocols.

We should be pushing modular TZIPs that can be optionally implemented to extend FA2. Not FA2.1, not FA3, not FA++, or God-FA.

And reaaally what yall are looking for is field-level standardization for token_metadata. That’s what everyone is already set up to read, and how the wallet or exchange knows to load the token image, name, symbol, etc. We have first-class support for it. So why not just make what we have better via TZIP? Tezos needs a core, base-layer FA that doesn’t get remade every 2 years.

Tokens do not need to do everything, developers should be shrewd enough to actually design their tokens well and choose what TZIPs to implement instead of relying on copying whatever boilerplate FA is posted in OpenMinter’s github. Heavy amounts of hand-holding will lead to this conversation happening again and again whenever a new protocol-level feature comes out.

As I see it, FA2s do everything necessary to allow simple token transfers, exchanges, management, and metadata storing. My request is that we keep standards clear of optional features.

This has been stated multiple times in this very thread, and folks need to accept it to move this conversation forward.

3 Likes

I can agree to most things but like @KStasi wrote in the Madfish Blogpost, support of views should be introduced. I dont know if possible but keep current issued FA1.2 and FA2 tokens but introduce a FA3 standard and with the introduction mark the others or at least FA1.2 as deprecated to use?

Is there actually some development ongoing for FA3 besides this discussion here?

Hello!

There’s not much I’d really want from an FA2.1/3. Here’s a short list:

  • allowances (for fungible multi-tokens)
  • relaxing the constraints on storage layouts (to allow for some more storage efficient token contracts)
  • clearly defined onchain views, ideally compatible with the FA2 offchain views so no one who just went that route gets retconned.
2 Likes

Unfortunately there is no standard way to separate nfts from fungible tokens right now when I make api calls to get all token. The only way to distinguish them is to use some heuristics, but they won’t be 100% accurate. I think something on token standard level to clearly separate this two would help many

1 Like