Testing Your Precompile
Learn how to test your precompile using Hardhat.
Just like with the Calculator precompile, we want to test the functionality of our precompile to make sure it behaves as intended.
Although we can write tests in Go, this is not the only way we can test our precompile. We can leverage Hardhat, a popular smart contract testing framework, for testing.
In this section, we'll cover writing the smart contract component of our tests and setting up our testing environment so that precompile-evm can execute these tests for us.
Structure of Testing with Hardhat
For StringStore
, we'll need to complete the following tasks in order to leverage Hardhat:
- Define the Genesis JSON file we want to use for testing
- Tell precompile-evm what Hardhat script to use to test
StringStore
- Write the smart contract that will hold the test cases for us
- Write the actual script that will execute the Hardhat tests for us
Defining the Genesis JSON
The easiest part of this tutorial, we will need to define the genesis state of our testing environment. For all intents and purposes, you can copy the genesis JSON that you used in the Defining Default Values section and paste it in precompile-evm/tests/precompile/genesis
, naming it StringStore.json
(it is important that you name the genesis file the name of your precompile).
Telling Precompile-EVM What To Test
The next step is to modify suites.go
and update the file so that precompile-evm can call the Hardhat tests for StringStore. Go to precompile-evm/tests/precompile/solidity
and find suites.go
. Currently, your file should look like the following:
If you view the comments generated, you will already see a general structure for how we can declare our tests for precompiles. Let's take this template and use it to declare the tests for StringStore!
Again, the naming conventions are important. We recommend you use the same name as your precompile whenever possible.
Defining Test Contract
In contrast to using just Go, Hardhat allows us to test our precompiles using Solidity.
To start, create a new file called StringStoreTest.sol
in precompile-evm/contract/contracts
. We can start defining our file by including the following:
As of right now, there are two important things to note.
We are first importing test.sol
, a testing file that includes a range of assertion functions to assert that our outputs are as expected. In particular, these assertion functions are methods of the DSTest contract.
Next, we are importing the interface of the StringStore precompile that we want to test.
With this in mind, let's fill in the rest of our test file:
In the contract StringStoreTest
, we are inheriting the DSTest contract so that we can leverage the provided assertion functions. Afterward, we are declaring the variable stringStore so that we can directly call the StringStore precompile. Next, we have the two testing functions.
Briefly looking at the logic of each test function:
step_getString
: We are testing that the getString function returns the default string defined in the genesis JSON (in this example, the default string is set to "Cornell")step_getSet
: We are assigning a new string to our precompile and making sure that setString does so correctly
We now want to note the following two details regarding Solidity test functions in Hardhat:
- Any test functions that you want to be called must start with the prefix "step"
- The assertion function you use to check your outputs is
assertEq
With our Solidity test contract defined, let's write actual Hardhat script!
Writing Your Hardhat Script
To start, go to precompile-evm/contracts/test
and create a new file called StringStore.ts
. It is important to name your TypeScript file the same name as your precompile. Here are the steps to take when defining our Hardhat script:
- Specify the address at which our precompile is located
- Deploy our testing contract so that we can call the test functions
- Tell Hardhat to execute said test functions
To make our lives even easier, Subnet-EVM (a library that Precompile-EVM leverages) has helper functions to call our test functions simply by specifying the names of the test functions. You can find the helper functions here: https://github.com/ava-labs/subnet-evm/blob/master/contracts/test/utils.ts.
In the end, our testing file will look as follows:
Running Your Hardhat Test
To run your HardHat tests, first change to the root directory of precompile-evm and run the following command:
Afterward, run the following command:
The variable GINKGO_LABEL_FILTER
simply tells precompile-evm which tests suite from suites.go
to execute. Execute the StringStore
test suite.
However, if you have multiple precompiles to test, set GINKGO_LABEL_FILTER
equal to "Precompile." You should see something like the following:
Congrats, you can now write Hardhat tests for your stateful precompiles!