Test the smart contract

The high value and immutable nature of smart contracts proves the importance of testing smart contract code without exception. Reducing loopholes and errors in the contract is a top priority for the developer of the contract.

Why test smart contracts

  1. Smart contracts are of high value

Smart contracts often deal with high-value financial assets, especially in industries such as decentralized finance, and valuable items such as non-fungible tokens. Therefore, small bugs in smart contracts can and usually will cause huge, irreparable losses to users. However, comprehensive testing can expose bugs in smart contract code and reduce security risks before deployment.

  1. Smart contracts are immutable

Smart contracts deployed in the HAH virtual machine (EVMC) are immutable by default. While traditional developers may be used to fixing software bugs after release, HAH development leaves little room for patching security holes once smart contracts are running on the blockchain.

While upgradeability mechanisms exist for smart contracts, such as the proxy model, these can be difficult to implement. In addition to reducing immutability and introducing complexity, upgrades often require complex governance processes. In most cases, upgrading should be considered a last resort and should be avoided unless necessary. Detecting potential vulnerabilities and flaws in smart contracts during the pre-release phase reduces the need for logic upgrades.

Testing and Formal Verification

While testing helps confirm that a contract returns the expected results for certain data inputs, it cannot conclusively prove that the same is true for inputs that were not used during testing. Testing a smart contract does not guarantee "functional correctness," meaning it cannot show that the program behaves with all input values and sets of conditions.

Therefore, we encourage developers to incorporate formal verification into their approach to assessing the correctness of smart contracts. Formal verification uses formal methods—rigorous mathematical methods for specifying and verifying software.

Formal verification is considered important for smart contracts because it helps developers formally test assumptions related to smart contracts. The approach is to create a formal specification describing the properties of the smart contract and verify that the formal model of the smart contract matches the specification. This approach increases confidence that the smart contract will only perform the functions defined in its business logic and nothing else.

Automated Test

Automated testing involves scripting tests of smart contracts using automated tools. The technology relies on automated software that can perform repeated tests to find flaws in smart contracts. Automated testing is efficient, uses fewer resources, and provides better coverage than manual analysis. Automated testing tools can also configure test data, allowing them to compare predicted behavior with actual results.

Function Test

Functional testing verifies the functionality of the smart contract and ensures that every function in the code works as expected. Functional testing requires understanding how your smart contract behaves under certain conditions.

You can then test each function by running calculations with selected values and comparing the returned output with the expected output. Functional testing covers three approaches: unit testing, integration testing, and system testing.

Unit Test

Unit testing needs to test each component of the smart contract separately to ensure its correctness.

Unit tests are simple, run quickly, and provide a clear understanding of what went wrong when a test fails. Unit testing is essential for smart contract development, especially when you need to add new logic to your code. You can verify the behavior of each function and confirm that it performs as expected. Running unit tests often requires creating assertions — simple, informal statements specifying requirements of a smart contract. Unit tests can then be used to test each assertion to see if it holds when executed.

Examples of assertions related to contracts include:

  • Only admins can suspend contracts

  • Non-admins have no right to mint new tokens

  • The contract will be reverted on error

Integration Test

In the test hierarchy, integration tests are at a higher level than unit tests. In integration testing, the individual components of the smart contract are tested together. This approach detects bugs caused by interactions between different components of a contract or across multiple contracts.

You should use this method if you have a complex contract with multiple functions or a contract that interacts with other contracts. Integration tests help ensure that things like inheritance and dependency injection work correctly.

System Test

System testing is the final stage of smart contract functional testing. The system evaluates the smart contract as a fully integrated product to see if it performs as specified in the technical requirements.

You can think of this stage as an end-to-end process of checking the smart contract from the user's perspective. A good way to perform system testing on a smart contract is to deploy it in a production-like environment, such as a testnet or a development network.

Here, end users can conduct test runs and report any issues with the contract's business logic and overall functionality. System testing is important because you cannot change the code once the contract is deployed in the main HAH virtual machine environment.

Last updated