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

Fungible Token Switchboard contract and tests #71

Merged
merged 73 commits into from
Aug 19, 2022
Merged

Conversation

alilloig
Copy link
Member

@alilloig alilloig commented Jun 2, 2022

Closes: #66

Description

Created FungibleTokenSwitchboard contract. Created transactions for setting up switchboard and manage them. Created test suite using js. Design proposal can be found here


  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the standards mentioned here.
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

alilloig and others added 26 commits May 19, 2022 14:10
… of reference was beeing used as dictionary key
… to a <&FungibleTokenSwitchboard.Switchboard{FungibleToken.Receiver}>
… changed SwitchboardReceiverPublicPath to the royalties standard path
…aultCapabilityRemoved in the corresponding functions
@joshuahannan
Copy link
Member

Can you put the test directory into a lib/js/ directory so it isn't at the top level? Thank you!

…WARNING: Test failing due to js test framework not supporting PublicPath as a parameter for transactions, feature has been tested on playground
@alilloig
Copy link
Member Author

alilloig commented Jul 8, 2022

What do you think of an event that would be emitted if a deposit fails?

    /// NotCompletedDeposit
    /// 
    /// The event that is emitted when a deposit can not be completed
    ///
    pub event NotCompletedDeposit(type: Type, amount: UFix64, 
                                    switchboardOwner: Address)

        /// deposit Takes a fungible token vault and routes it to the proper
        ///         fungible token receiver capability for depositing it
        /// 
        /// Parameters: from: The deposited fungible token vault resource
        ///        
        pub fun deposit(from: @FungibleToken.Vault) {
            if let depositedVaultCapability = self.receiverCapabilities[from.getType()]{
                if let vaultRef = depositedVaultCapability.borrow() {
                    vaultRef.deposit(from: <- from)
                } else {
                    emit NotCompletedDeposit(type: from.getType(), 
                                        amount: from.balance, 
                                        switchboardOwner: self.owner!.address)
                    panic ("Can not borrow a reference to the the vault")
                }
            } else {
                emit NotCompletedDeposit(type: from.getType(), 
                                        amount: from.balance, 
                                        switchboardOwner: self.owner!.address)
                panic ("The deposited vault is not available on this switchboard")
            }
        }


        /// safeDeposit Takes a fungible token vault and tries to route it to 
        ///             the proper fungible token receiver capability for 
        ///             depositing the funds, avoiding panicking if the vault is 
        ///             not available
        ///             
        /// Parameters: vaultType: The type of the ft vault that wants to be 
        ///                        deposited
        ///
        /// Returns: The deposited fungible token vault resource, without the
        ///          funds if the deposit was succesful, or still containing the
        ///          funds if the reference to the needed vault was not found
        ///
        pub fun safeDeposit(from: @FungibleToken.Vault): @FungibleToken.Vault? {
            // Try to get the proper vault capability from the switchboard
            // If the desired vault is present on the switchboard...
            if let depositedVaultCapability = self.receiverCapabilities[from.getType()] {
                // We try to borrow a reference to the vault from the capability
                // If we can borrow a reference to the vault...
                if let vaultRef =  depositedVaultCapability.borrow(){
                    // We deposit the funds on said vault
                    vaultRef.deposit(from: <- from)
                    return nil
                } else {                    
                    // If we can't borrow a reference to the vault we emit the
                    // proper event and return the passed vault so the depositer 
                    // can recover their funds
                    emit NotCompletedDeposit(type: from.getType(), 
                                        amount: from.balance, 
                                        switchboardOwner: self.owner!.address)

                    return <- from
                }
            } else {
                // If the vault was not found on the switchboard and the deposit
                // could not be completed we emit the proper event and return
                // the passed vault so the depositer can recover their funds
                emit NotCompletedDeposit(type: from.getType(), 
                                        amount: from.balance, 
                                        switchboardOwner: self.owner!.address)              
                return <- from
            }
        }

@joshuahannan
Copy link
Member

If the execution reverts, then the events aren't emitted I believe so it wouldn't make sense for the regular deposit. It would probably be good for the safe deposit though

@bluesign
Copy link

bluesign commented Jul 9, 2022

great idea. Just code is little too complex now to grasp at first sight. maybe something like this?

 pub fun safeDeposit(from: @FungibleToken.Vault): @FungibleToken.Vault? {
            // Try to get the proper vault capability from the switchboard
            // If the desired vault is present on the switchboard...
            if let depositedVaultCapability = self.receiverCapabilities[from.getType()] {
                // We try to borrow a reference to the vault from the capability
                // If we can borrow a reference to the vault...
                if let vaultRef =  depositedVaultCapability.borrow(){
                    // We deposit the funds on said vault
                    vaultRef.deposit(from: <- from.withdraw(amount: from.balance))
                }
            }
            
            // if deposit failed for some reason 
            if from.balance>0{
                emit NotCompletedDeposit(type: from.getType(), 
                                        amount: from.balance, 
                                        switchboardOwner: self.owner!.address)              
                return <- from
            }
            
            destroy from 
            return nil
}

@alilloig
Copy link
Member Author

If the execution reverts, then the events aren't emitted I believe so it wouldn't make sense for the regular deposit. It would probably be good for the safe deposit though

thank you, I wasn't 100% sure if the events emitted before the execution was aborted were emitted anyways

@alilloig
Copy link
Member Author

@bluesign I liked your way, event added!

@alilloig
Copy link
Member Author

alilloig commented Jul 13, 2022

And I came up with a thought, should not the getVaultTypes() method check if all the stored capabilities can be borrowed, and if any of them cannot be borrowed, don't return that Type? So the caller can be truly aware of which FT can actually deposit into the switchboard

something like

        pub fun getVaultTypes(): [Type] {
            let efectitveTypes: [Type] = []
            for vaultType in self.receiverCapabilities.keys{
                if self.receiverCapabilities[vaultType]!.check<>(){
                    efectitveTypes.append(vaultType)
                }
            }
            return efectitveTypes
        }

…ies that can be borrowed when the method is called
@alilloig
Copy link
Member Author

as soon as the new version of the flow-js-testing is released on npm (it will add support for Paths) I'll update it and request a re-review from you guys

@joshuahannan
Copy link
Member

@alilloig Can you pull the latest from master and fix the merge conflicts that are shown here? Thanks!

@alilloig
Copy link
Member Author

@joshuahannan I believe is ready to merge!

@alilloig alilloig merged commit 36abd68 into master Aug 19, 2022
@alilloig alilloig deleted the alilloig/switchboard branch August 19, 2022 15:18
@onflow onflow deleted a comment from pinkizpunk Oct 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature SC-Eng Issues that we want to see surfaced in SC-Eng ZH Board
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build core FungibleTokenSwitchboard features
5 participants