cadence icon indicating copy to clipboard operation
cadence copied to clipboard

Allow borrowing a concrete reference type to a capability linked as an interface type

Open joshuahannan opened this issue 1 year ago • 11 comments

Issue to be solved

In Cadence 1.0, with the addition of entitlements, references that are restricted to an interface type can be cast to the concrete type if it is known. Because of this, it would be nice to have the ability to borrow a concrete reference type directly from a capability that is only linked as an interface type instead of having to borrow and then cast.

The inability to do this may cause issues with some standard transactions. For example, many apps use a transaction like this one to set up an account based of only a reference to a generic NFT, without having imported the contract first. The transaction only links the new collection as NonFungibleToken.Receiver.

Many other transactions try to borrow the public collection as its concrete type though, ExampleToken.Collection. Because this isn't possible, many of these transactions would fail. If they were able to borrow it directly, then this wouldn't be a problem. This allows us to standardize more simple transactions that don't need boilerplate for borrowing as a reference before casting. We can always just borrow directly.

Suggested Solution

For a capability created like this:

        // create a public capability for the collection
        let collectionCap = signer.capabilities.storage.issue<&{NonFungibleToken.Receiver}>(
                collectionData.storagePath
            )
        signer.capabilities.publish(collectionCap, at: publicPath)

Assuming ExampleNFT.Collection implements NonFungibleToken.Receiver, the reference should be borrowable like this:

        // borrow a public reference to the receivers collection
        let receiverCap = recipient.capabilities.get<&ExampleNFT.Collection>(collectionData.publicPath)
            ?? panic("Could not get the recipient's Receiver Capability")

joshuahannan avatar Feb 07 '24 18:02 joshuahannan

We need to discuss this

j1010001 avatar Mar 12 '24 17:03 j1010001

Yes, this is very important to have IMO, but isn't necessarily a blocker.

joshuahannan avatar Mar 12 '24 17:03 joshuahannan

If i want to get a Cap{NonFungibleToken.Receiver} should that not work if it linked as a concrete impl or any interface that implements NonFungibleToken.Receiver?

bjartek avatar Mar 27 '24 18:03 bjartek

@bjartek That is possible and works currently I believe

joshuahannan avatar Mar 27 '24 19:03 joshuahannan