or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

abi-utilities.mdcli.mdcompilation.mdindex.mdlinking.mdsmt-integration.mdutilities.mdversion-management.md

linking.mddocs/

0

# Bytecode Linking

1

2

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

3

4

## Capabilities

5

6

### Link Bytecode

7

8

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

9

10

```typescript { .api }

11

/**

12

* Link library addresses into compiled bytecode

13

* @param bytecode - Hex-encoded bytecode string containing library placeholders

14

* @param libraries - Mapping of library names to deployed addresses

15

* @returns Hex-encoded bytecode string with placeholders replaced by addresses

16

*/

17

function linkBytecode(bytecode: string, libraries: LibraryAddresses): string;

18

19

interface LibraryAddresses {

20

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

21

}

22

```

23

24

**Usage Examples:**

25

26

```typescript

27

import linker from "solc/linker";

28

29

// Simple library linking

30

const bytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________73123456789...";

31

const linkedBytecode = linker.linkBytecode(bytecode, {

32

"lib.sol:MyLib": "0x1234567890123456789012345678901234567890"

33

});

34

35

// Multiple libraries with nested format

36

const libraries = {

37

"lib.sol:Math": "0x1111111111111111111111111111111111111111",

38

"lib.sol": {

39

"Storage": "0x2222222222222222222222222222222222222222"

40

}

41

};

42

const result = linker.linkBytecode(bytecode, libraries);

43

```

44

45

### Library Address Formats

46

47

The `LibraryAddresses` interface supports multiple formats for maximum compatibility:

48

49

```typescript { .api }

50

interface LibraryAddresses {

51

/** Flat format: fully qualified library name to address */

52

[qualifiedNameOrSourceUnit: string]: string | {

53

/** Nested format: source unit containing unqualified library names */

54

[unqualifiedLibraryName: string]: string;

55

};

56

}

57

```

58

59

**Supported Address Formats:**

60

61

```typescript

62

// Flat format (backwards compatible)

63

const flatFormat = {

64

"MyLibrary": "0x1234567890123456789012345678901234567890",

65

"lib.sol:MyLibrary": "0x1234567890123456789012345678901234567890"

66

};

67

68

// Nested format (Standard JSON compatible)

69

const nestedFormat = {

70

"lib.sol": {

71

"MyLibrary": "0x1234567890123456789012345678901234567890",

72

"OtherLib": "0x2234567890123456789012345678901234567890"

73

}

74

};

75

76

// Mixed format

77

const mixedFormat = {

78

"utils.sol:Helper": "0x3334567890123456789012345678901234567890",

79

"math.sol": {

80

"SafeMath": "0x4434567890123456789012345678901234567890"

81

}

82

};

83

```

84

85

### Find Link References

86

87

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

88

89

```typescript { .api }

90

/**

91

* Find all library placeholder locations in hex-encoded bytecode

92

* @param bytecode - Hex-encoded bytecode string

93

* @returns Mapping of library labels to their placeholder locations

94

*/

95

function findLinkReferences(bytecode: string): LinkReferences;

96

97

interface LinkReferences {

98

[libraryLabel: string]: Array<{

99

/** Byte offset in binary (not hex) bytecode */

100

start: number;

101

/** Length in bytes (always 20 for addresses) */

102

length: number;

103

}>;

104

}

105

```

106

107

**Usage Examples:**

108

109

```typescript

110

import linker from "solc/linker";

111

112

const bytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________73123456789...";

113

const references = linker.findLinkReferences(bytecode);

114

115

console.log(references);

116

/* Output:

117

{

118

"lib.sol:MyLib": [

119

{ start: 26, length: 20 }

120

]

121

}

122

*/

123

124

// Use with Standard JSON output

125

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

126

const contractBytecode = output.contracts['Contract.sol']['MyContract'].evm.bytecode.object;

127

const linkRefs = linker.findLinkReferences(contractBytecode);

128

129

// Compare with compiler-provided link references

130

const compilerRefs = output.contracts['Contract.sol']['MyContract'].evm.bytecode.linkReferences;

131

```

132

133

### Placeholder Formats

134

135

Solc supports two placeholder formats in bytecode:

136

137

**Legacy Placeholders:**

138

- Format: `__<library_name>____________________` (40 characters total)

139

- Example: `__lib.sol:MyLib________________`

140

- Truncated to 36 characters, padded with underscores

141

142

**Modern Placeholders:**

143

- Format: `__$<hash>$__` (40 characters total)

144

- Example: `__$cb901161e812ceb78cfe30ca65050c4337$__`

145

- Uses keccak256 hash of fully qualified library name

146

147

```typescript

148

// Both formats are automatically handled

149

const legacyBytecode = "608060405234801561001057600080fd5b50__lib.sol:MyLib________________";

150

const modernBytecode = "608060405234801561001057600080fd5b50__$cb901161e812ceb78cfe30ca65050c4337$__";

151

152

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

153

154

// Both will be linked correctly

155

const linkedLegacy = linker.linkBytecode(legacyBytecode, libraries);

156

const linkedModern = linker.linkBytecode(modernBytecode, libraries);

157

```

158

159

### Address Validation

160

161

Library addresses are automatically validated and formatted:

162

163

```typescript

164

// Addresses are validated

165

try {

166

linker.linkBytecode(bytecode, {

167

"MyLib": "invalid_address" // Error: Invalid address

168

});

169

} catch (error) {

170

console.error(error.message); // "Invalid address specified for MyLib"

171

}

172

173

// Addresses are automatically padded

174

linker.linkBytecode(bytecode, {

175

"MyLib": "0x123" // Automatically padded to "0x0000000000000000000000000000000000000123"

176

});

177

178

// 0x prefix is required

179

linker.linkBytecode(bytecode, {

180

"MyLib": "1234567890123456789012345678901234567890" // Error: Invalid address

181

});

182

```

183

184

### Integration with Compilation

185

186

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

187

188

```typescript

189

import solc from "solc";

190

import linker from "solc/linker";

191

192

// Compile contract with library dependency

193

const input = {

194

language: 'Solidity',

195

sources: {

196

'Contract.sol': {

197

content: `

198

import "./MyLib.sol";

199

contract MyContract {

200

function test() public returns (uint) {

201

return MyLib.calculate(42);

202

}

203

}

204

`

205

},

206

'MyLib.sol': {

207

content: `

208

library MyLib {

209

function calculate(uint x) public pure returns (uint) {

210

return x * 2;

211

}

212

}

213

`

214

}

215

},

216

settings: {

217

outputSelection: { '*': { '*': ['evm.bytecode', 'evm.deployedBytecode'] } }

218

}

219

};

220

221

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

222

223

// First deploy the library

224

const libraryBytecode = output.contracts['MyLib.sol']['MyLib'].evm.bytecode.object;

225

// ... deploy library and get address ...

226

const libraryAddress = "0x1234567890123456789012345678901234567890";

227

228

// Then link the main contract

229

const contractBytecode = output.contracts['Contract.sol']['MyContract'].evm.bytecode.object;

230

const linkedBytecode = linker.linkBytecode(contractBytecode, {

231

"MyLib.sol:MyLib": libraryAddress

232

});

233

234

// Now linkedBytecode can be deployed

235

```