aboutsummaryrefslogtreecommitdiff
path: root/lib/compilers/solidity.js
diff options
context:
space:
mode:
authorAnders-T | 0x80.eth <95024805+anders-torbjornsen@users.noreply.github.com>2022-04-26 03:20:13 +0100
committerGitHub <noreply@github.com>2022-04-26 04:20:13 +0200
commitfb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c (patch)
tree24abc9ecca97d68b958ba9d698b2841e0166a0df /lib/compilers/solidity.js
parent21b764f392e4b1062e61ec910c590f3dfba4d544 (diff)
downloadcompiler-explorer-fb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c.tar.gz
compiler-explorer-fb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c.zip
Fix Solidity compilers and line numbers in versions 0.4.x - 0.8.x (#3561)gh-2523
* fixing compilers 0.4.x - 0.8.x * update contributors file
Diffstat (limited to 'lib/compilers/solidity.js')
-rw-r--r--lib/compilers/solidity.js119
1 files changed, 84 insertions, 35 deletions
diff --git a/lib/compilers/solidity.js b/lib/compilers/solidity.js
index 383177ff0..fd926742d 100644
--- a/lib/compilers/solidity.js
+++ b/lib/compilers/solidity.js
@@ -46,7 +46,7 @@ export class SolidityCompiler extends BaseCompiler {
return [
// We use --combined-json instead of `--asm-json` to have compacted json
'--combined-json',
- 'asm,ast,generated-sources,generated-sources-runtime',
+ this.compiler.semver.split('.')[1] < 8 ? 'asm,ast' : 'asm,ast,generated-sources,generated-sources-runtime',
'-o',
'contracts',
];
@@ -79,6 +79,9 @@ export class SolidityCompiler extends BaseCompiler {
return line;
});
+ let compilerVersion = {};
+ [compilerVersion.major, compilerVersion.minor, compilerVersion.patch] = this.compiler.semver.split('.');
+
const asm = JSON.parse(result.asm);
return {
asm: Object.entries(asm.contracts)
@@ -92,37 +95,73 @@ export class SolidityCompiler extends BaseCompiler {
// tags (jumpdests) to show what function they're
// part of. here we parse the AST so we know what
// range of characters belongs to each function.
- const contractFunctions = asm.sources[sourceName].AST.nodes
- .find(node => {
- return node.nodeType === 'ContractDefinition' && node.name === contractName;
- })
- .nodes.filter(node => {
- return node.nodeType === 'FunctionDefinition';
- })
- .map(node => {
- const [begin, length] = node.src.split(':').map(x => parseInt(x));
-
- let name = node.kind === 'constructor' ? 'constructor' : node.name;
-
- // encode the args into the name so we can
- // differentiate between overloads
- if (node.parameters.parameters.length > 0) {
- name +=
- '_' +
- node.parameters.parameters
- .map(paramNode => {
- return paramNode.typeName.name;
- })
- .join('_');
- }
+ let contractFunctions;
+ // the layout of this JSON has changed between versions...
+ if (compilerVersion.major === 0 && compilerVersion.minor < 8) {
+ contractFunctions = asm.sources[sourceName].AST.children
+ .find(node => {
+ return node.name === 'ContractDefinition' && node.attributes.name === contractName;
+ })
+ .children.filter(node => {
+ return node.name === 'FunctionDefinition';
+ })
+ .map(node => {
+ const [begin, length] = node.src.split(':').map(x => parseInt(x));
- return {
- name: name,
- begin: begin,
- end: begin + length,
- tagCount: 0,
- };
- });
+ let name = node.attributes.isConstructor ? 'constructor' : node.attributes.name;
+
+ // encode the args into the name so we can
+ // differentiate between overloads
+ if (node.children[0].children.length > 0) {
+ name +=
+ '_' +
+ node.children[0].children
+ .map(paramNode => {
+ return paramNode.attributes.type;
+ })
+ .join('_');
+ }
+
+ return {
+ name: name,
+ begin: begin,
+ end: begin + length,
+ tagCount: 0,
+ };
+ });
+ } else {
+ contractFunctions = asm.sources[sourceName].AST.nodes
+ .find(node => {
+ return node.nodeType === 'ContractDefinition' && node.name === contractName;
+ })
+ .nodes.filter(node => {
+ return node.nodeType === 'FunctionDefinition';
+ })
+ .map(node => {
+ const [begin, length] = node.src.split(':').map(x => parseInt(x));
+
+ let name = node.kind === 'constructor' ? 'constructor' : node.name;
+
+ // encode the args into the name so we can
+ // differentiate between overloads
+ if (node.parameters.parameters.length > 0) {
+ name +=
+ '_' +
+ node.parameters.parameters
+ .map(paramNode => {
+ return paramNode.typeName.name;
+ })
+ .join('_');
+ }
+
+ return {
+ name: name,
+ begin: begin,
+ end: begin + length,
+ tagCount: 0,
+ };
+ });
+ }
// solc generates some code, for things like detecting
// and reverting if a multiplication results in
@@ -143,11 +182,17 @@ export class SolidityCompiler extends BaseCompiler {
return generatedSources;
};
+ // (0.8.x onwards only!)
// there are two sets of generated sources, one for the code which deploys
// the contract (i.e. the constructor) 'generated-sources', and the code
// which is deployed and stored on-chain 'generated-sources-runtime'
- const generatedSources = processGeneratedSources(data['generated-sources']);
- const generatedSourcesRuntime = processGeneratedSources(data['generated-sources-runtime']);
+ const hasGeneratedSources = compilerVersion.major > 0 || compilerVersion.minor > 7;
+ const generatedSources = hasGeneratedSources
+ ? processGeneratedSources(data['generated-sources'])
+ : {};
+ const generatedSourcesRuntime = hasGeneratedSources
+ ? processGeneratedSources(data['generated-sources-runtime'])
+ : {};
const processOpcodes = (opcodes, indent, generatedSources) => {
// first iterate the opcodes to find all the tags,
@@ -176,8 +221,12 @@ export class SolidityCompiler extends BaseCompiler {
for (const opcode of opcodes) {
// source 0 is the .sol file the user is
// editing, everything else is generated
- // sources
- if (opcode.source === 0) {
+ // sources (from version 0.8.x onwards).
+ // if source is undefined, then this is
+ // a compiler version which doesn't
+ // provide one (< 0.6.x), but we can
+ // infer 0 in this case.
+ if (opcode.source === 0 || opcode.source === undefined) {
opcode.line = charToLine[opcode.begin];
processPossibleTagOpcode(opcode, contractFunctions);