Building on Flow: 3 Common Issues and How to Solve Them

July 30, 2021

This past week has been a blast as our team at Decentology kicked off the first ever Fast Floward bootcamp. The bootcamp helps web2 developers learn about the basics and get started in the web3 (decentralized) world. In this 3 week long bootcamp we are focusing on Flow. In week 1, we noticed three common issues bootcamp attendees encountered. In this post, we’ll discuss those issues and the solutions for each.


Flow Playground

As users learned more throughout the week, they encountered a few common issues. I will be using the Flow Playground to show visuals of these issues and how we can solve them. The playground I use can be found here: https://play.onflow.org/59294d03-78a4-4652-ac32-e259f874d792?type=account&id=0


Issue #1: Loss of Resources

If you’ve been developing in Cadence for some time, there is no doubt you have encountered an error that looks something like this...


In Cadence, resources (which are a unique type to the Cadence programming language and can be learned about here: https://docs.onflow.org/cadence/#intuiting-ownership-with-resources) cannot be left “dangling.” 

There are two main ways to deal with this issue: 

a) destroy the resource if you no longer need it by using the destroy keyword, or...

b) move the resource to somewhere else, whether it be account storage, an array, dictionary, another resource, or anywhere where the resource can live after the function call/transaction has concluded.


Let’s take a look at an example here…

I have defined a simple contract that has a resource called Test, and a function called createTest that simply creates a Test resource and returns it to the caller. Let’s set up a transaction to call createTest…

Ah, look! We get a “loss of resource” error. But we know how to fix this. Let’s look at both methods a) and b) to solve this issue.


And remember: to move resources, you must use the move syntax (<-) to explicitly “move” the resource.


Issue #2: Unwrapping an Optional

The second most common issue participants have encountered has been removing a value from an optional type. In Cadence, an optional is declared using the ? syntax. For example, if we have: let x: Int?, this means x is either an Int or nil. A common error participants have encountered is something along the lines of, “expected Int, got Int?”. All this means is we haven’t “unwrapped” the Int from it’s optional yet. 

Let’s take a look at an example using the contract from Issue 1, but now let’s add a function that returns the Test resource as an optional…


We can write a transaction that calls this function, but let’s purposefully try to get an error…

What went wrong? Well, we declared testResource as a HelloWorld.Test, but we received a HelloWorld.Test? because that’s what HelloWorld.createTestOptional() returns. How can we fix this? The answer is we can use the force-unwrap operator !, which will either return the value if it’s there, or nil. Let’s see how we can use it in our example…


As you can see, there is no longer an error about mismatched types. Hoorah!


Issue #3: Prepare Phase vs Execute Phase

Lastly, although not a big issue, it is important to address the difference between the prepare phase and the execute phase of a transaction. It is best practice to put the “setup” of a transaction in the prepare phase, and all the logic/functional components in the execute phase. 

There are two main things that constitute the “setup” of a transaction:

  1. Everything that has to do with the authorizers AuthAccount. This is required. The only way we can access the authorizer’s account storage is with the AuthAccount. Because we no longer have access to the AuthAccount in the execute phase, it is required that we borrow references from the AuthAccount’s account storage in the prepare phase. Similarly, if we want to load resources from storage, it must take place in the prepare phase as well.
  2. Retrieving capabilities. Although not a requirement, it is usually best practice to get any capabilities from public accounts in the prepare phase and then use them in the execute phase. Let’s look at a quick example, assuming we are using the contract code defined in the playground example linked above:



Conclusion
We’ve learned a lot as a community and are looking forward the next couple of weeks ahead. I hope this content is helpful as you learn more about web3, Flow, and Cadence. The best way to learn is by hitting errors and working through them. We’re excited to continue helping guide bootcamp attendees as they learn how to build on Flow.


Also, it’s still not too late to join if you’re interested. Get started by registering here: https://www.decentology.com/blog/fast-floward-developer-bootcamp-for-flow 


Learn more about Flow

Learn more about Cadence

Follow Jacob on Twitter

💌
Join the newsletter & get updates to your inbox.
Your information has been saved.
Looks like we're having trouble