CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-solc

JavaScript bindings for the Solidity compiler with Standard JSON I/O interface

Pending
Overview
Eval results
Files

linking.mddocs/

Bytecode Linking

Link library addresses into compiled bytecode and analyze library dependencies with support for both legacy and modern placeholder formats.

Capabilities

Link Bytecode

Replace library placeholders in compiled bytecode with actual deployed library addresses.

/**
 * Link library addresses into compiled bytecode
 * @param bytecode - Hex-encoded bytecode string containing library placeholders
 * @param libraries - Mapping of library names to deployed addresses
 * @returns Hex-encoded bytecode string with placeholders replaced by addresses
 */
function linkBytecode(bytecode: string, libraries: LibraryAddresses): string;

interface LibraryAddresses {
  [qualifiedNameOrSourceUnit: string]: string | { [unqualifiedLibraryName: string]: string };
}

Usage Examples:

import linker from "solc/linker";

// Simple library linking
const bytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________73123456789...";
const linkedBytecode = linker.linkBytecode(bytecode, {
  "lib.sol:MyLib": "0x1234567890123456789012345678901234567890"
});

// Multiple libraries with nested format
const libraries = {
  "lib.sol:Math": "0x1111111111111111111111111111111111111111",
  "lib.sol": {
    "Storage": "0x2222222222222222222222222222222222222222"
  }
};
const result = linker.linkBytecode(bytecode, libraries);

Library Address Formats

The LibraryAddresses interface supports multiple formats for maximum compatibility:

interface LibraryAddresses {
  /** Flat format: fully qualified library name to address */
  [qualifiedNameOrSourceUnit: string]: string | {
    /** Nested format: source unit containing unqualified library names */
    [unqualifiedLibraryName: string]: string;
  };
}

Supported Address Formats:

// Flat format (backwards compatible)
const flatFormat = {
  "MyLibrary": "0x1234567890123456789012345678901234567890",
  "lib.sol:MyLibrary": "0x1234567890123456789012345678901234567890"
};

// Nested format (Standard JSON compatible)
const nestedFormat = {
  "lib.sol": {
    "MyLibrary": "0x1234567890123456789012345678901234567890",
    "OtherLib": "0x2234567890123456789012345678901234567890"
  }
};

// Mixed format
const mixedFormat = {
  "utils.sol:Helper": "0x3334567890123456789012345678901234567890",
  "math.sol": {
    "SafeMath": "0x4434567890123456789012345678901234567890"
  }
};

Find Link References

Analyze bytecode to find library placeholder locations for manual linking or debugging.

/**
 * Find all library placeholder locations in hex-encoded bytecode
 * @param bytecode - Hex-encoded bytecode string
 * @returns Mapping of library labels to their placeholder locations
 */
function findLinkReferences(bytecode: string): LinkReferences;

interface LinkReferences {
  [libraryLabel: string]: Array<{
    /** Byte offset in binary (not hex) bytecode */
    start: number;
    /** Length in bytes (always 20 for addresses) */
    length: number;
  }>;
}

Usage Examples:

import linker from "solc/linker";

const bytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________73123456789...";
const references = linker.findLinkReferences(bytecode);

console.log(references);
/* Output:
{
  "lib.sol:MyLib": [
    { start: 26, length: 20 }
  ]
}
*/

// Use with Standard JSON output
const output = JSON.parse(solc.compile(input));
const contractBytecode = output.contracts['Contract.sol']['MyContract'].evm.bytecode.object;
const linkRefs = linker.findLinkReferences(contractBytecode);

// Compare with compiler-provided link references
const compilerRefs = output.contracts['Contract.sol']['MyContract'].evm.bytecode.linkReferences;

Placeholder Formats

Solc supports two placeholder formats in bytecode:

Legacy Placeholders:

  • Format: __<library_name>____________________ (40 characters total)
  • Example: __lib.sol:MyLib________________
  • Truncated to 36 characters, padded with underscores

Modern Placeholders:

  • Format: __$<hash>$__ (40 characters total)
  • Example: __$cb901161e812ceb78cfe30ca65050c4337$__
  • Uses keccak256 hash of fully qualified library name
// Both formats are automatically handled
const legacyBytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________";
const modernBytecode = "608060405234801561001057600080fd5b50__$cb901161e812ceb78cfe30ca65050c4337$__";

const libraries = { "lib.sol:MyLib": "0x1234567890123456789012345678901234567890" };

// Both will be linked correctly
const linkedLegacy = linker.linkBytecode(legacyBytecode, libraries);
const linkedModern = linker.linkBytecode(modernBytecode, libraries);

Address Validation

Library addresses are automatically validated and formatted:

// Addresses are validated
try {
  linker.linkBytecode(bytecode, {
    "MyLib": "invalid_address" // Error: Invalid address
  });
} catch (error) {
  console.error(error.message); // "Invalid address specified for MyLib"
}

// Addresses are automatically padded
linker.linkBytecode(bytecode, {
  "MyLib": "0x123" // Automatically padded to "0x0000000000000000000000000000000000000123"
});

// 0x prefix is required
linker.linkBytecode(bytecode, {
  "MyLib": "1234567890123456789012345678901234567890" // Error: Invalid address
});

Integration with Compilation

Linking is typically done after compilation when deploying contracts with library dependencies:

import solc from "solc";
import linker from "solc/linker";

// Compile contract with library dependency
const input = {
  language: 'Solidity',
  sources: {
    'Contract.sol': {
      content: `
        import "./MyLib.sol";
        contract MyContract {
          function test() public returns (uint) {
            return MyLib.calculate(42);
          }
        }
      `
    },
    'MyLib.sol': {
      content: `
        library MyLib {
          function calculate(uint x) public pure returns (uint) {
            return x * 2;
          }
        }
      `
    }
  },
  settings: {
    outputSelection: { '*': { '*': ['evm.bytecode', 'evm.deployedBytecode'] } }
  }
};

const output = JSON.parse(solc.compile(JSON.stringify(input)));

// First deploy the library
const libraryBytecode = output.contracts['MyLib.sol']['MyLib'].evm.bytecode.object;
// ... deploy library and get address ...
const libraryAddress = "0x1234567890123456789012345678901234567890";

// Then link the main contract
const contractBytecode = output.contracts['Contract.sol']['MyContract'].evm.bytecode.object;
const linkedBytecode = linker.linkBytecode(contractBytecode, {
  "MyLib.sol:MyLib": libraryAddress
});

// Now linkedBytecode can be deployed

Install with Tessl CLI

npx tessl i tessl/npm-solc

docs

abi-utilities.md

cli.md

compilation.md

index.md

linking.md

smt-integration.md

utilities.md

version-management.md

tile.json