algorand / go-algorand

Algorand's official implementation in Go.
https://developer.algorand.org/
Other
1.36k stars 474 forks source link

Add mutable data field on ASAs #5264

Open SilentRhetoric opened 1 year ago

SilentRhetoric commented 1 year ago

Edit 4-9-23

Following a rich discussion here as well as in Discord, it seems that the way forward with the NFT metadata use case, which precipitated the creation of this issue, will be to pursue data storage held & managed by an application.

The application could be part of an ARC-20 "Smart ASA" or otherwise, and the application managing data for an ASA could be unique or even a central utility app for storing token data on behalf of many ASAs.

The issue will be left for community input on the original proposal with the understanding that this proposal is currently unlikely to be implemented as originally described below.

Status

Algorand Standard Assets (ASA) have four 32-byte mutable fields which are intended to be addresses, although sometimes they are repurposed as in the ARC-19 standard.

However, in the event that these address fields are required for their primary purpose, there is no mutable field on an ASA that can be used to hold arbitrary data.

Additionally, current ARC-based token metadata solutions put data off-chain, which prevents on-chain applications from accessing that data.

Expected

To be able to store on-chain some mutable data related to an ASA.

Solution

A mutable ASA parameter that can hold 1024 bytes of arbitrary data. This field could be called "Note" for simplicity.

Populating this field would incur an additional minimum balance requirement increase of 0.4 Algo on the ASA creator account beyond the ASA creation MBR of 0.1A. In total, an ASA with a note field would require 0.5A to be locked in the creator account. (Edited to incorporate @jannotti's suggestion)

Dependencies

Adding 1024 bytes of data to ASA would have an effect on the maximum potential ledger size. The proposed MBR cost is intended to counterbalance that.

Urgency

Within the NFT community, there is a consistent theme of people wanting to be able to create configurable ASAs without having to rely on somewhat complicated approaches involving ARC-19 and/or another storage location such as IPFS given its performance issues.

Additional Considerations & Interactions

ARC-3: Conventions Fungible/Non-Fungible Tokens

ARC-3 puts asset metadata off-chain, typically on IPFS. ASA Note could enable metadata to be brought directly on-chain. This would have the benefit of reducing dependency on IPFS, which can introduce performance, cost, and centralized infrastructure issues.

ARC-19: Templating of NFT ASA URLs for mutability

ARC-19 again puts metadata off-chain, albeit in a way that the URL can be modified. ASA Note simplifies the process of editing the metadata URL in addition to the benefits mentioned above related to reducing dependence on IPFS.

ARC-69: ASA Parameters Conventions, Digital Media

ARC-69 is enables mutable ASA metadata but does so by relying on asset config transactions, which can only be fetched from an Algorand Indexer or similar service provider. Bringing metadata onto the ASA itself makes the metadata available on any Algorand node without the need for a partial/full indexer or even an archival node.

ARC-20: Smart ASAs

An ASA Note field would make metadata available to a smart contract that is managing the ASA, and so this proposal would strictly enhance the capabilities of "Smart ASAs" that are interacting with an ASA. Additionally, because data could be stored on the token itself, this could simplify tooling required to fetch & display information about tokens.

New Applications

One interesting capability achieved by attaching mutable data directly to an ASA would be that this information could travel with the ASA, wherever it goes. Whether the ASA is managed by a trusted entity such as an individual creator or company or trustlessly by a smart contract, an ASA with an on-chain Note could provide rich functionality in both the on- and off-chain ecosystem without requiring tools & dApps to handle the complexity of smart contract interactions (as in ARC-20/ARC-72) or infrastructure challenges of IPFS.

jannotti commented 1 year ago

I don't love the idea, as I don't think ASAs are the place for such data. But I don't feel all that strongly, so I'll just ask questions to make this work well if the community wants it.

How is this field manipulated? I guess that only the manager address can change it? And it's expected to do so by using an acfg.

There is a tricky case to handle here. Normally, when a field is empty, it is omitted from the txn. So, if we imagine a new field anote, and do things the way things are normally done, an acfg that omits anote would be interpreted as having set that field to "", thereby clearing it out when trying to, for example, set the FreezeAddress. Of course, all existing code that tries to change an address today will omit this field, since it doesn't exist currently.

So we would need to be careful about the meaning of a missing anote. I think it should mean that anote should be unchanged. However, if one did want to clear it out, they would want to send an empty (but present) anote field. That is also unusual, but can probably be dealt with.

Note, by the way, that all of this "omitempty" stuff applies to all the special ASA addresses, as well. So, for example, an acfg that only contains anote would clear all of the special addresses!

Would the minimum balance be incremented at ASA create time only? That is, if the anote is empty at create time, I suppose a manager can't come along later and set the anote, thereby incrementing the MBR of the creator? That would be a weird "action at a distance". (Which is also why I'm glad the proposal does not seem to ask for the MBR to change based on different sizes that anote may be set to later.)

Since boxes only charge 400µA per byte, I think maybe this should only be a 0.4A MBR increment.

SilentRhetoric commented 1 year ago

What if this was handled similarly to reserving global state for an application such that the ASA "Note" field must be initialized with a non-empty value and additional Note field MBR covered at the time of ASA creation? It could not be added later, thus avoiding the action-at-a-distance problem.

ASA Creation

ASA Update

ASA Update, where ASA does not have a Note field initialized

ASA Update, where ASA has a Note field

ctibo commented 1 year ago

Does that mean the anote could be read by smart contracts on chain? If so, that means we could build smart contracts that interact with NFT properties and traits! It would open up a whole new scope of on-chain interactions with ASAs.

For example, you could allow staking only for NFTs that reach a certain level.

LoafPickleWW commented 1 year ago

I really like this idea and I think it will help increase interoperability between SCs and ASAs.

jannotti commented 1 year ago

Does that mean the anote could be read by smart contracts on chain?

I presume that there would be a new field for asset_params_get, so you'd have something like asset_params_get AssetNote

ChrisAntaki commented 1 year ago

Would love to see this feature added

TommyAlex79 commented 1 year ago

Just a thought... if all we want to do is ensure that when getting one or more assets from the algorand indexer/conduit we also get a 1kb note, then this could be done at the indexer/conduit level, to make sure it automatically report the last acfg tx note, together with the asset(s), maybe only when a new option is present and set to true (i.e. last-acfg-note=true). This would avoid making a change at the blockchain level. It would also be backward compatible and support existing assets (i.e. Arc69).

I think for a change to the ASA at the blockchain level, we might need need something that is more general purpose and more flexible and ideally more consistent with other solutions (i.e. boxes).

SilentRhetoric commented 1 year ago

Just a thought... if all we want to do is ensure that when getting one or more assets from the algorand indexer/conduit we also get a 1kb note, then this could be done at the indexer/conduit level, to make sure it automatically report the last acfg tx note, together with the asset(s), maybe only when a new option is present and set to true (i.e. last-acfg-note=true).

This would avoid making a change at the blockchain level. It would also be backward compatible and support existing assets (i.e. Arc69).

I think for a change to the ASA at the blockchain level, we might need need something that is more general purpose and more flexible and ideally more consistent with other solutions (i.e. boxes).

To be clear, I am intentionally and explicitly proposing an on-chain attribute that would be available for smart contracts to interact with.

The proposal itself is agnostic of ARCs and backwards compatible with all ARCs. That said, it is easy to see how this capability would lead to the development of new, different, and/or more ergonomic NFT standards.

LoafPickleWW commented 1 year ago

If this gets implemented, I'll work towards getting a new ARC made for NFTs that allow for easily mutable images URLs and metadata and provide no code tooling to support it.

Included in the metadata as well can be preferred royalties from the creator that listing smart contracts can read it and have that royalty included in the sale.

This also opens up avenues for having ASA oracles for smart contracts to pull information and data from.

One word: Please 🙏

jannotti commented 1 year ago

If this gets implemented, I'll work towards getting a new ARC made for NFTs that allow for easily mutable images and metadata and provide no code tooling to support it.

Included in the metadata as well can be preferred royalties from the creator that listing smart contracts can read it and have that royalty included in the sale.

This also opens up avenues for having ASA oracles for smart contracts to pull information and data from.

One word: Please 🙏

This comment is exactly why I don't think this is a good idea. All of these things, especially images, are not going to fit in 1k. So at some point (soon!), we will be in a place that demands either a) solutions that are just like we have now, using an on chain hash to point at further data (which, if it must be seen on chain, can be done with a merkle proof) or b) an exact repeat of this request in a year asking for 10-100k of data.

Algorand has apps. We spend a lot of time figuring out how to make them suitable for the general purpose things being described here. Shoehorning into ASA is going to have compromise after compromise.

ChrisAntaki commented 1 year ago

I'm pretty sure @LoafPickleWW meant image URLs

LoafPickleWW commented 1 year ago

I'm pretty sure @LoafPickleWW meant image URLs

Correct, image URLs.

I think storing media on chain is a waste of space. Edited.

joe-p commented 1 year ago

An alternative to changing the protocol is setting the ASA URL to an appID that follows some specific standard for storing on-chain fields in box storage and point to IPFS for off-chain stuff.

SilentRhetoric commented 1 year ago

An alternative to changing the protocol is setting the ASA URL to an appID that follows some specific standard for storing on-chain fields in box storage and point to IPFS for off-chain stuff.

Yes, and...

I think this proposal has merit on its own because it makes ASA metadata a first-class citizen on chain, rather than requiring ASAs be associated with or managed by smart contracts with state and/or boxes.

It seems to me that ARC-19 and ARC-69 are both awkward work-arounds to achieve mutability due to this feature missing from ASAs in a native way.

Also, ASAs with their own mutable data would be strictly additive to the capabilities provided by a "Smart ASA" managed by an app, but native ASA Notes would also open up simpler possibilities in which additional on-chain data could enrich ASAs in various ways.

joe-p commented 1 year ago

Field mutability and on-chain metadata are related but separate issues. If you were simply proposing the option to have a mutable URL field I'd be all for it.

What your proposing here is a field with a large amount of data for token metadata. Regardless if it's mutable or not, I don't think it's necessary to attach large amounts of metadata directly to an asset. If we were to do this, we'd need to either

A is not ideal because there is a max size which users will inevitably want to circumvent, thus creating yet another standard.

B and C both seem like significant changes to how multiple things works (plus the field config problem JJ previously mentioned) which seems unnecessary since we have already solved the large on-chain storage problem via box storage.

By associating an ASA with app, we not only get box storage, which can be used to store metadata, we also get all the extra functionality smart contracts can offer on-top of ASAs. This also means any time apps get more features, ASAs associated with apps also get more features (opposed to needing to update ASA and contract functionality separately).

The most obvious objection to associating an ASA with an app for box storage is that it's not as simple to mint assets for new devs. I don't think we should be changing the protocol to address UX problems that can be solved at higher levels of abstraction.

The other potential problem with this approach is that to access the box storage associated with asset on-chain you need to pass both the asset and app in the foreign reference arrays, which might impact composability. I'd argue, however, that this is not a big concern given typical use-cases of ASA metadata and AVM9 with group resource right around the corner.

jannotti commented 1 year ago

@joe-p's proposal has merit and can be even simpler. There can be exactly one app that is considered the "ASA metadata" app. It can support "set" and "get" methods that take an ASA id, and a value.

If it's a set, it confirms that the caller is the current manager of the ASA given, and sets a box, named by the ASA id.

If it's a get, it returns it.

The details of giving the app algos to account for MBR and getting them back are not much harder. If you want the semantics described in the original proposal, the app would expect to receive the MBR when included in a transaction group that mints the asset, and return it if it's in a group that deletes the asset. In fact, this technique is more powerful, because we could have richer semantics that, for example, allow adding the metadata to be added later (even if the ASA already exists today), if done by the manager.

I think the idea of "first class" support is a distraction that tries to insinuate that a solution like this is somehow less powerful. It is more powerful, because it's far less constrained by annoying details of protocol development and backward compatibility. The whole point of expanding the power of apps has been to make stuff like this possible without changing the underlying protocol.

joe-p commented 1 year ago

Rather than having one app I think it'd be better to have individual apps. This allows the ARC to be much more modular. Maybe some creators want their ASA's app to implement interface X, some want to implement interface Y, and some want to implement both X and Y.

emg110 commented 1 year ago

IMHO, combination of ASC, ASA and box feature is very powerful when used by C2C calls and there is no specific need for an additional mutable field on ASAs (I used exactly this architecture for POAP mutable metadata that is being developed and it works ok). However, I think the asset URL field being immutable can be subject to change to match the real-world usage and context of URLs which may be subject to change. Having an Asset URL as a mutable filed would both satisfy those with requirements on having a mutable field right on ASA and at the same time have more compatibility with real-world usage.

cusma commented 1 year ago

Some arguments of this discussion resemble the points debated during the definition of ARC-20 (both here and on Discord). One of the main critiques/divergences over the ARC-20 approach at that time was somehow summarized by the question "Why having an ASA at all instead of just relying on Apps?"

This discussion over ASA mutable fields confirms the idea that in the community, despite all the growth and extension of AVM capabilities, there is still a strong demand of ASA as flexible, widespread and simple tokenization framework.

Therefore, all the consideration I'll made in the rest of this post rely on the assumption that the answer to the argument "Why having an ASA at all?" is: "Because the ecosystem still wants ASA".

This being said, the idea of a "Stateful ASA" has been in the back of my mind, expecially in the early days of Algorand, when the capabilities of the AVM where much more restricted than today and the ecosystem lacked ARC standards for NFTs. Upgrade of ASA fields already happened once to support NFT use cases: URL, in fact, were originally only 32 bytes long, than extended to 96 bytes to natively support IPFS CIDs.

Given the evolution we had at AVM level, and all the engineering efforts spent over last year or so to improve AVM and App state scalability, I think that today a binding between ASA and Apps would be much more powerful than changing the ASA protocol just to introduce a new mutable field.

The ARC-20 approach aimed to enrich ASA with two fundamental properties: more flexibility on ASA transferability rules and more expressiveness on ASA state. The first point has been obtained by abstracting and replacing the ASA "direct transfers" with ASA "request for transfer" processed by a controlling App. The second point is obtained with an on-chain binding between an ASA and an App, which could just be used as an extension of asset state (without enforcing the transferability rules through the Clawback binding).

Although ARC-20 does not mandate a way of binding an ASA with an App, ASA URL field (which I wished could simply be called metadata) seemes to be the best way to expose the ARC-20 ASA/App binding to the AVM.

Among the proposals made in this discussion so far to address the need of ASA extensibility, I would like to point out my preferences in decreasing order of desirability:

  1. Smart ASA - Leave ASA as-is, rely on ASA URL field to create a binding between the ASA and an App and reinforce tooling (like specific conduit or SDK) to improve the UX and the usability of Smart ASA. The PROs of this approach are: no upgrade needed at protocol level as long as taking advantage of App features and scalability;

  2. App ID ASA field - New uint64 static ASA field, exposed to the AVM among the Asset Params, and explicitly dedicated to the ASA-App binding. This proposal inherit the PROs of proposal 1. while avoids hijacking the URL field for exotic purposes;

  3. Mutable ASA field - Leave the ASA almost as-is, just making the URL field mutable by the Manager Address (or a new specific role address). One concern I would like to rise about this approach regards the meaning of the relationship between a mutable URL (maybe renamed just ASA metadata) and the metadata hash field, intended to be as an integrity committment of off-chain metadata linked in the mutable URL;

  4. Additional mutable ASA field - This is the solution I would leave as last resource: I think this approach would introduce deeper (and breaking) changes at protocol level as long as harder discontinuity on backward compatibility.

Bottom line: option 1 is the one I'm most inclined to.

joe-p commented 1 year ago

The benefit of ASAs is that you are solely relying on Algorand's consensus/L1 features for accounting and access control. Using a smart contract for things like accounting, freeze, clawback, etc (like ARC-0020 recommends) inherently introduces more risk especially for non-technical users and allows for deviations of the implementation. It also means more complex tooling, which is why I imagine it hasn't really been widely adopted.

Bottom line: option 1 is the one I'm most inclined to.

I agree, 1 is the most sane solution. If we were to add a new field, I would propose that this is a more general field that is optionally mutable.

The only problem with using URL to hold the app ID is that it can be a bit confusing, but for end-users this is solved at higher levels of abstraction (for example, explorers could say "App" instead of "URL" when it's an app ID).

SilentRhetoric commented 1 year ago

Following a rich discussion here as well as in Discord, it seems that the way forward with the NFT metadata use case, which precipitated the creation of this issue, will be to pursue data storage held & managed by an application.

The application could be part of an ARC-20 "Smart ASA" or a different implementation/standard, and the application managing data for an ASA could be unique or even a central utility app for storing token data on behalf of many ASAs.

For now the issue will be left open for community input on the original proposal with the understanding that this proposal is currently unlikely to be implemented as originally described below.

emg110 commented 1 year ago

IMHO, since the asset URL field is more effective to be mutable because the nature of ASA is immutable but the nature of URLs is to be subject to change because of relation to real entities like brands, company names, products, or services names..., I go with option 3.

This option (3) also satisfies and serves the better implementation of option 1.

Example thought experiment (only in case the ASA author needs the asset URL field to point to a specific URL on the web) :

Facebook issues an ASA on Algorand ---> ASA URL points to Facebook... ---> Facebook goes Meta----> asset URL cannot change---> lots of trouble keeping consistency because ASA needs to be re-issued

kcelestinomaria commented 1 year ago

Just to comment. I remember changing ASA fields was always rejected as a proposal as far back as in 2021-2022 by Algorand's core devs and AF team(I remember Fabrice stating that ASA fields will never mutable, only a select few). In as much as handling this mutability on the application side is great, one thing to note is that it does add a cost for the users interacting with these apps, this does make applications undesirable(speaking for non-technical users) to some extent in as much as it is necessary on a technical level, and so at the end of it all, if we take on a big picture we all get back to how fees can be managed/controlled by developers, probably guidelines on that would be a good idea?

Also, it's good to know that it adds new requirements for explorers being built on the network.

On the IPFS issue, yes IPFS is not scalable and actually has a cost beyond some data sizes. Maybe we can have an Algorand-based IPFS? If not, developers are still relying on "centralized services" like Amazon's S3 and Amazon Cloudfront, which honestly still do a good job, used solely or in conjunction with IPFS.