Skip to main content

Deploy a smart contract with SmartPy

Estimated time: 30 minutes

This tutorial covers writing and deploying a simple smart contract with the SmartPy programming language. SmartPy has syntax similar to Python, but you don't need any experience with Python or SmartPy to do this tutorial.

SmartPy is a high-level programming language that you can use to write smart contracts for the Tezos blockchain. It abstracts away the complexity of using Michelson (the smart contract language directly available on-chain) to make it easier to write smart contracts on Tezos.

In this tutorial, you will learn how to:

  • Create a wallet to manage an account containing cryptocurrency tokens
  • Get free tez tokens (the native cryptocurrency token on Tezos) from a faucet
  • Code a contract in SmartPy, including:
    • Creating a contract in the online IDE
    • Defining the storage for the contract
    • Defining entrypoints in the contract
  • Deploy (or originate) the contract to Tezos and set its starting storage value
  • Look up the current state of the contract
  • Call the contract

What is a smart contract?

A smart contract is a computer program that is stored on a blockchain and runs on a blockchain. Because the blockchain is spread across many computer nodes, you don't have to think about where to host the program or worry whether a computer will run it or not. Responsibility for running the contract is distributed across all of the nodes in the Tezos system, so when you deploy a smart contract, you can be confident that it will be available and unmodified when someone wants to run it.

A smart contract has these parts:

  • Persistent storage, data that the contract can read and write
  • One or more entrypoints, which are a kind of function that clients can call, like endpoints in an API or functions or methods in many programming languages
  • A Tezos account that can store tokens (technically, the contract is itself a type of Tezos account, but you can think of it as a program with a Tezos account)

Tutorial contract

The contract that you deploy in this tutorial stores a string value. It provides entrypoints that clients can call to change the value of that string:

  • The replace entrypoint accepts a new string as a parameter and stores that string, replacing the existing string.
  • The append entrypoint accepts a new string as a parameter and appends it to the existing string.

After you deploy the contract, you or any other user can call it from various sources, including web applications, other contracts, and the Octez command-line client. However, no one can prevent it from running or tamper with its code or its storage.

Creating and funding a wallet

To deploy and work with the contract, you need a wallet and some tez tokens.

  1. Install a Tezos-compatible wallet. Which wallet you install is up to you and whether you want to install a wallet on your computer, in a browser extension, or as a mobile app. For options, see Installing and funding a wallet

  2. Switch the wallet to use the Shadownet testnet instead of Tezos Mainnet. Shadownet is a network for testing Tezos applications where tokens are free so you don't have to spend real currency to work with your applications.

    For example, for the Temple browser wallet:

    1. Expand the menu at top right and then turn on Testnet mode, as in this picture:

      Setting testnet mode in Temple
    2. Above the list of tokens, click the display options button:

      Clicking the button to open display options
    3. Under Filter by network, expand All Networks.

    4. Select Shadownet:

      Selecting Shadownet in the network settings

    Now Temple shows your token balances on the Shadownet test network.

  3. From your wallet, get the address of your account, which starts with tz1. This is the address that applications use to work with your wallet.

  4. Go to the Shadownet faucet page at https://faucet.shadownet.teztnets.com.

  5. On the faucet page, connect your wallet, or paste your wallet address into the input field labeled "Fund any address" and click the button for the amount of tez to add to your wallet. 20 tez is enough to work with the tutorial contract, and you can return to the faucet later if you need more tez.

    Depending on the amount you requested, it may take a few seconds or minutes for the faucet to send the tokens and for those tokens to appear in your wallet.

    You can use the faucet as much as you need to get tokens on the testnet, but those tokens are worthless and cannot be used on Mainnet.

    Funding your wallet using the Shadownet Faucet

Now you have an account and funds that you can use to work with Tezos.

Creating the contract

The contract that you will create has these basic parts:

  • A function that initializes the contract and sets the starting value for its storage.

  • Functions called entrypoints that run code when clients call the contract.

  • Automated tests that verify that the contract works as expected.

Follow these steps to create the code for the contract:

  1. Open the SmartPy online IDE at https://smartpy.io/ide. You can work with SmartPy code in any IDE, but this online IDE keeps you from having to install software on your computer, and it also simplifies the process of deploying contracts.

  2. In the code editor, add this line of code to import SmartPy:

    import smartpy as sp
  3. Add this code that creates the entrypoints:

    @sp.module
    def main():
    class StoreGreeting(sp.Contract):
    def __init__(self, greeting): # Note the indentation
    # Initialize the storage with a string passed at deployment time
    # Cast the greeting parameter to a string
    sp.cast(greeting, sp.string)
    self.data.greeting = greeting

    @sp.entrypoint # Note the indentation
    def replace(self, params):
    self.data.greeting = params.text

    @sp.entrypoint # Note the indentation
    def append(self, params):
    self.data.greeting += params.text

    Indentation is significant in Python, so make sure that your indentation matches this code.

    The first two lines create a SmartPy module, which indicates that the code is SmartPy instead of ordinary Python.

    Then the code creates a class named StoreGreeting, which represents the smart contract. The contract has an __init__ function, which runs when the contract is deployed. In this case, the function sets the initial value of the storage to a parameter that you pass when you deploy the contract. This storage value is a string, but the storage can be another primitive type such as an integer or timestamp, or a complex data type that contains multiple values. For more information on contract data types, see Data types.

  4. Add this code, which creates automated tests:

    # Automated tests that run on simulation
    @sp.add_test()
    def test():
    # Initialize the test scenario
    scenario = sp.test_scenario("StoreGreeting", main)
    scenario.h1("StoreGreeting")

    # Initialize the contract and pass the starting value
    contract = main.StoreGreeting("Hello")
    scenario += contract

    # Verify that the value in storage was set correctly
    scenario.verify(contract.data.greeting == "Hello")

    # Test the entrypoints and check the new storage value
    contract.replace(text = "Hi")
    contract.append(text = ", there!")
    scenario.verify(contract.data.greeting == "Hi, there!")

    When you run the SmartPy file, SmartPy runs a simulation in which it tests and compiles the contract. In this case, the tests verify that the replace and append endpoints work. For more information about SmartPy and tests, see the SmartPy documentation.

The SmartPy online IDE looks like this:

The SmartPy online IDE, including the code for the contract

The complete contract looks like this:

import smartpy as sp

@sp.module
def main():
class StoreGreeting(sp.Contract):
def __init__(self, greeting): # Note the indentation
# Initialize the storage with a string passed at deployment time
# Cast the greeting parameter to a string
sp.cast(greeting, sp.string)
self.data.greeting = greeting

@sp.entrypoint # Note the indentation
def replace(self, params):
self.data.greeting = params.text

@sp.entrypoint # Note the indentation
def append(self, params):
self.data.greeting += params.text

# Automated tests that run on simulation
@sp.add_test()
def test():
# Initialize the test scenario
scenario = sp.test_scenario("Test scenario", main)
scenario.h1("StoreGreeting")

# Initialize the contract and pass the starting value
contract = main.StoreGreeting("Hello")
scenario += contract

# Verify that the value in storage was set correctly
scenario.verify(contract.data.greeting == "Hello")

# Test the entrypoints and check the new storage value
contract.replace(text = "Hi")
contract.append(text = ", there!")
scenario.verify(contract.data.greeting == "Hi, there!")

Testing and compiling the contract

Before you can deploy the contract to Tezos, you must run it in the IDE, which automatically compiles it to Michelson, the base language of Tezos contracts. Then, the IDE also automatically runs the tests.

  1. Compile the contract and run the tests by clicking the Run Code button:

    The right-hand pane of the online IDE shows the results of the simulation, compilation, and testing process. The first step is simulating the deployment (origination) of the contract. The simulation assigns the contract a temporary address and shows the initial state of its storage:

    The originated contract and the initial storage in the SmartPy IDE

    Then, the simulation runs the test cases and shows the results of each call to an entrypoint:

    The results of the entrypoint calls

Deploying (originating) to the testnet

Deploying a contract to the network is called "originating." Originating the contract requires a small amount of Tezos tokens as a fee.

  1. Under the origination step, click Deploy contract.

    The originated contract, with the Deploy contract button highlighted

    The IDE shows the compiled Michelson code of the contract, which is the language that smart contracts use on Tezos.

  2. Below the Michelson code, click Continue.

  3. In the new window, under "Node and Network," select the Shadownet testnet and accept the default RPC node, as in this picture:

    Selecting the Shadownet network and default RPC node
  4. Under "Wallet," click Select Account.

  5. In the pop-up window, connect your wallet. For most wallets, use the Beacon tab.

  6. When your wallet is connected, click Validate.

    The Origination page shows your wallet information:

    The successful connection to your wallet on the origination page
  7. Under "Contract Origination Parameters," click Estimate cost. The Fee field shows the estimated cost to deploy the contract in tez.

  8. At the bottom of the page, click Deploy Contract.

  9. In the pop-up window, click Accept.

  10. Approve the transaction in your wallet app.

    The "Result" section shows information about the deployed contract, including its address:

    Information about the originated contract
  11. Copy the contract address, which starts with KT1.

    note

    Be sure to save the contract address because it is not shown in the SmartPy online IDE again.

    If you close the window and forget the address, you can look up your account address in a block explorer; the block explorer shows your recent transactions, including smart contracts that you deployed.

  12. Open the contract in the block explorer Better Call Dev:

    1. Click Open explorer.

      The IDE shows information about the contract and links to popular block explorers.

    2. Click Explore with Better Call Dev.

    You can also go directly to https://better-call.dev/ in a new browser tab and search for the contract by its address.

    The block explorer shows information about the contract, including recent transactions and the current state of its storage:

    The block explorer, showing information about the contract
  13. Try calling one of the entrypoints:

    1. Go to the Storage tab and check the current state of the storage. If you just originated the contract, the storage is "Hello" because that's the value set in the smart contract code.

    2. Go to the Interact tab. This tab shows the entrypoints in the contract and lets you use them.

    3. For the append entrypoint, in the Parameters section, put some text in the field, as shown in this image:

      Putting in a value for an entrypoint parameter
    4. Click Execute and then click Wallet.

    5. Select your wallet and connect it to the application.

    6. Confirm the transaction in your wallet.

    7. Wait for a success message that says "The transaction has successfully been broadcasted to the network."

    8. Go back to the Storage tab and see that the text that you put in the parameter has been added to the contract storage, as in this picture:

      Updated storage value

Summary

Now the contract is running on the Tezos blockchain. You or any other user can call it from any source that can send transactions to Tezos, including Octez, dApps, and other contracts.

If you want to continue working with this contract, here are some ideas:

  • Change permissions for the contract so only your account can call its entrypoints
  • Add your own entrypoints and originate a new contract; note that you cannot update the existing contract after it is deployed
  • Create a dApp to call the contract from a web application, similar to the dApp that you create in the tutorial Build a simple web application