Another new Ethereum token standard is making the rounds: ERC-4907, which proposes a way to create “rental NFTs”. Exciting! So can Radix’s asset-oriented resources do such a thing? Are new Scrypto / Radix Engine features needed to enable it?
As with soulbound tokens, the answer is that the Radix way of creating assets already elegantly addresses the use case in a more intuitive, safe way – two ways in fact – without requiring a new token standard with a lengthy process of adopting it and rebuilding dApps and wallets around it.
What’s a Rental NFT?
In effect, the proposed ERC-4907 standard creates a new kind of NFT where the owner is able to let somebody else use the NFT for a period of time as if they owned it, while not actually transferring ownership. ERC-4907’s creators were motivated by the use case of a Web3.0 game dApp where an NFT is used in the game. This NFT might be very valuable and its owner might want to loan it to somebody for use while ensuring they don’t lose control of it.
“Use” of the NFT here just means that from the perspective of the user and smart contracts it looks as if they hold it in their account. (This point will be important to remember a little later.)
Of course on Ethereum, “holding” a token or NFT doesn’t work like you might assume. In reality, an NFT smart contract maintains a list of what addresses own which NFTs, with each owner having the ability to send a request to the smart contract to “send” the NFT by removing it from their entry in the list and adding it to somebody else’s. “Holding” a token just means that if you ask the smart contract who owns a given NFT, it tells you the corresponding address in its internal balance sheet. (Weird, right?)
So the ERC-4907 standard creates “renting” behavior by offering two ways of asking the smart contract who holds an NFT: you can ask it who the “owner” is and who the “user” is. When the owner asks the smart contract to “loan” the NFT to somebody else, that other person’s address is now listed as the “user” even though the “owner” didn’t change. The “user” has no powers to change who the “owner” is. As a convenience, a timer can be set for when the “user” reverts to being the same as the “owner”.
This is pretty weird when you think about it though. The standard is just redefining what it means to hold an NFT, and then expecting wallets and dApps to agree. Those developers must change their wallet or dApp logic to say “when I look up who holds this NFT, I’ll pretend it’s held by the ‘user’ and not the ‘owner’”.
This can lead to some very real confusion. Where exactly is the loaned NFT? A new wallet or dApp that has been built to fully understand the ERC-4907 definition of holding will say “the token is held by Bob, but Alice owns it”. A wallet or dApp that hasn’t updated, however, or that misinterprets the new definition, might think that it’s held by either Bob or Alice depending how they look at it. The creator of a game that interacts with the NFT must carefully write its logic to avoid breaking the game, or at least greatly frustrating a user-holder if the game denies that they have the NFT they’ve paid to borrow!
So how do we redefine what it means to hold an NFT to make it rentable on Radix?
Answer: We don’t, because that’s silly and dangerous.
Instead there are two much better asset-oriented solutions using Scrypto, depending on what you’re really trying to accomplish.
Solution 1: When somebody just needs to use an NFT they don’t own
Assets created using Scrypto on Radix work a different way – they’re features of the platform itself, not smart contracts.
In the asset-oriented Radix world, we’ve designed assets to behave intuitively like the real-world “physical” versions. Tokens and NFTs are actually held in real on-ledger accounts. This means that there can be no confusing double-meaning of “holding”. If we want to enable an NFT owner to loan it out, then possession of the NFT must really move to the borrower’s account.
Let’s go back and think about the problem we’re trying to solve. The use case here is a Web3.0 game where a player needs to call a game dApp and say “I have the right to use this NFT”. Currently on Ethereum this means the game dApp asks the NFT smart contract “does the player calling me own the right NFT?”. ERC-4907 adds a second way that lets the game dApp ask “can the player calling me ‘use’ the right NFT?” – where “use” just means another form of seeing if the NFT is “in their account” (even though it’s now kinda-sorta in two places at once).
Stripping away the weird Ethereum way of doing this, the dApp needs a form of proof that the player has the right to use the NFT in this transaction.
Scrypto already provides this capability in a much better way. The idea of proving ownership of an NFT (or any other kind of asset) in a transaction is very useful. In fact, as we talked about in a past article on soulbound tokens (definitely go read it), it’s the basis for Scrypto’s access control system where badges (a token used for authorization) are used to represent the rights to do things with resources and components. The holder of any token can produce a “proof” of it, an unfalsifiable representation of a token that vanishes at the end of the transaction. This proof safely shows any dApp that the owner of the NFT approves of its use there, without actually transferring it away.
So on Radix, the Web3.0 game dApp would be created in a different (and much easier and safer) way. Rather than talking to an NFT smart contract and asking about owner/user addresses, the game logic simply declares “I need to see a proof of the right NFT in the transaction”.
And when things are built this way, allowing somebody else to use your NFT no longer requires redefining ownership in a new token standard – or even “loaning” it at all. The owner needs to simply produce the proof – whether for their own use, or on behalf of somebody else.
They can do this transaction-by-transaction, in just one line in the transaction manifest (a unique Radix way of defining transactions that has other benefits).
If you want to allow somebody to be able to get “proofs” of your NFT for some period of time (perhaps for a fee), a simple component could hold the NFT and allow the borrower to ask it for a proof whenever needed, until time is up.
With Scrypto, there’s no need to define a new token standard, no need to carefully re-write dApp logic. And handling things like a timed return with a loaning component provides vastly more flexibility to set whatever sorts of conditions of borrowing you want because the developer isn’t limited by features frozen into the asset definition itself, as with ERC-4907.
Solution 2: When the borrower needs to really have the NFT
But maybe simply producing a proof of ownership isn’t enough for some use cases. Maybe you have a situation where the owner needs to truly transfer possession of the NFT to a borrower, let them hold it, and do anything they like with it unfettered – without the owner giving up their rights of ownership.
To create a better way of doing this in Scrypto, think about how this works in the real world. If I loan my neighbor my car, I physically transfer it into their possession so they can go drive it around. I retain the right to go knock on their door and say “hey, I need my car back, buddy” and regain possession because legally the car is still mine.
There is a legal authority here: the state or country that issues the car registrations defines who really owns the car and has the rights to reclaim it from anyone else. If push comes to shove, I can call a repo man (who may or may not be Emilio Estevez). They will go get my car back, whether my neighbor likes it or not, because that’s the nature of car ownership.
Fortunately, Scrypto lets us define things in these physically intuitive terms. Let’s go back to Scrypto’s access control system again. Scrypto resources support a feature called “recallable” that – if enabled – specifies who (or what) is able to pull the resource back from wherever it is using a badge. This lets the NFT’s creator define the “legal authority” to whom owners can appeal if they need to get their NFT back.
Though not yet implemented in the current release of Scrypto, doing this will be as simple as adding this one line when creating a resource:
.recallable(rule!(require(some_badge_address)), LOCKED)
If we want to make this fully automated, we can imagine a simple component that acts like a repo man. The creator of the “car NFT” type would give the recallable badge to the repo man component. Then, whenever a new car NFT is minted, along with it is minted a unique “car title NFT” – encoded with the ID of that newly minted car NFT. The repo man is programmed to reclaim car NFTs if presented with the car title NFT. Now the owner can hand their car NFT over to whoever they like, but they can always go back to the repo man, show a proof of their car title NFT, and the repo man will pull the car NFT back for them.
If you want reclamation automated on a timer (or using whatever logic you prefer), you can freely define that in the repo man component logic.
Once again, we avoid the problems of ERC-4907 (and every new ERC-style token standard on Ethereum and other smart contract networks). We have a system where there’s no need to define a new token standard, other dApps don’t need to re-implement any of their logic to work with it, and the NFT creator has much more power and flexibility because we haven’t frozen a particular set of “loaning” features into the asset definition itself.