# Compiling non-inlinable libraries

Solidity libraries can be divided into two categories:

  • Inlinable. The ones that contain only private or internal methods. Since they can never be called from outside, the Solidity compiler inlines them, i.e. does not use external calls to access the library methods and uses the code of these libraries as part of the code that uses them.
  • Non-inlinable. The ones that have at least one public or external method. While they may be inlined by the Solidity compiler, they are not inlined when compiled to Yul representation. Since Yul is an intermediate step when compiling to zkEVM bytecode, this means that these libraries can not be inlined by the zkSync compiler.

Practically this means that libraries with public methods need to be deployed separately and their addresses passed as an argument when compiling the main contract. Usage of the methods of this library will be replaced with calls to the address of it.

# OpenZeppelin utility libraries

Please note, that the total majority of the OpenZeppelin utility libraries are inlinable. That means that there is no need to do any further actions to make them compile.

This section describes the compilation of non-inlinable libraries only.

# Example

Let's say that we have a small library that calculates the square of a number:

pragma solidity ^0.8.0;

library MiniMath {
    function square(uint256 x) public pure returns (uint256) {
         return x*x;
    }
}

And there is a smart contract that uses this library

pragma solidity ^0.8.0;

import "./MiniMath.sol";

contract Main {
    uint256 public lastNumber;

    function storeSquare(uint256 x) public {
        uint256 square = MiniMath.square(x);
        lastNumber = square;
    }
}

If you try to create a project with these two files following the guidelines from the getting started guide, the yarn hardhat compile command will fail with the following error:

Error in plugin @matterlabs/hardhat-zksync-solc: LLVM("Library `contracts/MiniMath.sol:MiniMath` not found")

That error tells us that the address of the MiniMath library should be provided.

To resolve the issue, you need to create a separate project, where only the library file will be located. After deploying only the library to zkSync, you should get the address of the deployed library and pass it to the compiler settings. The process of deploying the library is exactly the same as deploying smart contracts. You can learn how to deploy smart contracts on zkSync with the getting started guide.

Let's say that the address of the deployed library is 0xF9702469Dfb84A9aC171E284F71615bd3D3f1EdC. To pass this address to the compiler parameters, open the harhdat.config.ts file of the project where the Main contract is located and change its content to the following one:

require("@matterlabs/hardhat-zksync-deploy");
require("@matterlabs/hardhat-zksync-solc");

module.exports = {
  zksolc: {
    version: "1.1.5",
    compilerSource: "docker",
    settings: {
      optimizer: {
        enabled: true,
      },
      experimental: {
        dockerImage: "matterlabs/zksolc",
        tag: "v1.1.5"
      },
      libraries: {
        "contracts/MiniMath.sol": {
          MiniMath: "0xF9702469Dfb84A9aC171E284F71615bd3D3f1EdC",
        },
      },
    },
  },
  zkSyncDeploy: {
    zkSyncNetwork: "https://zksync2-testnet.zksync.dev",
    ethNetwork: "goerli", // Can also be the RPC URL of the network (e.g. `https://goerli.infura.io/v3/<API_KEY>`)
  },
  networks: {
    hardhat: {
      zksync: true,
    },
  },
  solidity: {
    version: "0.8.16",
  },
};

The address of the library is passed in the following lines:

libraries: {
  'contracts/MiniMath.sol': {
    'MiniMath': '0xF9702469Dfb84A9aC171E284F71615bd3D3f1EdC'
  }
},

where 'contracts/MiniMath.sol' is the location of the library's Solidity file and MiniMath is the name of the library.

Now, running yarn hardhat compile should successfully compile the Main contract.

Last Updated: 8/30/2022, 2:33:15 PM