FAQ
Discovering SmartPy
What is SmartPy?
SmartPy is a comprehensive solution for developing and testing smart contracts on the Tezos blockchain. It includes the Python-like SmartPy language, a compiler that converts SmartPy code to Michelson code, tools for testing contracts in test scenarios, and utility libraries.
How do I get started?
Begin with our tutorial. For practical examples, navigate to the web IDE and explore the variety of templates provided.
You can also install SmartPy locally with pip
; see Installation.
What is the relationship between SmartPy and Python?
SmartPy code looks and behaves much like Python but is not actually Python. It is a domain-specific language that has types, structures, and limitations specific to the Tezos blockchain.
A single file can contain both SmartPy and Python code:
- The SmartPy code is in SmartPy modules, which are designated with the
@sp.module
decorator - The Python code is outside of the SmartPy modules and defines test scenarios
You can also put SmartPy code (without standard Python) in .spy
files. For more information, see Modules.
How is SmartPy similar to and different from Python?
See Differences between SmartPy and Python.
What is a smart contract?
A smart contract is essentially a program executed within the blockchain environment. Once deployed, contracts are immutable and public. This ensures transparency, audibility, and reproducibility.
What is a blockchain?
A blockchain is a decentralized ledger system. You can delve deeper into its intricacies on opentezos.com/blockchain-basics.
What is Tezos?
Tezos is a dynamically evolving blockchain, distinguished by its unique on-chain governance. From inception, it has employed proof-of-stake and continues to provide a multitude of security-enhancing features.
Learn more at tezos.com or opentezos.com/tezos-basics.
Can I use VSCode, Pycharm, emacs, etc.?
Absolutely! SmartPy provides an offline command line interface compatible with your favourite IDE.
Do you recommend using the SmartPy web IDE instead?
While the SmartPy web-based IDE is ideal for beginners due to its simplicity, we suggest using your preferred IDE for more intense development. It's recommended to manage your files on your own system and not depend solely on your browser's local storage.
Can I write smart contracts for other blockchains using SmartPy?
Currently, SmartPy concentrates exclusively on developing smart contracts for the Tezos blockchain.
What is Michelson?
Michelson is a specialized programming language created specifically for Tezos. It offers an elevated level of security and avoids certain issues prevalent in the Ethereum Virtual Machine (EVM). You can learn more about it here.
Can I deploy a smart contract on Tezos using SmartPy?
Yes, the SmartPy website offers an origination tool. You can also employ any other deployment tools available within the Tezos ecosystem. SmartPy does not provide a built-in way to deploy smart contracts from the command line. To deploy from the command line, use a Tezos tool such as the Octez client as described in Deploying contracts.
What are the resources or community forums where I can learn more and get help with SmartPy?
Diving into the language
What is the equivalent to struct
in SmartPy?
In SmartPy, the equivalent to a struct
is a record.
How do I accept tez in an entrypoint?
There's no specific step required. In Tezos, received tez are automatically added to the contract's balance.
To control the received amount or enforce a payment, use the assert
instruction with the sp.amount
instruction, which reflects the amount received. For instance, assert sp.amount > 10
ensures that an amount greater than ten tez is received, otherwise, the entrypoint will fail.
Can I use Python libraries in my smart contracts?
Although other Python libraries cannot be directly used in the smart contract code itself, they can be used in the code that tests your contracts.
Can I use Python f-strings?
While Formatted string literals (known as "f-strings") are not supported within the contract's code due to the absence of this feature in Michelson, they can be used for testing contracts.
Why don't my old contracts work in the simulator anymore?
With version 0.18 SmartPy has migrated to a new syntax. If your contracts are written in the old syntax, you can still access them using the legacy version available at legacy.smartpy.io.
I'm getting the error module 'smartpy' has no attribute 'Contract'
.
The code of a smart contract should reside inside a module (sp.module
). If you need assistance with this, please refer to the tutorial. If your contract is outdated, refer to the solution for the previous question.
Can I run test scenarios with contracts from the old syntax together with contracts in the new syntax?
Unfortunately this isn't possible. However, migrating contracts to the new syntax is generally a relatively straightforward process.
Is there a way to generate random numbers?
Tezos doesn't offer an in-built instruction to generate random numbers on-chain. If this is a requirement for your project, you might find this resource helpful: opentezos.com/smart-contracts/avoiding-flaws/#7-using-unreliable-sources-of-randomness.
With that in mind there is an example template rng.spy
and test test_rng.py
in the templates pack that comes with the offline installation. This example smart contract implements a counter-based pseudo-random number generator and uses tickets for the input seed values and output random values. The 64 bit, 4-digit Threefry algorithm used is described here.
This smart contract could be embellished with other Tezos features like sapling transactions or timelocks to hide or encrypt the ticket transfers for the seed input or random output.
What is the difference between on-chain and off-chain views?
On-chain views are part of the contract's deployed code and can be invoked both on-chain and off-chain and have the ability to call other on-chain views. If a contract calls them, the gas cost is part of the transaction. Off-chain views, on the other hand, are only callable off-chain and are exempt from gas costs. Their code is stored off-chain but referenced in the contract.
How can I optimize my code?
In SmartPy, as in most of computing, optimization largely stems from your application's overall design. Common ways to reduce costs include avoiding lengthy error messages, conducting most of the computations off-chain, and minimizing the complexity of your tasks.
Compilation
How do I compile a SmartPy contract?
To compile a SmartPy contract, make sure that SmartPy is installed as described in Installation. Then, run the command python path/to/contract.py
, where path/to/contract.py
is the path to your contract. For more information, see Compiling contracts.
Where are SmartPy's output files?
When you compile a SmartPy contract locally with the python
command, SmartPy writes output files to the folder that you specify when you create the test scenario. For example, if you create the test scenario with the code scenario = sp.test_scenario("My test", main)
, SmartPy writes output files to the My_test
folder, relative to the location of the test scenario file.
What are the compiled files?
SmartPy compiles each contract, each contract's initial storage, and the parameters for each smart contract call to multiple output files:
Output log: The
log.txt
file includes messages from the compiler, the names of other compiled files as they are created, and messages that you add as described in Logging.Compiled contract files: SmartPy compiles each contract that you instantiate and add to the test scenario to a Michelson in files that end in
_contract.tz
and Micheline JSON in files that end in_contract.json
.SmartPy gives each contract in the test scenario an ID number in the order that they are instantiated in the code, starting with 0. The first contract is compiled to a file that ends in
_cont_0_contract.tz
. Other output files that are associated with this contract have the same ID number, such asstep_001_cont_0_storage.tz
for its initial storage value andstep_007_cont_0_params.tz
for the parameters sent to that contract in a call.Compiled initial storage files: SmartPy compiles the initial storage value of each contract to Python, Micheline JSON, and Michelson files that end in
_storage.py
,_storage.json
, and_storage.tz
. You can use the contents of these files to set the initial storage of the contract when you deploy it.Parameter files: SmartPy compiles the parameters from each smart contract call in the test scenario to Python, Micheline JSON, and Michelson files that end in
_params.py
,_params.json
, and_params.tz
. You can use the contents of these files as examples of how to format parameters for smart contract calls after you deploy the contract.
Each file starts with step_[nnn]
, where [nnn]
is the number of the step in the test scenario that instantiated the contract. The log.txt
file lists when each file is created so you can match files to commands in your test scenario.
Tokens
How do tokens work?
A smart contract (a program that runs independently on the blockchain) maintains a ledger. The ledger indicates who owns which token. It also maintains a list of metadata associated with each token type. The metadata for a token can specify the token's name, symbol, number of decimals, and other details.
A token is identified by two values: the address of the smart contract and an ID number.
What can I do with tokens?
Tokens can be minted (created from scratch), burned (definitively destroyed) and transferred depending on rules written in the smart contract that maintains them.
What do they represent?
Tokens can represent anything. The metadata associated with the tokens give you the endless possibilities. Tokens can represent money, piece of art, permissions, real world assets like houses or contracts.
What are fungible tokens?
Fungible tokens are interchangeable values. A fungible token is identical to another fungible token of the same type. For example, you wouldn't mind if someone replaces a $20 bill in your pocket with another $20 bill because you don't distinguish two bills of the same value.
What are NFTs or non-fungible tokens?
NFTs represent a unique value that is not interchangeable with any other token. NFTs are useful to represent real world assets that are unique like a painting or a house. They can also represent ownership of a digital asset that is considered unique like a digital picture or a piece of music.
How can I create tokens?
Create a smart contract that maintains a ledger that indicates who owns the tokens. We recommend creating tokens according to the Tezos FA2 token standard. To simplify the process, you can use the SmartPy FA2 library.
What are some common pitfalls to avoid when programming with SmartPy?
Common errors to avoid include:
Using
sp.source
instead ofsp.sender
.Tezos provides two ways to determine what account called a contract:
The source (which you can access as
sp.source
) is the account that initiated the original transaction that led to calling the current smart contract. The source is always a user account, also known as an implicit account, and it stays the same even if the transaction results in a chain of calls to multiple smart contracts.The sender (which you can access as
sp.sender
) is the account that sent the call to the current smart contract.
In most cases, contracts should use the sender to determine who called them. If they use the source, it's possible for a contract to act as a proxy and impersonate the sender.
For example, assume that account A calls smart contract B and contract B calls contract C. When contract C runs, the source is account A and the sender is contract B. If contract C wants to verify who called it, it should use the sender in most cases. If it uses the source, contract B may be able to impersonate account A in a call to contract C.
Executing multiple token transfers within a single transaction. If one transaction fails, all token transfers fail in that transaction also fail. To distribute tokens, instead of sending them in a single transaction, allow users to claim tokens in individual transactions.
Introducing computations that may lead to gas overflows, such as loops that can run many times.
Performing intensive computations or storing large volumes of data on-chain. Keep private data off-chain. Use on-chain computations solely for tasks that require high trust and public verification. If the data exceeds a few bytes, consider storing references (like hashes) instead of the actual data.
A helpful resource for common pitfalls is opentezos.com/smart-contracts/avoiding-flaws/.
How do I test my SmartPy contracts?
SmartPy provides a robust testing system that allows you to swiftly test code without deploying anything to the blockchain.
Visit the manual to learn more.
How do I return a value from an entrypoint?
Entrypoints cannot return values directly. To return a value from a transaction, you can use a callback, a view, or an event.For more information, see this forum post.
Standards
In there an ERC-20 equivalent?
Indeed, it is called FA2. See the FA2 library.
How do I react to an FA2 transfer?
There is no way to react to a FA2 transfer. The solution is to invert the logic: the receiver now claims its tokens. This way they know the transfer has been done. More information on the forum.
How can I create NFTs with multiple owners?
Technically, a token that multiple people can independently hold and transfer isn't an NFT, because NFTs are unique and have only one owner. You might be referring to a fungible or "semi-fungible" token with a limited quantity. More information can be found here: FA2 library - base classes
Is there an allowance system in the token standard?
FA1.2 standard
The FA1.2 standard has an allowance system. See TZIP-7 and fa1_2.py.
FA2 standard
Instead of an allowance system, the FA2 standard uses an operator system. However, you can implement your own allowance system using the FA2 library. Here is an example.
Here is the desired flow of transactions:
- The user calls
update_operators
and thenupdate_allowance
to set an account as an operator and give that account an allowance. - The operator account calls the contract's
transfer
entrypoint as usual. - The contract uses the operator privilege limited by the allowance system to transfer the tokens.
Note that changing the allowance value from a non-zero value to a non-zero value is forbidden to prevent the corresponding attack vector, however this is not enough on its own to guarantee a safe allowance change. See How to safely change the allowance.