Our goal in this article is to give you a basic understanding of Solidity libraries, their advantages, and how you can implement them in your smart contracts.

A solidity library is similar to a contract that contains reusable code.

There are functions in a library that can be accessed by other contracts.

The cost of gas is reduced when common code is deployed through libraries.

Only pure and view functions can be called directly from outside of the library, since they do not modify state variables.

Due to the assumption that it is stateless, it can’t be destroyed. State variables aren’t present in the library, it can’t inherit anything, and it cannot be inherited.

Syntax

A library in solidity can be constructed using the following syntax:

library <libraryName> {
// Your Code
}

The example below shows the creation of a customized library and its use in solidity contract:

Example:

pragma solidity ^0.8.0;
library My_Library{ // Here we have created a library and have named it as My_Library
function get_String(string memory mrx) public pure returns(string memory){
return mrx;
}
function factorial(uint limit) public pure returns(uint){
if(limit==0){
return 0;
}
else{
uint result = 1;
for (uint i = 2; i <= limit; i++) {
result *= i;
}
return result;
}
}
}
contract SolidityTest{
function use_String_Method_From_My_Library(string memory ample) external pure returns(string memory){
return My_Library.get_String(ample);
}
function calculate_Factorial(uint mrx_Number) external pure returns(uint){
return My_Library.factorial(mrx_Number);
}
}

Similarly, to create a self made library having functions that perform different types of mathematical operations can be done as follow:

Example:

pragma solidity ^0.8.0;
library Mrx_Library{ // Here we have created a library by ourselves and have named it as Mrx_Library
function maximum(uint256 a, uint256 b) public pure returns (uint256) {
return a > b ? a : b;
}
function minimum(uint256 a, uint256 b) public pure returns (uint256) {
return a < b ? a : b;
}
function power(uint256 base, uint256 _exponent) public pure returns (uint256) {
if (_exponent == 0) {
return 1;
} else if (_exponent % 2 == 0) {
uint256 temp = power(base, _exponent / 2);
return temp * temp;
} else {
uint256 temp = power(base, (_exponent -- 1) / 2);
return base * temp * temp;
}
}
function exponent(uint256 x) public pure returns (uint256) {
uint256 result = 1;
uint256 factorial = 1;
for (uint256 i = 1; i <= 10; i++) {
factorial *= i;
result += (x ** i) / factorial;
}
return result;
}
}
contract SolidityTest{ // The use of library functions in the contract can be done as shown below
function get_Maximum(uint mrx,uint ample) external pure returns(uint){
return Mrx_Library.maximum(mrx,ample);
}
function get_Minimum(uint mrx,uint ample) external pure returns(uint){
return Mrx_Library.minimum(mrx,ample);
}
function Calculate_Power(uint mrx,uint ample) external pure returns(uint){
return Mrx_Library.power(mrx,ample);
}
function Calculate_Exponent(uint mrx) external pure returns(uint){
return Mrx_Library.exponent(mrx);
}
}

You can attach library functions from library A to a type B using the directive using A for B. Caller types will be used as the first parameter of these functions (identified using self).

The given program shows the use of a for keyword to create a better understanding among the learners. The following program takes an input from the user and then uses the table() method from the custom library to calculate its table:

Example:

pragma solidity ^0.5.0;
library My_Library{
function table(uint n) public pure returns(uint[] memory) {
uint[] memory table = new uint[](10);
for(uint i = 1; i <= 10; i++) {
table[i-1] = n * i;
}
return table;
}
}
contract SolidityTest{
using My_Library for uint; // Here we have made a use of Library we created above
function get_Table(uint number) external pure returns(uint[] memory){
return My_Library.table(number);
}
}