Introduction
The RDX Works development team is considering the possibility of extending the Radix Network’s native Pool component to include not just today's fungible Pool Unit tokens, but NFT-based Pool Unit tokens for use cases not well served by the fungible kind.
There are certainly clear use cases for NFT-based Pool Units, but it’s important that the design be as flexible as possible, while still providing the user-level guarantees that are the ultimate purpose of native components and resources.
The RDX Works development team wishes to gather feedback on the use cases and needs where NFT-based Pool Units might be used to inform that design. Your feedback on your real use cases is highly desired!
The Purpose of Native Resources
One of the big goals of Radix is giving users more confidence when they use DeFi and Crypto, and a major aspect of that is confidence in the assets they hold. On other smart contract networks, users often are confused (or even scammed) by the assets they hold because they have no guarantees at all about what a given token is, how it can behave, or what it can be used for.
Radix’s resource-based asset system nicely answers the first two questions – what a given token is, and how it can behave. All Radix resources have a clear and objective definition that a wallet can directly read, including whether it is fungible or non-fungible, and who (or what) is able to authorize minting, burning, withdrawing, depositing, recalling, or freezing it. This already allows the Radix Wallet to more clearly display, classify, and explain the behavior of any asset the user holds.
But it is also useful for resources to provide an objective definition of what they can be used for – at least in cases where there is a common pattern of usage that can be explained and understood by the user.
This is the purpose of various native resources that are included in the Radix Network, which are created by an associated native component (defined by a native blueprint package built into the network). Most prominently, this includes Liquid Stake Unit tokens and Stake Claim NFTs (created by a native Validator component), and Pool Unit tokens (created by a native Pool component).
The advantage of having these native, built-in resource and component definitions is that the Radix Wallet – and any other application – can fully rely on the purpose and meaning of these resources. This means they can be safely categorized and displayed uniquely, and reliable guarantees can be made to the user about what they mean.
The goal is not, however, to create 1000 native resource types for 1000 individual use cases. The intention is to add native components and resources only when two criteria are met:
- When the asset and component definition is general enough to cross over between many application types
- When it is possible to give users useful meaning for the asset in a way that is objectively guaranteed
When these two things are true, the value is high in creating a native implementation, and updating the Radix Wallet and other tools to understand and interact with it. These native implementations can meaningfully make the user experience more clear and safe for many applications they may interact with.
The Desire for an NFT-based Pool Unit
Pool Units fundamentally exist to represent redeemable value from the Pool it is issued by. With today’s fungible Pool Units, that redeemable value is a completely fungible share of a combined pool of assets. Every contribution is the same: it is a percentage of the pool, and the Pool Unit that is returned represents that percentage. This is quite flexible because it says nothing about what the pool may be used for by the application – only that a given quantity of Pool Units represents a certain percentage of whatever is in there.
However, this model doesn’t work when different contributions are not the same. In this case, an NFT is a natural fit because it can represent whatever was unique about a particular contribution. Those unique parameters can be written into the non-fungible data on the NFT (or perhaps stored in a hashmap against the NFT ID within the Pool) and used to determine things like when it can be redeemed and for what underlying value.
So the question is this: Is there a form of NFT-based Pool Unit that can meet the two criteria described above?
Can the implementation be made to enable a wide range of applications that desire it?
Can it provide strong guarantees about the meaning or value of the Pool Unit NFT?
What Does an NFT-based Pool Unit Mean?
This is more complicated than it might seem. A simple form of NFT-based Pool might simply take whatever quantity of fungible Pool Units it would normally mint and instead write that number into the non-fungible data of a Pool Unit NFT. When turned in to the Pool to be redeemed, it would return the proportional share of the Pool assets, just as today. Logic could even be included to enable partial redemption (resulting in re-issuing a new NFT indicating a smaller share).
Then each application using an NFT-based Pool might write whatever other unique data it wants to the Pool Unit NFT before providing it to the user.
However, remember that the reason we’re using the NFT in the first place is that the unique data written to it matters to its meaning. That data might determine a variety of things, like:
- A specific time after which the NFT can be redeemed for its pool value
- A changing redeemable value based on time
- An association with a specific redeemable value for just that user, not a shared pool
- A specific “position” with complex application-specific calculated value
If the goal is to provide strong guarantees to users about the meaning and value of the asset, then these details change that meaning and value to its holder.
That means that the Radix Wallet should have access to objective guarantees about that meaning and value, if it is to show it to the user. If those guarantees can’t be provided, then the reason for having a native implementation rapidly vanishes.
Call for Feedback
Today’s fungible pool unit token may always be redeemed for its proportional value from the pool. But if an application is using unique NFTs that each determine specifics like when it can be redeemed, and for how much value, what objective guarantees can be actually provided to the user? Can such guarantees be provided without implementing 100 different Pool variations for specific use cases? Is there a lowest common denominator? Or is the best that can be done to show the user “here’s the data written to this NFT, but only the dApp can tell you what it means?”
Answering those questions is why the RDX Works development team needs your feedback.
It is important to understand the real use cases where NFT-based Pools might be used, and specifically what the NFT represents in those use cases. With that, perhaps a common denominator can be found that is both flexible and helpful to users. The team has already gathered some input on this from the community, but a more complete view is desired.
Respond to the Call
The request for feedback is now closed.
Summary of Results
Thanks to those who responded!
We heard from a variety of applications like DEXes, NFT marketplaces, and more. And actually there was some pretty consistent feedback about why NFT-based pool units would be valuable and how the developers would expect to use them. We might summarize with these two points:
- I want my users to have objective guarantees about the redemption value of the NFT I issue
- I want my application to provide an arbitrary and realtime definition of what can be redeemed using the NFT
This makes absolute sense. The sort of guarantees described in point #1 are a large part of why we would consider any native component or resource. And there is such a diversity of application types that the application logic really needs to decide - realtime - what "redemption" means and when it can be done.
Unfortunately these two things are in pretty direct opposition. #1 says "the wallet needs to be able to 100% trust what the native component says about redemption" and #2 says "the application needs to have 100% ability to tell the component what redemption means".
So what's the conclusion?
Well, an NFT-based pool units are not going to be a simple thing to add. There is just too much diversity in how a given defines the meaning of that NFT. And that diversity is a good thing! We shouldn't constrain application thinking with a narrow definition of a native component.
There may be another way though. We cannot give up point #2 - it's too important. But maybe we can cautiously look at #1. Perhaps rather than requiring an absolute guarantee, we can allow an application to declare a redemption value according to its own logic. Of course the wallet absolutely cannot present that in a guaranteed way – for example, the way we show the redemption value of LSUs or today's simple fungible pool units. But perhaps the wallet could show something like a "dApp declared value (not guaranteed)". We should make it very clear to the user that they are trusting the dApp not to lie, to avoid this becoming a path to exploit users. But this might be a way to give users that useful visibility in the wallet.
The likely way to do this would be an interface standard rather than a native component. For example, perhaps we set the standard that an NFT's metadata could include something like a `redeemer_component` and the wallet would expect to find, at that component, a `get_current_redemption_value` method that could be passed the NFT's global ID and return an untrusted declaration of current value. We could also define a standard `redeem` method interface for redeemer components, allowing the wallet to attempt to build and submit a redemption transaction right from within the wallet. Again, the dApp could have this method do something totally different than the expected redemption, or it could do nothing at all, but the transaction manifest would make this plain to the user.
This would be a somewhat different direction for how the Radix Wallet presents information to the user, and not to be done lightly. And there would be some non-trivial work in wallet and gateway to enable this in a good, efficient way. But it's something we'll be considering.
If you think this sort of approach would work for your application, sound off in Discord and let us know!