From 1db68bb1eedf5aeb69113b647ffbed1825c5a581 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 23 May 2024 17:40:06 +0100 Subject: [PATCH 1/4] fix subtle bug in recursion in getDependencyGraph --- .../src/app/plugins/contractFlattener.tsx | 6 ++- .../src/lib/logic/flattenerUtilities.ts | 42 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/contractFlattener.tsx b/apps/remix-ide/src/app/plugins/contractFlattener.tsx index f8205351c6..46176cc07c 100644 --- a/apps/remix-ide/src/app/plugins/contractFlattener.tsx +++ b/apps/remix-ide/src/app/plugins/contractFlattener.tsx @@ -1,3 +1,4 @@ +/* eslint-disable prefer-const */ import React from 'react' import { Plugin } from '@remixproject/engine' import { customAction } from '@remixproject/plugin-api' @@ -57,11 +58,12 @@ export class ContractFlattener extends Plugin { let sorted let result let sources + let order: string[] = [] try { - dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings) + dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings, order) sorted = dependencyGraph.isEmpty() ? [filePath] : dependencyGraph.sort().reverse() sources = source.sources - result = concatSourceFiles(sorted, sources) + result = concatSourceFiles(sorted, sources, order) } catch (err) { console.warn(err) } diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts index 2ff814125a..b30ab3be2a 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -4,39 +4,49 @@ const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm; const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm; type Visited = { [key: string]: number } -export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[]) { +export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[], order: string[]) { const graph = tsort(); const visited = {}; visited[target] = 1; - _traverse(graph, visited, ast, target, remappings); + _traverse(graph, visited, ast, target, remappings, order); return graph; } -export function concatSourceFiles(files: any[], sources: any) { - let concat = ''; - for (const file of files) { - const source = sources[file].content; - const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, ''); - const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, ''); - concat += `\n// File: ${file}\n\n`; - concat += sourceWithoutSPDX; - } - return concat; +export function concatSourceFiles(files: any[], sources: any, order: string[]) { + let concat = '' + order.reverse().forEach((importName) => { + for (const file of files) { + if (file === importName) { + const source = sources[file].content + const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') + const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') + concat += `\n// File: ${file}\n\n` + concat += sourceWithoutSPDX + } + const source = sources[importName].content + const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') + const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') + concat += `\n// File: ${importName}\n\n` + concat += sourceWithoutSPDX + } + }) + return concat } -function _traverse(graph: Graph, visited: Visited, ast: { [name: string]: CompilationSource }, name: string, remappings: string[]) { +function _traverse(graph: Graph, visited: Visited, ast: { [name: string]: CompilationSource }, name: string, remappings: string[], order: string[]) { let currentAst = null currentAst = ast[name].ast const dependencies = _getDependencies(currentAst); for (const dependency of dependencies) { const path = resolve(name, dependency, remappings); if (path in visited) { - // continue; // fixes wrong ordering of source in flattened file + continue; // fixes wrong ordering of source in flattened file } visited[path] = 1; graph.add(name, path); - _traverse(graph, visited, ast, path, remappings); + _traverse(graph, visited, ast, path, remappings, order); } + order.push(name) } function _getDependencies(ast: AstNode) { @@ -191,4 +201,4 @@ export function normalizeContractPath(contractPath: string): string[] { } const resultingPath = `${folders}${filename}` return [folders,resultingPath, filename] -} \ No newline at end of file +} From 1ee0820e1219f3f9bff327c8b0b2c4b976fd5d46 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Fri, 24 May 2024 10:45:39 +0100 Subject: [PATCH 2/4] remove preoptimizations in source file concatenation --- .../solidity-compiler/src/lib/logic/flattenerUtilities.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts index b30ab3be2a..8df959cb4e 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -14,7 +14,7 @@ export function getDependencyGraph(ast: { [name: string]: CompilationSource }, t export function concatSourceFiles(files: any[], sources: any, order: string[]) { let concat = '' - order.reverse().forEach((importName) => { + order.forEach((importName) => { for (const file of files) { if (file === importName) { const source = sources[file].content @@ -23,11 +23,6 @@ export function concatSourceFiles(files: any[], sources: any, order: string[]) { concat += `\n// File: ${file}\n\n` concat += sourceWithoutSPDX } - const source = sources[importName].content - const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') - const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') - concat += `\n// File: ${importName}\n\n` - concat += sourceWithoutSPDX } }) return concat From 2813fad8b2ff3b3a71f174e868b5db6959fa9c86 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Fri, 24 May 2024 14:59:42 +0100 Subject: [PATCH 3/4] add regex to fix duplicate pragma lines in flattened contract --- .../src/lib/logic/flattenerUtilities.ts | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts index 8df959cb4e..0f8defb4b8 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -1,15 +1,16 @@ import type { CompilationSource, AstNode } from '@remix-project/remix-solidity' -const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm; -const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm; +const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm +const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm +const PRAGMA_SOLIDITY_REGEX = /^pragma\s+.*$/gm type Visited = { [key: string]: number } export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[], order: string[]) { - const graph = tsort(); - const visited = {}; - visited[target] = 1; - _traverse(graph, visited, ast, target, remappings, order); - return graph; + const graph = tsort() + const visited = {} + visited[target] = 1 + _traverse(graph, visited, ast, target, remappings, order) + return graph } export function concatSourceFiles(files: any[], sources: any, order: string[]) { @@ -20,8 +21,9 @@ export function concatSourceFiles(files: any[], sources: any, order: string[]) { const source = sources[file].content const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') + const sourceWithoutDuplicatePragma = sourceWithoutSPDX.replace(PRAGMA_SOLIDITY_REGEX, '') concat += `\n// File: ${file}\n\n` - concat += sourceWithoutSPDX + concat += sourceWithoutDuplicatePragma } } }) @@ -31,15 +33,15 @@ export function concatSourceFiles(files: any[], sources: any, order: string[]) { function _traverse(graph: Graph, visited: Visited, ast: { [name: string]: CompilationSource }, name: string, remappings: string[], order: string[]) { let currentAst = null currentAst = ast[name].ast - const dependencies = _getDependencies(currentAst); + const dependencies = _getDependencies(currentAst) for (const dependency of dependencies) { - const path = resolve(name, dependency, remappings); + const path = resolve(name, dependency, remappings) if (path in visited) { continue; // fixes wrong ordering of source in flattened file } - visited[path] = 1; - graph.add(name, path); - _traverse(graph, visited, ast, path, remappings, order); + visited[path] = 1 + graph.add(name, path) + _traverse(graph, visited, ast, path, remappings, order) } order.push(name) } From 4ed97720af1d6b8624da79b68f8f043ea5f4a45f Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 27 May 2024 13:38:31 +0100 Subject: [PATCH 4/4] fix regexp for pragma experimental --- .../solidity-compiler/src/lib/logic/flattenerUtilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts index 0f8defb4b8..26cc45d992 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -2,7 +2,7 @@ import type { CompilationSource, AstNode } from '@remix-project/remix-solidity' const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm -const PRAGMA_SOLIDITY_REGEX = /^pragma\s+.*$/gm +const PRAGMA_SOLIDITY_REGEX = /^pragma experimental\s+.*$/gm type Visited = { [key: string]: number } export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[], order: string[]) {