Skip to main content

Creating smart contracts

Introduction

This documentation provides step-by-step instructions for creating smart contracts on Tezos. After creating the contract, you can find the resources on testing and deploying.

Choosing your smart contract language

Tezos supports a variety of smart contract languages: Michelson, SmartPy, LIGO, Archetype.

You can select a language based on your familiarity with programming paradigms, the complexity of the contract you want to deploy, and the specific features you require. Here's a more detailed table for each language:

MichelsonSmartPyLIGOArchetype
ComplexityHigh (stack-based, low-level)Low (Python-like, high-level)Moderate (various high-level syntaxes)Moderate (includes formal specification features)
CapabilitiesFull control over contract, optimal for gas efficiencyEasy to write, automatically manages stack operationsStatically-typed, strong error checkingSpecialized for formal verification and correctness
Use CasesOptimized contracts, developers with blockchain experiencePython developers, rapid prototypingDevelopers familiar with static typing, variety of mainstream programming backgroundsHigh-security contracts, developers looking for formal proof of contract behavior

For beginners, we recommend SmartPy or LIGO for their higher-level more abstracted approach.

Making a strategic choice

Before writing your code, take some time to consider whether your project is suitable for starting with a pre-existing template or if it would be better to start from scratch. Essentially, this depends on the type of contract you are building. For example:

  • FA2 contract: it’s better to use a template to start.
  • Others: build it from scratch.

Coding your contract

Before coding, you should clearly outline the purpose of your smart contract, define the problem it addresses, detail the functions it will perform, and specify any external interactions or transactions it will manage.

Starting with online IDE

The online editor is the quickest and easiest way to get started.

For example:

Defining contract storage

Contract storage holds the persistent state of your smart contract. It’s important to carefully design your storage since storage is expensive on-chain. You should avoid storing any data that the contract will not use.

  • SmartPy: Use Pythonic classes and types to represent storage. SmartPy provides a straightforward way to map these into Michelson storage requirements.
  • LIGO: Choose the most suitable syntax flavor and use the type definitions to lay out the storage structure.

In Tezos, big maps are a storage optimization feature for large sets of data, especially when handling large datasets that don't need to be fully loaded into memory at once. Big maps are ideal for ledger applications with numerous accounts, as they load data lazily, fetching only necessary parts on demand. In contrast to regular maps, suitable for smaller collections, and lists, which order data, big maps save costs when the dataset is large.

In SmartPy, you can define a big map using sp.big_map, and in LIGO, you use big_map keyword for the type declaration.

Defining entrypoints

Entrypoints serve as methods to receive external communication in Tezos.

  • SmartPy: Entrypoints are defined as methods within a Python class that extends sp.Contract. They use decorators like @sp.entry_point to denote entrypoints
  • LIGO: Entrypoints in LIGO are defined as functions that manipulate storage. The function keyword is used, and each entrypoint function must be explicitly marked for export in the contract interface

You should clearly define the parameters and storage interaction for both languages.

  • Each entrypoint's parameters must be well-specified, with types that match the expected inputs. For example, if an entrypoint is supposed to accept an integer and a string, the parameter list should reflect this.
  • The contract storage is usually passed as an argument to the entrypoints. In SmartPy, the storage is accessed through the self.data attribute inside the entrypoint methods. In LIGO, storage is a parameter of the function, and it's often the last parameter by convention.