Creating upgradable smart contracts using TDD

Creating upgradable smart contracts using TDD

Introduction

Creating an upgradable smart contract is a complex task that needs to be carefully managed. In this article, we will discuss how to use a test-driven approach to create upgradable smart contracts.

Test-driven development is an important part of software development and is a great way to ensure that the code is correct and works as expected. With the help of test-driven development, developers can create upgradable smart contracts that are reliable and have a long lifespan. We will also discuss how to use automated tests to check the correctness of the code and ensure that it is secure.

Benefits of Test-Driven Development

Test-driven development (TDD) is a powerful tool that can be used by software development teams to help them produce high-quality products. In TDD, tests are written before the code, so that developers can ensure that the product they are producing meets the requirements, and is of the highest possible standard. Let's say there is a software development team that is tasked with creating a new product. Without TDD, the team might go straight into writing code with no checks and balances to ensure it meets the needs of the customer.

But, with TDD, the team can first write tests before the code, so that they can ensure that the resulting code meets all of the requirements for the product. Moreover, TDD provides the team with an opportunity to review their code, identify any mistakes and make improvements before it is shared with the customer. Having tests before the code also means that the team can more easily spot any issues that could arise with the product in the future, as well as ensure that any changes or updates to the code are done correctly.

Overall, TDD is a powerful tool that allows developers to produce high-quality products that meet customer requirements, while also saving time and money in the long run by preventing potential mistakes and issues.

Overview of Test-Driven Smart Contract Development

Test-driven smart contract development is an approach to developing smart contracts for blockchains using automated tests to guide the design and build process. By breaking the development cycle into small incremental steps, the developer can write code with greater confidence, reducing the risk of bugs or unexpected behavior.

By writing automated tests first and then writing the contract code that passes the tests, it's possible to validate the correctness of the code and document the expected behavior of the contract. This approach gives developers greater confidence in the code that they write and helps ensure that their code works as expected.

Prerequisites:

• Knowledge of the fundamentals of smart contract development

• Understanding of blockchain technologies and version control systems.

• Understanding of automated testing concepts

• Experience with scripting languages such as JavaScript or Python

• Experience with development environments such as Nodejs

• Familiarity with smart contract development tools such as Hardhat and Truffle

We will be creating a library system built on the Ethereum blockchain.

The project prompt is shown below;

A Library System built on the Smart Contract is a way to create a decentralized and secure platform for borrowing, returning, and tracking books.

It provides an efficient and secure way to manage a library's assets and transactions. Through the use of a blockchain-based smart contract, the Library System eliminates manual processes associated with the lending and returning of books.

The system is designed with data privacy and security in mind, ensuring that only authorized parties can access the Library System. The Smart Contract also automates the tracking of books and keeps a record of borrowers and their loan history, allowing library staff to track library assets and monitor usage.

Furthermore, the smart contract ensures efficient book management and provides a secure, tamper-proof record of library transactions. It also enables library staff to streamline the administering of library policies and procedures.

The Library System empowers libraries to keep track of their assets, streamline their book processing, and ensure the security of their data.

In order to have a better grasp of the prompt above, we need to create a system design for the system.

System Design for a Library System on Smart Contract

Overview:

This system design is for a Library System built on the Smart Contract. It will enable users to sign up and register as members, add the book(s) to the library, search and borrow books, keep track of book loans and overdue payments and manage library inventory.

Functional Requirements:

• User Registration and Login: Users should be able to register and log in to the library system.

• Book Management: Users should be able to add, search and delete books from the library system.

• Book Lending: Users should be able to check out books from the library and have the option to renew the loaned book.

• Payment Management: Users should be able to pay an overdue payment for any loaned books.

• Inventory Management: The library system should be able to keep track of the library inventory and notify the library staff when there are insufficient books for lending.

For our case, we will be focusing on Book management, where users can add, search and delete books.

We will be working with hardhat, and also instead of installing all the dependencies on our local machine, we will be using gitpod.

To get started, we will need a GitHub account, then create a new repository, and give it a name.

In our case, we will name our repository SmartLibrary,

Then, in the address bar, append the GitHub URL with gitpod.io/#

This will create a gitpod workspace.

Now, we need to install hardhat and create an empty hardhat project.

in the terminal, type

npm init -y  && npm install  --save-dev hardhat

The command above will create a package.json file and also install hardhat as a development dependency.

Next, we create an empty hardhat project with the command,

npx hardhat init

then choose, `create an empty hardhat.config.js.`

Next, we create a folder test, this folder is where all our tests will be written. In the test folder, create a file bookManagement.test.js For our tests, we will need an assertion library, so we will install chai, and hardhat-toolbox.

npm i -D chai @nomicfoundation/hardhat-toolbox

Then we add the hardhat-toolbox dependency in our hardhat.config.js file

In the bookManagement.test.js file, add the following code,

const { expect } = require("chai");


describe("Book management", () => {
    before(async () => {
        this.Library = await ethers.getContractFactory("Library");
    })

    beforeEach(async () => {
        this.library = await this.Library.deploy();
        await this.library.deployed();
        await this.library.createBook("Lord of the Flies", "William Golding");
    })

    it("user should be able to add a book", async () => {
        const value = await this.library.getBook(0)
        expect(value).not.to.be.undefined
    })
    it("user should be able to get a book title and the author name", async () => {
        const value = await this.library.getBook(0)
        expect(value.toString()).to.equal("Lord of the Flies,William Golding")
    })
})

We then run the test,

npx hardhat test

We should have this showing in the terminal

Now, let’s create a contracts folder, then create the Library.sol in the folder. In the Library.Sol file

Add the following to the file;

// SPDX-License-Identifier == Unlicensed

pragma solidity ^0.8.0;

contract Library{

}

Now run the test again,

npx  hardhat test

We should have the error below in our test;

Now, we begin to create our smart contract and the functions to pass the test.

In the Library.sol file add the following code;

// SPDX-License-Identifier == Unlicensed

pragma solidity ^0.8.0;

contract Library{

    struct Book{
        string title;
        string authorName;
    }

    Book[] public books;


    function createBook( string memory title , string memory author ) public {
       Book memory newBook = Book(title,author);
        books.push(newBook);
    }

    function getBook(uint index) public view returns (Book memory){
        return books[index];
    } 

}

Now if we run the test again, the two test cases should pass;

Challenges of Test-Driven Smart Contract Development

Though Test driven smart contract development seems to be the silver bullet for creating a smart contract, the blockchain itself creates some barriers to making this process hassle-free. Some of the challenges are as follow;

1. Difficulty in debugging: Debugging a smart contract can be a difficult process since there is no way to access a local console or step through the code. Debugging can only be done on the blockchain and finding smart contract errors can be confusing and time-consuming.

2. Difficulty in writing tests that uncover bugs: Writing tests for smart contracts is a tricky process since even subtle changes can have a huge impact on the contract’s behavior. Additionally, writing tests that can uncover potential bugs can be difficult since bugs can be hard to predict.

3. Difficulty in setting up the testing environment: Smart contract testing requires setting up specialized tools in order to simulate the environment in which the contracts will be executed. This process can be time-consuming and difficult to manage, particularly in dynamic and collaborative development environments.

4. Limited resources and tools: There is currently a limited number of resources and tools available for test-driven smart contract development. Many of the existing tools are either incomplete, too complex, or difficult to use, making development unnecessarily difficult and time-consuming.

5. Difficulty in establishing standards and best practices: Establishing standards and best practices for test-driven smart contract development are difficult due to the lack of industry-wide agreement. Without a set of agreed-upon standards, it can be difficult to ensure the quality and reliability of smart contracts, as well as the security of user data.

Conclusion

In this article, we have been able to go through the TDD landscape and also built a smart contract with hardhat.

Creating upgradable smart contracts using Test Driven Development is a cost-effective and secure way to develop decentralized applications. By focusing on the testing phase of development, developers can build reliable and maintainable smart contracts, while reducing the risk of errors in their code.

For more content like this, you can reach out to me on Twitter and Linkedin

#tdd #smartcontracts #blockchain #cryptocurrency