Skip to content

Commit f7c22b3

Browse files
committed
Implement findLinkReferences in linker.js
1 parent 067aa6f commit f7c22b3

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

linker.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,40 @@ var linkBytecode = function (bytecode, libraries) {
3131
return bytecode;
3232
};
3333

34+
var findLinkReferences = function (bytecode) {
35+
// find 40 bytes in the pattern of __...<36 digits>...__
36+
// e.g. __Lib.sol:L_____________________________
37+
var linkReferences = {};
38+
var offset = 0;
39+
while (true) {
40+
var found = bytecode.match(/__(.{36})__/);
41+
if (!found) {
42+
break;
43+
}
44+
45+
var start = found.index;
46+
// trim trailing underscores
47+
// NOTE: this has no way of knowing if the trailing underscore was part of the name
48+
var libraryName = found[1].replace(/_+$/gm, '');
49+
50+
if (!linkReferences[libraryName]) {
51+
linkReferences[libraryName] = [];
52+
}
53+
54+
linkReferences[libraryName].push({
55+
// offsets are in bytes in binary representation (and not hex)
56+
start: (offset + start) / 2,
57+
length: 20
58+
});
59+
60+
offset += start + 20;
61+
62+
bytecode = bytecode.slice(start + 20);
63+
}
64+
return linkReferences;
65+
};
66+
3467
module.exports = {
35-
linkBytecode: linkBytecode
68+
linkBytecode: linkBytecode,
69+
findLinkReferences: findLinkReferences
3670
};

test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require('./linker.js');
12
require('./translate.js');
23
require('./package.js');
34
require('./abi.js');

test/linker.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
const tape = require('tape');
2+
const linker = require('../linker.js');
3+
4+
tape('Link references', function (t) {
5+
t.test('Empty bytecode', function (st) {
6+
st.deepEqual(linker.findLinkReferences(''), {});
7+
st.end();
8+
});
9+
10+
t.test('No references', function (st) {
11+
st.deepEqual(linker.findLinkReferences('6060604052341561000f57600080fd'), {});
12+
st.end();
13+
});
14+
15+
t.test('One reference', function (st) {
16+
var bytecode = '6060604052341561000f57600080fd5b60f48061001d6000396000f300606060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326121ff081146043575b600080fd5b3415604d57600080fd5b60536055565b005b73__lib2.sol:L____________________________6326121ff06040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b151560b357600080fd5b6102c65a03f4151560c357600080fd5b5050505600a165627a7a723058207979b30bd4a07c77b02774a511f2a1dd04d7e5d65b5c2735b5fc96ad61d43ae40029';
17+
st.deepEqual(linker.findLinkReferences(bytecode), { 'lib2.sol:L': [ { start: 116, length: 20 } ] });
18+
st.end();
19+
});
20+
21+
t.test('Two references', function (st) {
22+
var bytecode = '6060604052341561000f57600080fd5b61011a8061001e6000396000f30060606040526004361060255763ffffffff60e060020a60003504166326121ff08114602a575b600080fd5b3415603457600080fd5b603a603c565b005b73__lib2.sol:L____________________________6326121ff06040518163ffffffff1660e060020a02815260040160006040518083038186803b1515608157600080fd5b6102c65a03f41515609157600080fd5b50505073__linkref.sol:Lx________________________6326121ff06040518163ffffffff1660e060020a02815260040160006040518083038186803b151560d957600080fd5b6102c65a03f4151560e957600080fd5b5050505600a165627a7a72305820fdfb8eab411d7bc86d7dfbb0c985c30bebf1cc105dc5b807291551b3d5aa29d90029';
23+
st.deepEqual(
24+
linker.findLinkReferences(bytecode),
25+
{ 'lib2.sol:L': [ { start: 92, length: 20 } ], 'linkref.sol:Lx': [ { start: 180, length: 20 } ] }
26+
);
27+
st.end();
28+
});
29+
30+
t.test('Library name with leading underscore', function (st) {
31+
var bytecode = '6060604052341561000f57600080fd5b60f48061001d6000396000f300606060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326121ff081146043575b600080fd5b3415604d57600080fd5b60536055565b005b73__lib2.sol:_L___________________________6326121ff06040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b151560b357600080fd5b6102c65a03f4151560c357600080fd5b5050505600a165627a7a7230582089689827bbf0b7dc385ffcb4b1deb9f9e61741f61f89b4af65f806ff2b0d73470029';
32+
st.deepEqual(
33+
linker.findLinkReferences(bytecode),
34+
{ 'lib2.sol:_L': [ { start: 116, length: 20 } ] }
35+
);
36+
st.end();
37+
});
38+
39+
t.test('Library name with leading underscore (without fqdn)', function (st) {
40+
var bytecode = '6060604052341561000f57600080fd5b60f48061001d6000396000f300606060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326121ff081146043575b600080fd5b3415604d57600080fd5b60536055565b005b73___L____________________________________6326121ff06040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b151560b357600080fd5b6102c65a03f4151560c357600080fd5b5050505600a165627a7a7230582089689827bbf0b7dc385ffcb4b1deb9f9e61741f61f89b4af65f806ff2b0d73470029';
41+
st.deepEqual(
42+
linker.findLinkReferences(bytecode),
43+
{ '_L': [ { start: 116, length: 20 } ] }
44+
);
45+
st.end();
46+
});
47+
48+
t.test('Library name with underscore in the name', function (st) {
49+
var bytecode = '6060604052341561000f57600080fd5b60f48061001d6000396000f300606060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326121ff081146043575b600080fd5b3415604d57600080fd5b60536055565b005b73__lib2.sol:L_L__________________________6326121ff06040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b151560b357600080fd5b6102c65a03f4151560c357600080fd5b5050505600a165627a7a723058205cb324a27452cc7f8894a57cb0e3ddce2dce0c423e4fc993a3dd51287abd49110029';
50+
st.deepEqual(
51+
linker.findLinkReferences(bytecode),
52+
{ 'lib2.sol:L_L': [ { start: 116, length: 20 } ] }
53+
);
54+
st.end();
55+
});
56+
57+
// Note: this is a case the reference finder cannot properly handle as there's no way to tell
58+
t.test('Library name with trailing underscore', function (st) {
59+
var bytecode = '6060604052341561000f57600080fd5b60f48061001d6000396000f300606060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326121ff081146043575b600080fd5b3415604d57600080fd5b60536055565b005b73__lib2.sol:L____________________________6326121ff06040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b151560b357600080fd5b6102c65a03f4151560c357600080fd5b5050505600a165627a7a7230582058e61511a603707222cfa83fd3ae4269f94eb86513cb9042cf0b44877403d85c0029';
60+
st.deepEqual(
61+
linker.findLinkReferences(bytecode),
62+
{ 'lib2.sol:L': [ { start: 116, length: 20 } ] }
63+
);
64+
st.end();
65+
});
66+
67+
t.test('Invalid input (too short)', function (st) {
68+
var bytecode = '6060604052341561000____66606060606060';
69+
st.deepEqual(
70+
linker.findLinkReferences(bytecode),
71+
{}
72+
);
73+
st.end();
74+
});
75+
76+
t.test('Invalid input (1 byte short)', function (st) {
77+
var bytecode = '6060604052341561000__lib2.sol:L___________________________66606060606060';
78+
st.deepEqual(
79+
linker.findLinkReferences(bytecode),
80+
{}
81+
);
82+
st.end();
83+
});
84+
});

0 commit comments

Comments
 (0)