Skip to content

Commit 838a275

Browse files
committed
Add tests for pre-0.4.11 solc cborAuxdata handling
1 parent 6e94dba commit 838a275

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

packages/lib-sourcify/test/Compilation/SolidityCompilation.spec.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,4 +325,119 @@ describe('SolidityCompilation', () => {
325325
const immutableRefs = compilation.immutableReferences;
326326
expect(immutableRefs).to.deep.equal({ '3': [{ length: 32, start: 608 }] });
327327
});
328+
329+
// Contracts before 0.4.12 don't have `auxdata` in `legacyAssembly`
330+
// https://github.com/ethereum/sourcify/issues/2217
331+
it('should handle legacy Solidity 0.4.11 contracts with auxdata correctly', async () => {
332+
const contractPath = path.join(__dirname, '..', 'sources', 'pre-0.4.11');
333+
const sources = {
334+
'Multidrop.sol': {
335+
content: fs.readFileSync(
336+
path.join(contractPath, 'Multidrop.sol'),
337+
'utf8',
338+
),
339+
},
340+
};
341+
342+
const solcJsonInput: SolidityJsonInput = {
343+
language: 'Solidity',
344+
sources,
345+
settings: {
346+
optimizer: {
347+
enabled: false,
348+
runs: 200,
349+
},
350+
outputSelection: {
351+
'*': {
352+
'*': ['*'],
353+
},
354+
},
355+
},
356+
};
357+
358+
const compilation = new SolidityCompilation(
359+
solc,
360+
'0.4.11+commit.68ef5810', // Solidity 0.4.11
361+
solcJsonInput,
362+
{
363+
name: 'Multidrop',
364+
path: 'Multidrop.sol',
365+
},
366+
);
367+
368+
await compilation.compile();
369+
await compilation.generateCborAuxdataPositions();
370+
371+
// For Solidity 0.4.11, auxdata should be extracted from bytecode directly
372+
// The auxdata positions should be calculated correctly even though legacyAssembly doesn't have .auxdata field
373+
expect(compilation.runtimeBytecodeCborAuxdata).to.not.deep.equal({});
374+
expect(compilation.creationBytecodeCborAuxdata).to.not.deep.equal({});
375+
376+
// Verify that auxdata positions are properly structured
377+
if (Object.keys(compilation.runtimeBytecodeCborAuxdata).length > 0) {
378+
expect(compilation.runtimeBytecodeCborAuxdata['1']).to.have.property(
379+
'offset',
380+
);
381+
expect(compilation.runtimeBytecodeCborAuxdata['1']).to.have.property(
382+
'value',
383+
);
384+
expect(compilation.runtimeBytecodeCborAuxdata['1'].value).to.match(
385+
/^0x[a-fA-F0-9]+$/,
386+
);
387+
}
388+
389+
if (Object.keys(compilation.creationBytecodeCborAuxdata).length > 0) {
390+
expect(compilation.creationBytecodeCborAuxdata['1']).to.have.property(
391+
'offset',
392+
);
393+
expect(compilation.creationBytecodeCborAuxdata['1']).to.have.property(
394+
'value',
395+
);
396+
expect(compilation.creationBytecodeCborAuxdata['1'].value).to.match(
397+
/^0x[a-fA-F0-9]+$/,
398+
);
399+
}
400+
});
401+
402+
it('should handle very old Solidity versions (< 0.4.7) with no auxdata', async () => {
403+
const contractPath = path.join(__dirname, '..', 'sources', 'pre-0.4.11');
404+
const sources = {
405+
'Simple.sol': {
406+
content: fs.readFileSync(path.join(contractPath, 'Simple.sol'), 'utf8'),
407+
},
408+
};
409+
410+
const solcJsonInput: SolidityJsonInput = {
411+
language: 'Solidity',
412+
sources,
413+
settings: {
414+
optimizer: {
415+
enabled: false,
416+
runs: 200,
417+
},
418+
outputSelection: {
419+
'*': {
420+
'*': ['*'],
421+
},
422+
},
423+
},
424+
};
425+
426+
const compilation = new SolidityCompilation(
427+
solc,
428+
'0.4.0+commit.acd334c9',
429+
solcJsonInput,
430+
{
431+
name: 'Simple',
432+
path: 'Simple.sol',
433+
},
434+
);
435+
436+
await compilation.compile();
437+
await compilation.generateCborAuxdataPositions();
438+
439+
// For versions < 0.4.7, no auxdata should exist
440+
expect(compilation.runtimeBytecodeCborAuxdata).to.deep.equal({});
441+
expect(compilation.creationBytecodeCborAuxdata).to.deep.equal({});
442+
});
328443
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
pragma solidity ^0.4.0;
2+
3+
contract ERC20Basic {
4+
uint public totalSupply;
5+
6+
function balanceOf(address who) constant returns (uint);
7+
8+
function transfer(address to, uint value);
9+
10+
event Transfer(address indexed from, address indexed to, uint value);
11+
}
12+
13+
contract ERC20 is ERC20Basic {
14+
function allowance(address owner, address spender) constant returns (uint);
15+
16+
function transferFrom(address from, address to, uint value);
17+
18+
function approve(address spender, uint value);
19+
20+
event Approval(address indexed owner, address indexed spender, uint value);
21+
}
22+
23+
contract Ownable {
24+
address public owner;
25+
26+
function Ownable() {
27+
owner = msg.sender;
28+
}
29+
30+
modifier onlyOwner() {
31+
if (msg.sender != owner) {
32+
throw;
33+
}
34+
_;
35+
}
36+
37+
function transferOwnership(address newOwner) onlyOwner {
38+
if (newOwner != address(0)) {
39+
owner = newOwner;
40+
}
41+
}
42+
}
43+
44+
contract Multidrop is Ownable {
45+
function multisend(
46+
address _tokenAddr,
47+
address[] dests,
48+
uint256[] values
49+
) onlyOwner returns (uint256) {
50+
uint256 i = 0;
51+
while (i < dests.length) {
52+
ERC20(_tokenAddr).transfer(dests[i], values[i]);
53+
i += 1;
54+
}
55+
return (i);
56+
}
57+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pragma solidity ^0.4.0;
2+
3+
contract Simple {
4+
uint public value;
5+
6+
function Simple() {
7+
value = 42;
8+
}
9+
10+
function setValue(uint _value) {
11+
value = _value;
12+
}
13+
}

0 commit comments

Comments
 (0)