Testing

Discover how to effectively test smart contracts on ZKsync Era ecosystem.

Welcome back to our ZKsync 101 series, your fast-track to ZKsync development! In this third guide, we transition from deploying and managing contracts to the critical phase of testing. This guide will walk you through the steps to ensure your CrowdfundingCampaign contract, introduced in our first guide and efficiently deployed through contract factories in the second, work flawlessly.

Elevate your ZKsync toolkit with robust contract testing techniques.

Craft comprehensive tests for your CrowdfundingCampaign to ensure reliability and security.

Use Hardhat to write and run tests, ensuring your campaigns are ready.

Setup the project

Make sure to go through the setup provided in the initial Getting started section. You will have downloaded the 101 project through ZKsync CLI create. Since we are using hardhat-zksync for testing, you do not need to have the in memory node running for this section.

If your local in-memory node is running, stop it with the following command:

zksync-cli dev stop

hardhat-zksync-node

Testing contracts requires a more structured setup. We'll use hardhat-zksync-node which is a part of the hardhat-zksync package to run tests against its own implementation of the in memory node.

Within the hardhat.config.ts, you'll observe the zksync flag set to true under the hardhat network, indicating the integration with ZKsync's testing environment.

hardhat.config.ts
const config: HardhatUserConfig = {
  defaultNetwork: "inMemoryNode"
  networks: {
    ...
    hardhat: {
      zksync: true,
    },
    ...
  }
  ...
}

Your project has npm scripts for testing that set the --network to "hardhat".

Secondly within the hardhat.config.ts, you'll observe the importing of @nomicfoundation/hardhat-chai-matchers. This plugin provides Hardhat with an extended suite of assertion methods tailored for contract testing, significantly improving the testing toolkit available for your project.

import "@nomicfoundation/hardhat-chai-matchers";

Compile the CrowdfundingCampaign contract

Now that our setup is complete, it's time to focus on the core of this guide - testing our CrowdfundingCampaign.sol contract.

Thorough testing involves scrutinizing every function and aspect of our contract, including potential failure scenarios. In this guide, we'll focus in on the contribute method to ensure it's tested.

To compile the contracts in your project, run the following command:

npm
npm run compile

Test CrowdfundingCampaign

This section describes testing the CrowdfundingCampaign.sol contract. Let's review the contract at test/1-hello-zksync/CrowdfundingCampaign.test.ts

  • Initialization: Each test case initializes with fresh contract instances in the beforeEach and predefined rich wallet accounts to simulate various contributors and the contract owner.
  • Deployment: The CrowdfundingCampaign contract is deployed using the deployContract utility, setting a specific funding goal for each test scenario.

contribute Method Tests:

  • Zero Contributions: Verifies that the contract correctly rejects contribution attempts with zero value, ensuring the integrity of the contribution process.
  • Funds Aggregation: Tests the contract's ability to accurately aggregate contributions from multiple addresses and update the totalFundsRaised accordingly.
  • Goal Achievement: Checks for the GoalReached event emission upon meeting the funding goal, confirming the contract's responsiveness to achieving its set target.

Run the tests with the following command:

npm
npm run test:crowdfunding-campaign

Upon completion, the test suite will provide a summary of all executed tests, indicating their success or failure:

  CrowdfundingCampaign
    contribute
 should reject contributions of 0
 should aggregate contributions in totalFundsRaised (150ms)
 should emit GoalReached event when funding goal is met (81ms)
    withdrawFunds
 should revert if called by a non-owner
 should revert if funding goal hasn't been reached
      ✔ should transfer the funds to the owner when funds have been raised (229ms)
    getFundingGoal
      ✔ should return the correct funding goal
    getTotalFundsRaised
      ✔ should return 0 when no contributions have been made


  8 passing (2s)

🎉 Congratulations! Your CrowdfundingCampaign contract has been thoroughly tested and is ready for action.

Takeaways

  • Testing: Understanding contract testing is important for ensuring the reliability and security of your smart contracts on ZKsync. Proper testing safeguards against unforeseen errors and vulnerabilities.
  • Comprehensive Coverage: Achieving comprehensive test coverage, including both positive and negative testing scenarios, is essential for a robust smart contract. This guide emphasized the contribute method, but testing should encompass all aspects of your contract.
  • Tooling Efficiency: Leveraging Hardhat for testing provides a streamlined and efficient workflow. These tools offer powerful features and plugins, like @nomicfoundation/hardhat-chai-matchers, that enhance the testing process.

Next Steps

With a solid foundation in contract testing, you're well-equipped to advance your ZKsync development journey. Consider the following steps to further your expertise:

  • Upgradeability: Dive into the Upgradeability guide focusing on contract upgradeability. Learning to make your contracts upgradeable will enable you to update and improve your smart contracts over time without losing state or funds.
  • Advanced ZKsync Integrations: Explore deeper into ZKsync's ecosystem by implementing features like account abstraction and paymasters to enhance user experience and contract flexibility.
  • Community Engagement and Contribution: Join the vibrant ZKsync developer community. Participate in forums, Discord, or GitHub discussions. Sharing insights, asking queries, and contributing can enrich the ecosystem and your understanding of ZKsync.

Made with ❤️ by the ZKsync Community