Making a small Library in Solidity
Tags: blockchain, solidity, ethereum, javascript
Published: 2021-01-11 20:59:04

Hello guys, hope you all are doing great!!! 😎. 
Blockchain is quite popular these days. I mean it is the frenzy on the net especially with the upsurge of Bitcoin's value. Following the trend, I would be writing the greatest article of all time. 😈. I'm joking.. lol.
So in this post, I would be talking about how I created a small Library in Solidity.
What prompted me to do this was due to the fact that I needed a way to recreate a function in Solidity that behaves like the JavaScript function below. 
```js
function getPositiveAndSquare(arr){
  return arr.filter(i=>i>0).map(i=>i*i)
}

console.log(getPositiveAndSquare([2,3,4,0,2]))
// returns [4,9,16,4]
```
The function above takes in an array as an argument, filters the numbers in the array by leaving only the positive numbers and finally it transforms the positive numbers to its square 🥱. Ok, this seems quite easy to do in JavaScript but trying to replicate a function that has similar logic in Solidity wasn't that straight forward.

So to work it out, I entered the avatar state to unlock my chakra 🦾. 
![AvatarState](https://cdn.pixabay.com/photo/2019/03/07/04/55/cyborg-4039511_960_720.jpg)

But it was too much to handle, making me spend a lot of time figuring it out. This made me ask my self the big question, **Is my state authentic?**, **can I bend?**, **can I code?**, **Is solidity for me?**. I felt like crying but then I heard a voice from above speak to me. 
The voice made me feel energized and I felt at one with my code. I call this **entangled enlightenment** or what mortals call the **flow state**. 
I began to see the hidden codes of the universe unfettered. I could see images and text in plain binary format. At this point, I was ready to solve this 😎

## My Solution to the problem

```js
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

library util {
    function filterFunc(
        int256[] memory self,
        function(int256) pure returns (uint256) f
    ) internal pure returns (uint256[] memory newArr) {
        uint256[] memory tempArr = new uint256[](self.length + 1);

        for (uint256 i = 0; i < self.length; i++) {
            if (self[i] > 0) {
                tempArr[tempArr.length - 1] = tempArr[tempArr.length - 1] + 1;
                tempArr[tempArr[tempArr.length - 1] - 1] = f(self[i]);
            }
        }

        newArr = new uint256[](tempArr[tempArr.length - 1]);
        for (uint256 j = 0; j < newArr.length; j++) {
            newArr[j] = tempArr[j];
        }
    }
}

contract MyContract {
    using util for int256[];

    function getPositiveAndSquare(int256[] memory arr)
        public
        pure
        returns (uint256[] memory)
    {
        return arr.filterFunc(square);
    }

    function square(int256 val) private pure returns (uint256) {
        return uint256(val * val);
    }
}

```
## Code flow
First I created a contract named, **MyContract**.  Inside the contract, I created a function named, **getPositiveAndSquare**. 
```js
function getPositiveAndSquare(int256[] memory arr)
        public
        pure
        returns (uint256[] memory)
    {
        return arr.filterFunc(square);
    }
```
The **getPositiveAndSquare** function  accepts an array with values of unsigned integers with **memory** as its storage location and **arr** as its parameter name. It returns an array of unsigned integers.

Within the  **getPositiveAndSquare** function you can see the **filterFunc** method being appended to the **arr** parameter. This is made possible with the creation of a solidity library which has a function (**filterFunc**) that conforms to the same type as  **arr** (int256 ).  The **filterFunc** function accepts a function named **square**.

Checking the definition of the **filterFunc** function in the Library section you can see that it accepts two parameters.   

So why am I passing only the **square** function into it? This is because the **arr** parameter conforms with the type definition of the first **filterFunction** parameter. So the **arr** paremter becomes the first argument of the **filterFunc** function while the **square** function becomes its second argument.

The **square** function takes in a signed integer and returns an unsigned integer. 
```js
    function square(int256 val) public pure returns (uint256) {
        return uint256(val * val);
    }
```

This is because the **square** function acts on the signed integers of the **self** parameter of the **filterFunc** function. The types have to be same to prevent errors. It returns an unsigned integer because the returned value must be a positive integer.

In the contract, **MyContract**, you can see this line:
```js
using util for int256[];
```
This means attach Solidity's library functions to a type of int256[] in the Contract.
That is what made attaching **filterFunc** to **arr** possible. It also made **arr** to be the first argument of the **filterFunc** function.

In the library, I only have one function named, **filterFunc**. It has two parameters **self** and **f** 

 ```js
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

library util {
    function filterFunc(
        int256[] memory self,
        function(int256) pure returns (uint256) f
    ) internal pure returns (uint256[] memory newArr) {
        uint256[] memory tempArr = new uint256[](self.length + 1);

        for (uint256 i = 0; i < self.length; i++) {
            if (self[i] > 0) {
                tempArr[tempArr.length - 1] = tempArr[tempArr.length - 1] + 1;
                tempArr[tempArr[tempArr.length - 1] - 1] = f(self[i]);
            }
        }

        newArr = new uint256[](tempArr[tempArr.length - 1]);
        for (uint256 j = 0; j < newArr.length; j++) {
            newArr[j] = tempArr[j];
        }
    }
}
```

The reason why this took longer than expected to implement is that memory arrays don't implement the **pop** and **push** functions as a member, the **length** member is read-only and Solidity's library doesn't allow defining state variables in it. 

So to get around this barrier, I had to create a new memory array called **tempArr**.  The **tempArr** was created to be one index longer than the **self** array. I used the last index of the **tempArr** to store the number of positive values in the **self** array and the other indexes to store the square of the positive values in **self** array. 

When creating a dynamic memory array in solidity, all the indexes are initialized with 0 for the int type.
So that means all or not all the indexes of the **tempArr** array would be updated. Some would remain zero.  For instance, check the pseudo code below
```js
//self array
self = [2,3,0,-1]
//during initialization of tempArr
temArr = [0,0,0,0,0]
//after lopping through self array
tempArr = [4,9,0,0,2]
```
Finally, I created a dynamic memory array called **newArr**.  It was constructed using the value of the last index of **tempArr** as its length while being populated with the values of tempArr up to the index of a value of the last index of **tempArr**.

So that is how I was able to implement the filter function in solidity

*Note: this post is based on solidity version 0.8.0*

And I hope you learnt something new about solidity 😁. You can help me share it too and comment. Thanks a lot 🙏