This blog post provides recommendations for securing smart contracts developed with LIGO and using FA1.2 tokens, as well as shares some overall security tips.
Non-trivial smart contracts can perform elaborate functions, but because of their complexity, they are also harder to secure. Your code, therefore, must be able to respond to unexpected behaviors and known vulnerabilities. In this blog post, we share some overall recommendations for securing smart contracts, as well as more specific guidelines for the contracts written in the LIGO programming language or using FA1.2 tokens.
Overall security recommendations
The first recommendation is adding owners to a smart contract, as there are certain cases, where we need to add simple authorization and access control mechanisms. This can be useful for simple systems or quick prototyping. The code sample below demonstrates how to provide exclusive access to the owners over specific functions.
The second recommendation is adding role-based access control to enable different levels of authorization. A role is an abstract name for the permission needed to access a particular set of resources or entry points. Each role that you want to define can be added as a union type annotation. We manage a
big_map that holds the list of accounts with that role.
Using exceptions with LIGO
If you are writing your contracts with LIGO, the
Failwith functions can be used to check for conditions and throw an exception.
Assert function checks if a certain condition has been met, as if it is not, a smart contract will fail. The
Failwith function causes a smart contract to fail with an error message, and it requires, in general, a type annotation on the
We can categorize exceptions into three types:
- Business exceptions that check specific business logic in the application and throw an exception. For example, if an account has liquidity to perform some action.
- Basic contract validations that check simple logic validations. For instance, if a value is zero or if a specific variable exists.
- Exceptions for inter-contract invocation that validate the existence of a smart contract to be invoked, so we can call a method safely.
Note that error messages can become redundant when using the
Failwith function. To avoid repetition, maintain all error messages in a separate file and simply invoke the error code needed. This method also makes it easier to update and add error messages.
Working with FA1.2 tokens
You can prevent the transfer of tokens to the same address of the FA1.2 smart contract. In this case, add a validation in the main function of the FA1.2 smart contract checking for the
amount reserved word.
To prevent the ERC20 attack vector breaches, do not change allowance values of the variables to non-zero if the previous value was also set to non-zero.
Final thoughts and considerations
While there are specific best practices that you can implement to secure your non-trivial smart contracts, there are also general steps you can take to enhance security. Learn about existing vulnerabilities and stay up-to-date with the latest releases from Tezos.
In this GitHub repository, you can check out real-world smart contracts, and how we make use of the above-mentioned recommendations when building them.