What are Solidity libraries
Libraries in Solidity smart contracts are blocks of reusable code. They contain functions used by other contracts on the blockchain network. They promote object oriented programming allowing developers to be modular with their design.
There are advantages to using libraries in Solidity smart contracts. The biggest advantage is code reusability across contracts. Since libraries are reusable they help prevent duplication of code. In addition, libraries save on gas since the same code is not deployed multiple times to the blockchain.
Libraries are a special form of contracts that:
- Are singletons
- Not allowed any storage or state variables that change
- Cannot have fallback functions
- Have no event logs
- Do not hold Ether
- Are stateless
- Cannot use destroy
- Cannot inherit or be inherited
Libraries in Solidity allow you to add functionality to types. For example you can use a library to enhance the functionality of a variable of type uint in a contract.
A library is an isolated block of code. A library contracts function uses the storage from the calling contract. During the execution of a library function call code is executed in the context of the calling contract. It can access state variables of a calling contract if they are explicitly supplied.
For example consider a Solidity library that performs the functions of a basic calculator (add, subtract, multiply and divide). The calling contract sends the inputs 5 and 5 to the libraries add function. The library add function executes and returns 10 to the calling contract.
How to create a library contract in Solidity
To create a library define the contract with the library keyword and not the contract keyword.
pragma solidity ^0.8.6;
library libraryName {
Libraries can support several different data types. The types supported are:
- Libraries support variables defined as constants because they are immutable. Library variables are stored in bytecode not in storage on the blockchain.
- User defined Struts and Enums.
The example library below called MathLibrary contains a basic multiplication operation. A calling contract would pass in two unsigned integers into the multiply function. The library would return a result to the calling contract.
pragma solidity ^0.8.6;
library MathLibrary {
function multiply(uint a, uint b) public view returns (uint, address) {
return (a * b, address(this));
}
}
How to deploy a library in Solidity
Libraries in Solidity are deployed as embedded coded or linked contract.
- Embed a library in a contract – If a library has only internal functions then the library is included in the contract that uses it. There is no need to deploy a separate contract for the library. In the diagram below see contract Z which is an example of the calling code and library all in one contract.
- Link a library to a contract – If a library has public or external functions then it can be deployed separately. The calling contract using the library needs to reference the library’s contract address. In the diagram below see contract X and Y link to the library contract. The picture below illustrates contract code reuse and less code deployed which results in a gas savings.
To illustrate these two concepts we will review both methods below using sample contracts.
How to use a Library in a Solidity smart contract
Embed the library in a contract
To begin, below the pragma statement include your library code. You can write your library code directly in the smart contact or you can keep your library code in a separate file and import it.
Option 1 – Using Import
When the “import” key word is used in a contract the compiler will copy the code in the file directly into the smart contract.
pragma solidity ^0.8.6;
//if your library is in another file you can import it into the contract
import LibraryName from “./libraryfile.sol”;
or
//to import all libraries in the file use the pattern below
import "./libraryfile.sol";
Option 2 – Library code directly in the contract
Libraries can be written at the top of the contract to be used in multiple calling functions.
pragma solidity ^0.8.6;
library MathLibrary {
//function that returns a * b and the requesting address
function multiply(uint a, uint b) internal view returns (uint, address) {
return (a * b, address(this));
}
}
To use a library within a smart contract use the following syntax:
using LibraryName for type;
This directive is used to attach functions from the library (LibraryName) to any data type (Type) of the calling contract.
- LibraryName – is the name of the library that you want to use in the contract
- Type – the variable type to use the library for (uint, string, address, etc.). Use the wildcard
*
to attach functions from the library to all types.
Below is a sample contract that uses a library. Take note to how the directive “using MathLibrary for uint;” calls the library. This means attach the function from the MathLibrary for all types of uint.
pragma solidity ^0.8.6;
library MathLibrary {
//function that returns a * b and the requesting address
function multiply(uint a, uint b) internal view returns (uint, address) {
return (a * b, address(this));
}
}
contract exampleContractUsingLibrary {
//use the syntax - using LibraryName for Type
//this can be use to attach library functions to any data type.
using MathLibrary for uint;
address owner = address(this);
//function calls the function multiply in the MathLibrary above
function multiplyExample(uint _a, uint _b) public view returns (uint, address) {
return _a.multiply(_b);
}
}
Try it in Remix
How a function calls a library
To use a library function the syntax is:
variable.libraryFunctionName(argument)
- Determine the variable you want to pass into the library function
- Add a “.” followed by the library function name we want to use
- Solidity implicitly passes in the first parameter into the function
For example:
//variable _a use the multiply function in the library
//_a.multiply(_b) which means multiply a * b
//_a is implicitly passed in as the first parameter
//_b is passed in as the second parameter
function multiplyExample(uint _a, uint _b) public view returns (uint, address) {
return _a.multiply(_b);
Link a deployed library to a smart contract using Remix
Next, lets use Remix to link a new contract to a deployed library. The process is as follows:
- Deploy library contract to a test network
- Configure Remix with deployed library address
- Deploy calling contract
Before we start linking contracts the following pre condition need to occur:
- You deployed and verified a library contract
- You have the library contract’s address
- The calling contract has import “./libraryfile.sol”; at the top and is ready for deployment
Remix configuration to link a library contract
By default Remix does not generate a contracts metadata file. To generate a contracts metadata file go to the settings module and select generate metadata.
Then go to the Solidity Compiler and recompile the calling smart contract to make sure there are no errors and generate the metadata file.
Next go to the artifacts folder in the file explorer of Remix and open the callingcontract.json file.
The default behavior of Remix is to automatically deploy a library and link it to the calling contract (autoDeployLib: true). This default behavior of Remix works well.
Modify the behavior of Remix to link a library to the calling contract. Edit the metadata file of the calling contract.
Using the address of the library replace the <address> tag of the network we are deploying to with the actual address of the library. In our example we are deploying to a test network so in the metadata file edit the appropriate tags.
We also need to update the autoDeployLib setting so that Remix does not automatically deploy the library when it deploys the calling contract. Set autoDeployLib to false.
Deploy the contract in Remix
In Remix select injected Web 3 as the deployment location, select the contract and click deploy. Verify your contract and test the process.
Use the sample files below. Deploy the library then link it to a separately deployed smart contract.
Sample library contract
//name this file MathLibrary.sol
pragma solidity ^0.8.6;
library MathLibrary {
function multiply(uint a, uint b) public view returns (uint, address) {
return (a * b, address(this));
}
}
Try on Remix
Sample calling contract
pragma solidity ^0.8.6;
import './MathLibrary.sol';
contract exampleContractUsingLibrary {
using MathLibrary for uint;
address owner = address(this);
function multiplyExample(uint _a, uint _b) public view returns (uint, address) {
return _a.multiply(_b);
}
}
Try it in Remix
Resources
Blockchain Networks
Below is a list of EVM compatible Mainnet and Testnet blockchain networks. Each link contains network configuration, links to multiple faucets for test ETH and tokens, bridge details, and technical resources for each blockchain. Basically everything you need to test and deploy smart contracts or decentralized applications on each chain. For a list of popular Ethereum forums and chat applications click here.
Ethereum test network configuration and test ETH faucet information | |
Optimistic Ethereum Mainnet and Testnet configuration, bridge details, etc. | |
Polygon network Mainnet and Testnet configuration, faucets for test MATIC tokens, bridge details, etc. | |
Binance Smart Chain Mainnet and Testnet configuration, faucets for test BNB tokens, bridge details, etc. | |
Fanton networt Mainnet and Testnet configuration, faucets for test FTM tokens, bridge details, etc. | |
Kucoin Chain Mainnet and Testnet configuration, faucets for test KCS tokens, bridge details, etc. |
Web3 Software Libraries
You can use the following libraries to interact with an EVM compatible blockchain.
- Python: Web3.py A Python library for interacting with Ethereum. Web3.py examples
- Js: web3.js Ethereum JavaScript API
- Java: web3j Web3 Java Ethereum Ðapp API
- PHP: web3.php A php interface for interacting with the Ethereum blockchain and ecosystem.
Nodes
Learn how to run a Geth node. Read getting started with Geth to run an Ethereum node.
Fix a transaction
How to fix a pending transaction stuck on Ethereum or EVM compatible chain