Skip to main content

Deploy a smart contract with CameLIGO

Estimated time: 30 minutes

This tutorial covers writing and deploying a simple smart contract with the LIGO programming language. Specifically, this tutorial uses the CameLIGO version of LIGO, which has syntax similar to OCaml, but you don't need any experience with OCaml or LIGO to do this tutorial.

LIGO 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 store cryptocurrency tokens
  • Get free tez tokens (the native cryptocurrency token on Tezos) from a faucet
  • Code a contract in LIGO, including:
    • Defining the storage for the contract
    • Defining entrypoints in the contract
    • Writing code to run when the entrypoints are called
  • 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 single integer. It provides entrypoints that clients can call to change the value of that integer:

  • The increment entrypoint accepts an integer as a parameter and adds that integer to the value in storage
  • The decrement entrypoint accepts an integer as a parameter and subtracts that integer from the value in storage
  • The reset entrypoint takes no parameters and resets the value in storage to 0

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 type that describes the contract's storage, in this case an integer. The storage can be a primitive type such as an integer, string, or timestamp, or a complex data type that contains multiple values. For more information on contract data types, see Data types.

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

  • A type that describes the return value of the entrypoints.

Follow these steps to create the code for the contract:

  1. Open the LIGO online IDE at https://ide.ligolang.org/. You can work with LIGO 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. At the top right of the page, in the Network menu, select Custom, as shown in this picture:

    warning

    You must not select the default Tezos Testnet because it will point you to Ghostnet, which is a legacy test network, soon to be decommissioned. A future release of LIGO will retarget this default choice to Shadownet.

    Selecting Custom in the list of networks

    Then in the newly opened window "Custom network" click on "New connection", and in the newly opened subwindow "New Custom Network Connection" fill in Shadownet for the Name and https://rpc.shadownet.teztnets.com for the Url of node rpc, as shown in this picture:

    Defining Shadownet as a custom network

    then click on "Check network" to update the Network info, then click on "Add network". Back in window "Custom network", click on "Connect", and you're now connected to the Shadownet testnet. Note that you only have to add Shadownet once, because the next times it will appear as a choice in the "Network" menu, in the "Others" section, as shown in this picture:

    Selecting Shadownet in the list of networks

  3. Connect a wallet to the IDE:

    1. At the top right of the page, click the Keypair Manager button.

    2. In the Keypair Manager window, import the account that you created earlier or create and fund a new account to use with the IDE.

      • To import the account that you created earlier, export the private key from your wallet app, click Import in the Keypair Manager window, and paste the private key. Now you can use your account in the IDE.

      • To create an account to use with the IDE, click Create in the Keypair Manager window, give the new keypair a name, and click Create. Then, copy the address of the keypair and get tez from the faucet as you did in Creating and funding a wallet.

  4. In the IDE, create a project from the empty template and select the CameLIGO syntax, as shown in this picture:

    Creating a project

    The IDE creates a project and a contract file named Contract.mligo.

  5. In the contract file, create a type to set the storage type to an integer:

    type storage = int
  6. Add this code to define the return type for the entrypoints. Tezos entrypoints return two values: a list of other operations to call and the new value of the contract's storage.

    type returnValue = operation list * storage
  7. Add the code for the increment and decrement entrypoints:

    // Increment entrypoint
    [@entry] let increment (delta : int) (store : storage) : returnValue =
    [], store + delta

    // Decrement entrypoint
    [@entry] let decrement (delta : int) (store : storage) : returnValue =
    [], store - delta

    These functions begin with the @entry annotation to indicate that they are entrypoints. They accept two parameters: the change in the storage value (an integer) and the current value of the storage (in the storage type that you created earlier in the code). They return a value of the type returnValue that you created in the previous step.

    Each function returns an empty list of other operations to call and the new value of the storage.

  8. Add this code for the reset entrypoint:

    // Reset entrypoint
    [@entry] let reset (() : unit) (_ : storage) : returnValue =
    [], 0

    This function is similar to the others, but it does not take the current value of the storage into account. It always returns an empty list of operations and 0.

The complete contract code looks like this:

type storage = int

type returnValue = operation list * storage

// Increment entrypoint
[@entry] let increment (delta : int) (store : storage) : returnValue =
[], store + delta

// Decrement entrypoint
[@entry] let decrement (delta : int) (store : storage) : returnValue =
[], store - delta

// Reset entrypoint
[@entry] let reset (() : unit) (_ : storage) : returnValue =
[], 0

Testing and compiling the contract

Before you can deploy the contract to Tezos, you must compile it to Michelson, the base language of Tezos contracts.

  1. Set the compiler to target the module to compile in your code:

    1. On the left side of the page, under Actions, click Project Settings.
    2. On the Project Settings tab, in the Module name field, set the module name to Counter.
    3. Close the Project Settings tab.
  2. Test the contract by passing parameters and the storage value to the LIGO dry-run command:

    1. On the left side of the page, under Actions, click Dry Run.

    2. In the Dry Run window, select the Increment entrypoint, set the input parameter to 32 and the storage to 10. The Dry Run window looks like this:

      The Dry Run window, showing the entrypoint to run, the parameter to pass, and the value of the storage
    3. Click Run.

      At the bottom of the window, the Result field shows the response (LIST_EMPTY(), 42). This response means that the contract did not call any other contracts, so the list of operations is empty. Then it shows the new value of the storage. You can test the decrement function in the same way. If you see any errors, make sure that the code of your contract matches the code in the previous section.

    4. Test the Reset entrypoint in the same way, but pass unit as the input parameter and any integer in the storage field. The Reset entrypoint takes no parameters, but technically it accepts the value unit, which means no parameter.

      The Result field shows the response (LIST_EMPTY(), 0), which means that the storage value is now 0.

  3. On the left side of the page, under Actions, click Compile, and in the Compile window, click Compile again.

If the compilation succeeds, the IDE prints the compiled code to the terminal and saves it to the file build/contracts/Contract.tz. You can see the code by expanding your project on the left side of the page, under .workspaces, and double-clicking Contract.tz. If you see error messages, verify that your contract code matches the code in the previous section.

Now you can deploy the contract.

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. On the left side of the page, under Actions, click Deploy. You may see a warning that the initial storage is not set. You can ignore this warning because you can set the initial storage now.

  2. In the Deploy contract window, in the Init storage field, set the initial value for the contract's storage to an integer.

  3. In the Signer field, make sure your account is selected.

  4. Click Estimate.

    The window shows the estimated fees to deploy the contract, as in this picture:

    The estimate of the fees to deploy the contract
  5. Click Deploy.

    The deployment process can take a few minutes. When the contract is deployed, the Deploy contract window shows the address at the bottom of the window.

  6. Copy the address of the deployed contract, which starts with KT1.

warning

Copy the contract address now, because it will not be shown again.

Now you can call the contract from any Tezos client, including web applications and command-line applications like The Octez client.

Calling the contract

These steps show you how to inspect the contract with a block explorer, which is a web application that shows information about Tezos. It also allows you to call the contract.

  1. Open the block explorer Better Call Dev at this link: https://better-call.dev/

  2. Paste the address of the contract in the search field and press Enter.

    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
  3. Try calling one of the entrypoints:

    1. Go to the Storage tab and check the current state of the storage, which should be the integer that you put in the Deploy window.

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

    3. For the increment entrypoint, in the Parameters section, put an integer 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 the new value of the 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