Lesson: Introduction to SmartPy

Ask Question

Chapter 14

Tinkering with decision making via if & sp.if in SmartPy

Intro:

You would be already be pretty familiar with basic decision making in Python using if...else statements.

In this chapter, we are going to understand how to go about writing decision making code inside smart contracts using SmartPy’s sp.if..sp.else statements.

In later half of the chapter, we design an alerting system to ping us when our Cryptobot runs out of plasma bullets!

Alert Text

Study Time:

Why use sp.if over plain if?

We use sp.if over plain if for the following reasons:

  1. In smart contracts, most of decision making tends to happen via placing conditions over values stored inside contract’s storage.
    • Since decision making evaluation in smart contracts actually happens when smart contract’s are being simulated or finally deployed to the Tezos blockchain, sp.if let’s us execute decision making with contract’s latest values in it’s storage.
    • Since plain if doesn’t have SmartPy’s superpowers, you won’t be able to bet whether it is executing on contract’s latest updated values or not.
  2. The difference between both comes from the environment in which they finally get to execute.

Hence whenever in doubt or you are running in weird errors, trust in SmartPy’s superpowers and use the prefix sp.

Show me an example:

Remember:

  1. coordinate_x which stores our cryptobot’s current x coordinate and
  2. move_horizontally entry point function which is used to change coordinate_x state variable value?
    class Cryptobot(sp.Contract):
        def __init__(self,):
            self.init(
                ....
                coordinate_x = sp.int(0),
                ... 
                }

            )
            
        ...
        @sp.entry_point
        def move_horizontally(self, update_to):
            self.data.coordinate_x += update_to
        ....
  1. We had specified a range for it that the cryptobot can only move between [-10, 10].
  2. Though currently our move_horizontally entry point function currently allows to move to any arbitrary value since we don’t check whether update_to is in the range of [-10, 10]!

We don’t want the cryptobot to start running away do we? 😰


Let us use sp.if to check whether update_to is in the range of [-10, 10]!:

@sp.entry_point
def move_horizontally(self, update_to):
   sp.if (update_to >= -10) & (update_to <= 10): 
       self.data.coordinate_x += update_to
   sp.else: 
       sp.failwith("Error: movement out of bounds")

Explaining the code above:

  1. The code is mostly straightforward to read where we basically instead of using if, we use sp.if to put condition over update_to
  2. If the condition fails, we use sp.failwith - a SmartPy helper method - to send back a relevant error message.

#buidl-ing time:

New feature request!

Currently if you run out of bullets, your shoot_alien function will still be able to run without alerting you that there are no bullets left!

Step by step walkthrough:

Let’s use sp.if to proceed forward with shooting only when plasma_bullet_count is greater than 1. If not, we will use sp.failwith to alert you that you run out of bullets!

  1. Using sp.if add a condition to check plasma_bullet_count >= 1. Use self.data.plasma_bullet_count to access it.
  2. Move the shooting code inside sp.if scope.
  3. Add sp.else and inside it’s scope use sp.failwith to return with "Error: you ran out of bullets! Please buy more!" error message.

When you’re finished:

  1. Click on “Check” to check your submission with the correct answer.
  2. Click on “Show Answer” in case you get stuck.

You can also tinker around with the final code on SmartPy’s online IDE. Try running the test by clicking on the ▶️ button!

Optional Reading:

Read more in depth about:

  1. Technical pov of using sp.if over if in your smart contract code - under reference manual’s “Control & Syntactical Sugar” section here.
  2. Why you cannot use and, or, not in your smart contract code and instead need to use &, |, ~ respectively - under reference manual’s “Boolean” section here.

Contract.py

Loading...