DEV Community

Liam Zebedee
Liam Zebedee

Posted on

3

How to link libraries into Solidity contracts generated by sol-compiler

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 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:

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 to generate TypeScript wrappers of our contracts.

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

{
    "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.

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!

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (1)

Collapse
 
leckylao profile image
Lecky Lao

Is it the same as what Hardhat doing it here?
hardhat.org/plugins/nomiclabs-hard...

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay