Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FungibleTokenSwitchboard is not interoperable with TokenForwarding #104

Closed
NtTestAlert opened this issue Dec 9, 2022 · 3 comments
Closed
Assignees
Labels
bug Something isn't working Feedback SC-Eng Issues that we want to see surfaced in SC-Eng ZH Board

Comments

@NtTestAlert
Copy link

Problem

If there are multiple &TokenForwarding{FungibleToken.Receiver} Forwarders on an account, such as
one for DapperUtilityCoin and one for FlowUtilityToken, which is currently used for Dapper Wallet accounts,
trying to add both, will result in only a single one being remembered by TokenForwarding,
because after .borrowing they resolve to the same Type.
Neither would be unusable anyway, because the type does not match the input (deposit) vault type.

It is impossible to tell which token is handled by a Forwarder, as that information is not accessible from the resource.

Proposed solution

An (optional?) parameter for addNewVault method, to override the deposit Type that the capability handles.

Reproduction

Setups:

/// Setup Switchboard 

transaction {

    prepare(acct: AuthAccount) {

        if acct.borrow<&FungibleTokenSwitchboard.Switchboard>
          (from: FungibleTokenSwitchboard.StoragePath) == nil {

            acct.save(
                <- FungibleTokenSwitchboard.createSwitchboard(),
                to: FungibleTokenSwitchboard.StoragePath)

            acct.link<&FungibleTokenSwitchboard.Switchboard{FungibleToken.Receiver}>(
                FungibleTokenSwitchboard.ReceiverPublicPath,
                target: FungibleTokenSwitchboard.StoragePath
            )

            acct.link<&FungibleTokenSwitchboard.Switchboard{FungibleTokenSwitchboard.SwitchboardPublic/*, FungibleToken.Receiver*/}>(
                FungibleTokenSwitchboard.PublicPath,
                target: FungibleTokenSwitchboard.StoragePath
            )
        }
    }
}

/// Setup forwarders

transaction(dapperAddress: Address) {

    prepare(signer: AuthAccount) {
        let dapper = getAccount(dapperAddress)

        let ducReceiverPublicPath = /public/dapperUtilityCoinReceiver
        let ducReceiverStoragePath = /storage/dapperUtilityCoinReceiver
        let ducReceiver = signer.getCapability<&{FungibleToken.Receiver}>(ducReceiverPublicPath)!

        let futReceiverPublicPath = /public/flowUtilityTokenReceiver
        let futReceiverStoragePath = /storage/flowUtilityTokenReceiver
        let futReceiver = signer.getCapability<&{FungibleToken.Receiver}>(futReceiverPublicPath)!

        if ducReceiver.borrow() == nil {
            let dapperDUCReceiver = dapper.getCapability(ducReceiverPublicPath)!
            let ducForwarder <- TokenForwarding.createNewForwarder(recipient: dapperDUCReceiver)
            signer.save(<-ducForwarder, to: ducReceiverStoragePath)

            signer.link<&DapperUtilityCoin.Vault{FungibleToken.Receiver}>(
                ducReceiverPublicPath,
                target: ducReceiverStoragePath
            )
        }

        if futReceiver.borrow() == nil {
            let dapperFUTReceiver = dapper.getCapability(futReceiverPublicPath)!
            let futForwarder <- TokenForwarding.createNewForwarder(recipient: dapperFUTReceiver)
            signer.save(<-futForwarder, to: futReceiverStoragePath)

            signer.link<&FlowUtilityToken.Vault{FungibleToken.Receiver}>(
                futReceiverPublicPath,
                target: futReceiverStoragePath
            )
        }
    }
}

/// Attach to Switchboard

transaction {
    let switchboardRef:  &FungibleTokenSwitchboard.Switchboard
    let vaultPaths: [PublicPath]
    let address: Address

    prepare(signer: AuthAccount) {
        self.address = signer.address

        let ducReceiverPublicPath = /public/dapperUtilityCoinReceiver
        let futReceiverPublicPath = /public/flowUtilityTokenReceiver

        self.vaultPaths = []
        self.vaultPaths.append(ducReceiverPublicPath)
        self.vaultPaths.append(futReceiverPublicPath)

        let ducTokenVaultCapabilty = signer.getCapability<&{FungibleToken.Receiver}>(ducReceiverPublicPath)
        assert(ducTokenVaultCapabilty.check(), message: "Signer does not have a DUC receiver capability")

        let futTokenVaultCapabilty = signer.getCapability<&{FungibleToken.Receiver}>(futReceiverPublicPath)
        assert(futTokenVaultCapabilty.check(), message: "Signer does not have a FUT receiver capability")

        self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
            (from: FungibleTokenSwitchboard.StoragePath)
            ?? panic("Could not borrow reference to switchboard")
    }

    execute {
        self.switchboardRef.addNewVaultsByPath(paths: self.vaultPaths, address: self.address)
    }
}

Script:

      pub fun main(addr: Address): [Type] {
        let sbC = getAccount(addr)!
          .getCapability<&{FungibleTokenSwitchboard.SwitchboardPublic/*, FungibleToken.Receiver*/}>(FungibleTokenSwitchboard.PublicPath)
        
        //let sbR = sbC.borrow()! 
        let sbS = (sbC as? Capability<&{FungibleTokenSwitchboard.SwitchboardPublic}>)!.borrow()!
        
        return sbS.getVaultTypes()
   }

Result: (one entry, while two capabilities were added earlier, so one overwrites the other)

  console.log
    [        
      {      
        kind: 'Resource',
        typeID: 'A.179b6b1cb6755e31.TokenForwarding.Forwarder',
        fields: [ [Object], [Object] ],
        initializers: [],
        type: ''
      }
    ]
@NtTestAlert NtTestAlert added bug Something isn't working Feedback labels Dec 9, 2022
@alilloig alilloig self-assigned this Dec 9, 2022
@alilloig alilloig added the SC-Eng Issues that we want to see surfaced in SC-Eng ZH Board label Dec 9, 2022
@alilloig
Copy link
Member

alilloig commented Dec 9, 2022

Thank you for your feedback! This was already noticed by @bjartek on issue #102. We are planning to add a new method allowing users to specify a different type of token for a certain capability, a PR addressing this will be created shortly.

@NtTestAlert
Copy link
Author

Ah, skimmed thru that issue but didn't notice it is the same thing, sorry for duplicate

@alilloig
Copy link
Member

alilloig commented Dec 9, 2022

Not at all!! Better duplicated than missed. And I love the level of detail explaining the issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Feedback SC-Eng Issues that we want to see surfaced in SC-Eng ZH Board
Projects
None yet
Development

No branches or pull requests

3 participants