How to link libraries into Solidity contracts generated by sol-compiler
Tags: ethereum, solidity, solcompiler, typescript
Published: 2019-04-18 11:43:17

---
title: How to link libraries into Solidity contracts generated by sol-compiler
description: The sol-compiler doesn't link for you like Truffle does. Here I explain with code, how the Solidity linker works and how to get it working with sol-compiler, all in JS.
tags: ethereum,solidity,sol-compiler,typescript
published: true
---

Solidity smart contracts are generated from source into bytecode. However, much like the days of yore in C, **linking** in other libraries that may already be deployed is sometimes a necessity. 

When a Solidity artifact is generated using Truffle or sol-compiler, there is a field called `bytecode` or `deployedBytecode`. If you have unlinked libraries and try to deploy this code, you will get an error along the lines of **invalid contract bytecode**:

```
{ Error: invalid contract bytecode (arg="bytecode", value="0x608060405260016004554360075543600__$e66798aa9224cd2742272d2e7f8089dbe6$__ffffffffffffffffffffffffffffffffffffffff1660601b81526014018281526020019350505050604051602081830303815290604052805190602001209050939250505056fea165627a7a72305820fdb2e9c02d3de9057e4d439bc377d8c8ae842b83649e495e3303688bfe6f7e930029", version=4.0.26)
```

If you examine deeper, you can see there is a very non-hexadecimal looking character `$` which is the beginning of a link reference. The link reference itself is a string `__$e66798aa9224cd2742272d2e7f8089dbe6$__`. This used to have a more human-readable name, such as `____________________$Library$_`, but it was changed to a more arcane algorithm. The [libraryHashPlaceholder](https://sourcegraph.com/github.com/ethereum/solc-js@40b8fc3e0b5f80b6629d6f9c4d7d19c190e6c388/-/blob/linker.js#L7) method creates this format, but what is the input we are giving it? It is of the form, `libraryName:lib`.

For example, my `MerkleTreeVerifier` library would have the name:

```js
libraryHashPlaceholder('/Users/liamz/Documents/open-source/0dex/packages/contracts/contracts/MerkleTreeVerifier.sol:MerkleTreeVerifier')
// '$1eb98b648b444978ea3820de6fcdeb48d6$'
```

## Integrating with sol-compiler
Now for the 0x compiler, you will need to do two things. Note that I'm also using [abi-gen](https://www.npmjs.com/package/@0xproject/abi-gen) to generate TypeScript wrappers of our contracts.

1) Enable the `metadata` option in `compiler.json`. For example, here is mine:

```json
{
    "contractsDir": "contracts",
    "artifactsDir": "build/artifacts",
    "contracts": "*",
    "compilerSettings": {
        "optimizer": { "enabled": false },
        "outputSelection": {
            "*": {
                "*": [
                    "metadata",
                    "abi",
                    "evm.bytecode.object",
                    "evm.bytecode.sourceMap",
                    "evm.deployedBytecode.object",
                    "evm.deployedBytecode.sourceMap"
                ]
            }
        }
    }
}
```

2\) Add your libraries and link them. 

```ts
export function addLibrary(name: string, address: string) {
    let artifact = require(`@ohdex/contracts/lib/build/artifacts/${name}.json`);
    let metadata = JSON.parse(artifact.compilerOutput.metadata)
    
    let [k,v] = Object.entries(metadata.settings.compilationTarget)[0];
    let key = `${k}:${v}`;
    
    console.log(`Registered library ${name} to ${key}`)

    libraries[key] = address;
}

// Deployment of libraries
// Note that if the library already exists, we just add the address instead
// ....

// Your sol-compiler generated wrapper
import { MerkleTreeVerifierContract } from '@ohdex/contracts/lib/build/wrappers/merkle_tree_verifier';


let merkleTreeVerifier = await MerkleTreeVerifierContract.deployAsync(
    ...getDeployArgs('MerkleTreeVerifier', pe, account)
)
addLibrary('MerkleTreeVerifier', merkleTreeVerifier.address)


// Linking libraries to your own contracts
let json = require(`@ohdex/contracts/lib/build/artifacts/${name}.json`);
let bytecode = json.compilerOutput.evm.bytecode.object;
bytecode = linker.linkBytecode(bytecode, libraries)
```

And tada! You've linked your libraries and deployed your contract!