SMTChecker: The Game Changer in Smart Contracts Verification and Security

Introduction
In the world of smart contracts, their verification and ensuring security and reliability is of utmost importance. With the increasing adoption of blockchain technology, smart contracts often manage valuable assets, and any vulnerability could lead to significant financial losses or other adverse consequences. To address this concern, verification and security auditing of smart contracts has become a critical aspect of the development process.

In this blog post, we will discuss how the SMTChecker, a powerful formal verification tool, can be used to enhance the security auditing process. This blog post builds upon our previously written blog posts, Formal Verification Made Easy with SMTChecker and SMTChecker and SMT Solvers: Exploring Formal Verification One Step at a Time. If you have not read them already, now is a good time for a refresher. In this blog post, we will demonstrate SMTChecker’s capabilities using the Horse contract, highlighting the importance of security auditing and how Truscova leverages the SMTChecker to provide top-class security auditing services. By the end of this article, you'll see why Truscova should be your first choice for smart contract audits.

Boost Your Smart Contract Security
Contact us

Table of Contents:
  1. The Importance of Security Auditing for Smart Contracts
  2. Introducing the SMTChecker
  3. Analyzing the Horse Contract with SMTChecker
  4. How Truscova Uses SMTChecker for Security Auditing
  5. Conclusion

The Importance of Security Auditing for Smart Contracts
Security auditing plays a vital role in the development and deployment of smart contracts. By thoroughly analyzing and verifying the contract code, security auditing ensures the correctness, reliability, and security of smart contracts. This process is essential for:
  • Protecting valuable assets managed by smart contracts
  • Building trust among users and stakeholders
  • Reducing the risk of financial losses due to vulnerabilities or bugs
  • Adhering to industry best practices and regulatory requirements
Given the high stakes involved, it is crucial to choose an experienced and trusted security auditing provider for your smart contracts. Truscova stands out as a premier choice, thanks to its comprehensive auditing process and the use of advanced tools such as the SMTChecker.

Get Peace of Mind with Truscova’s Security Auditing Services
Contact us

Introducing the SMTChecker
The SMTChecker is a formal verification tool integrated into the Solidity compiler. It automatically checks smart contracts for potential bugs and vulnerabilities using advanced techniques like SMT solvers and the Constrained Horn Clauses (CHC) engine. With the SMTChecker, you can:
  • Analyze execution paths and conditions in the contract code
  • Detect unreachable code, always true/false conditions, and verify invariants
  • Complement traditional testing methods, such as unit tests and integration tests
The SMTChecker is a powerful addition to the security auditing toolbox, helping to ensure that your smart contracts are free of vulnerabilities and function as intended. You can read our previous blog posts: Formal Verification Made Easy with SMTChecker and SMTChecker and SMT Solvers: Exploring Formal Verification One Step at a Time, on SMTChecker to know more about its capabilities.

Don't Leave Your Smart Contracts to Chance – Choose Truscova
Contact us

Analyzing the Horse Contract with SMTChecker:
To illustrate the capabilities of the SMTChecker, let's consider a sample Horse contract (Figure 1) with various movement functions.

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;

// Define a contract representing a horse that moves like a knight in chess
contract Horse {
    // Position of the horse on a chess board represented by x and y coordinates
    int8 private posX;
    int8 private posY;

    // Check if the horse's current position is within the bounds of an 8x8 chess board
    function isWithinBounds() internal view returns (bool) {
        return posX >= 0 && posX < 8 && posY >= 0 && posY < 8;
    }

    // Move the horse 1 step in the x-direction and 2 steps in the y-direction
    function step1() public {
        posX += 1;
        posY += 2;
        require(isWithinBounds());
    }

    // Move the horse 2 steps in the x-direction and 1 step in the y-direction
    function step2() public {
        posX += 2;
        posY += 1;
        require(isWithinBounds());
    }

    // Move the horse 2 steps in the x-direction and 1 step in the negative y-direction
    function step3() public {
        posX += 2;
        posY -= 1;
        require(isWithinBounds());
    }

    // Move the horse 1 step in the negative x-direction and 2 steps in the negative y-direction
    function step4() public {
        posX -= 1;
        posY -= 2;
        require(isWithinBounds());
    }
// Move the horse 1 step in the negative x-direction and 2 steps in the y-direction
    function step5() public {
        posX -= 1;
        posY += 2;
        require(isWithinBounds());
    }

    // Move the horse 2 steps in the negative x-direction and 1 step in the y-direction
    function step6() public {
        posX -= 2;
        posY += 1;
        require(isWithinBounds());
    }

    // Move the horse 2 steps in the negative x-direction and 1 step in the negative y-direction
    function step7() public {
        posX -= 2;
        posY -= 1;
        require(isWithinBounds());
    }

    // Move the horse 1 step in the negative x-direction and 2 steps in the negative y-direction
    function step8() public {
        posX -= 1;
        posY -= 2;
        require(isWithinBounds());
    }

    // Verify the horse is not at the destination position (7, 7) on the chess board
    function inv1_CheckNotAtDestination() public view {
        assert(!(posX == 7 && posY == 7));
    }
    
    // Verify the horse is not at the destination position (3, 4) on the chess board
    function inv2_CheckNotAtDestination() public view {
        assert(!(posX == 3 && posY == 4));
    }
}
Figure 1: Horse contract to implement Knight's moves on 8x8 chess board. [Github link]

It simulates the movements of a knight piece in a chess game on an 8x8 board. It keeps track of the knight's position on the board and implements various movement functions, allowing the knight to move according to the standard chess rules.

Here's a brief description of the Horse contract:
  • It maintains two private int8 variables, posX and posY, which represent the knight's current position on the 8x8 chessboard.
  • The contract has an internal function, isWithinBounds, which checks if the knight's current position is within the bounds of the chessboard.
  • There are eight public movement functions, step1 to step8, which update the knight's position according to the allowed knight moves in chess (L-shaped moves, consisting of two squares in one direction and one square in another direction). Each function also checks if the new position is valid using the isWithinBounds function and requires it to be true.
  • Additionally, the contract has a two invariants, inv1_CheckNotAtDestination and inv2_CheckNotAtDestination , which checks if the knight has not reached the destination square (7,7) and (3,4) on the chessboard.
When analyzing this contract, the SMTChecker can:
  • Identify issues with state properties and arithmetic operations
  • Detect an assertion violation and provide insights into potential fixes
  • Highlight the benefits of using SMTChecker in the security auditing process
In order to setup your Hardhat or Foundry project for running the SMTChecker, please follow our previous blog articles – Formal Verification Made Easy with SMTChecker and SMTChecker and SMT Solvers: Exploring Formal Verification One Step at a Time. Once setup, run build the smart contract. It will automatically use the SMTChecker in the background.At successful completion, the following output should appear on your screen (Figure 2):

Warning: CHC: Assertion violation happens here.
Counterexample:
posX = 7, posY = 7

Transaction trace:
Horse.constructor()
State: posX = 0, posY = 0
Horse.step2()
    Horse.isWithinBounds() -- internal call
State: posX = 2, posY = 1
Horse.step2()
    Horse.isWithinBounds() -- internal call
State: posX = 4, posY = 2
Horse.step5()
    Horse.isWithinBounds() -- internal call
State: posX = 3, posY = 4
Horse.step3()
    Horse.isWithinBounds() -- internal call
State: posX = 5, posY = 3
Horse.step1()
    Horse.isWithinBounds() -- internal call
State: posX = 6, posY = 5
Horse.step1()
    Horse.isWithinBounds() -- internal call
State: posX = 7, posY = 7
Horse.inv1_CheckNotAtDestination()
  --> contracts/Horse.sol:73:9:
   |
73 |         assert(!(posX == 7 && posY == 7));
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Warning: CHC: Assertion violation happens here.
Counterexample:
posX = 3, posY = 4

Transaction trace:
Horse.constructor()
State: posX = 0, posY = 0
Horse.step2()
    Horse.isWithinBounds() -- internal call
State: posX = 2, posY = 1
Horse.step2()
    Horse.isWithinBounds() -- internal call
State: posX = 4, posY = 2
Horse.step5()
    Horse.isWithinBounds() -- internal call
State: posX = 3, posY = 4
Horse.inv2_CheckNotAtDestination()
  --> contracts/Horse.sol:78:9:
   |
78 |         assert(!(posX == 3 && posY == 4));
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Figure 2: Output after using SMTChecker on Horse contract.

The high-level idea is that in our invariants, inv1_CheckNotAtDestination and inv2_CheckNotAtDestination, we tell SMTChecker that the positions (7,7) and (3,4) are not reachable. However, SMTChecker tell us that we are wrong and it lays out a step-by-step path (trace) to show how the aforementioned positions can be reached. This also shows the power of SMTChecker and formal verification. Hence, by leveraging the SMTChecker, potential issues are identified and addressed early in the development process, ensuring a more secure and reliable smart contracts.

Experience Unrivaled Security Analysis with Truscova
Get in touch

How Truscova Uses SMTChecker for Security Auditing
Truscova takes security auditing to the next level by incorporating formal verification techniques, such as the SMTChecker, into its auditing process. This approach provides numerous benefits:
  • Improving overall security by identifying and addressing potential vulnerabilities
  • Enhancing contract reliability by detecting unreachable code and verifying invariants
  • Strengthening client trust by providing rigorous analysis of smart contracts
  • Saving time and resources by automating part of the auditing process
  • Standing out in the market by demonstrating a commitment to high-quality, secure, and reliable smart contract auditing services

By using the SMTChecker alongside other testing and verification methods, Truscova ensures comprehensive security analysis of your smart contracts. This commitment to excellence makes Truscova the first choice for organizations looking to safeguard their valuable assets on the blockchain.

Safeguard Your Valuable Assets on the Blockchain with Truscova’s Security Auditing Services
Contact us

Conclusion
Security auditing plays a crucial role in the development of robust and secure smart contracts. The SMTChecker is a powerful tool that can significantly enhance the auditing process by detecting potential issues and verifying invariants. By leveraging the SMTChecker, Truscova can provide top-class security auditing services, ensuring that smart contracts are reliable, secure, and meet the highest industry standards.



About Truscova:
Truscova comes with 30+ years of academic research and hundreds of academic publications which pioneered the area of Formal Verification. The team combines academic leadership, industrial strength and Blockchain expertise. Truscova currently analyzes Solidity code combining Formal Verification techniques: abstract interpretation, constraint solving, theorem proving, and equivalence checking.


Ready To Take
The Next Step?

Contact Us

Contact

Truscova GmbH
Bremen | Germany
E-Mail

Social Media



©2022 | Imprint & Privacy Policy