ethershell 0.1.5-beta.0 → 0.1.6-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -17,7 +17,8 @@ import {
17
17
  compilerOptions,
18
18
  getCompilerOptions,
19
19
  compile,
20
- changeCompPath
20
+ changeCompPath,
21
+ flatten
21
22
  } from '../src/services/build.js';
22
23
  import { set, get, getDefault } from '../src/services/network.js';
23
24
  import { deleteDirectory } from '../src/services/files.js';
@@ -66,6 +67,7 @@ r.context.compInfo = getCompilerOptions;
66
67
  r.context.compOpts = compilerOptions;
67
68
  r.context.compPath = changeCompPath;
68
69
  r.context.build = compile;
70
+ r.context.flatten = flatten;
69
71
 
70
72
  // Config commands
71
73
  r.context.configInfo = getConfigInfo;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ethershell",
3
3
  "license": "MIT",
4
- "version": "0.1.5-beta.0",
4
+ "version": "0.1.6-beta.0",
5
5
  "description": "Interactive JavaScript console for Ethereum smart contract management",
6
6
  "author": "Alireza Kiakojouri (alirezaethdev@gmail.com)",
7
7
  "repository": {
@@ -110,12 +110,12 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
110
110
  // Wrap the contract instace with proxy
111
111
  const proxiedContract = createContractProxy(contractInstance, currentProvider, allAccounts);
112
112
 
113
- proxiedContract.contract_index = Array.from(contracts.values()).length;
114
- proxiedContract.contract_name = contractName;
115
- proxiedContract.contract_chain = connectedChain.name;
116
- proxiedContract.contract_chainId = connectedChain.chainId;
117
- proxiedContract.contract_deployType = 'ethershell-deployed';
118
- proxiedContract.contract_provider = currentProvider;
113
+ proxiedContract.index = Array.from(contracts.values()).length;
114
+ proxiedContract.name = contractName;
115
+ proxiedContract.chain = connectedChain.name;
116
+ proxiedContract.chainId = connectedChain.chainId;
117
+ proxiedContract.deployType = 'ethershell-deployed';
118
+ proxiedContract.provider = currentProvider;
119
119
 
120
120
  // Add to REPL context with proxy
121
121
  r.context[contractName] = proxiedContract;
@@ -193,12 +193,12 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
193
193
  // Wrap the contract instace with proxy
194
194
  const proxiedContract = createContractProxy(newContract, currentProvider, allAccounts);
195
195
 
196
- proxiedContract.contract_index = Array.from(contracts.values()).length;
197
- proxiedContract.contract_name = contractName;
198
- proxiedContract.contract_chain = connectedChain.name;
199
- proxiedContract.contract_chainId = connectedChain.chainId;
200
- proxiedContract.contract_deployType = 'ethershell-deployed';
201
- proxiedContract.contract_provider = currentProvider;
196
+ proxiedContract.index = Array.from(contracts.values()).length;
197
+ proxiedContract.name = contractName;
198
+ proxiedContract.chain = connectedChain.name;
199
+ proxiedContract.chainId = connectedChain.chainId;
200
+ proxiedContract.deployType = 'ethershell-deployed';
201
+ proxiedContract.provider = currentProvider;
202
202
 
203
203
  // Add to REPL context with proxy
204
204
  r.context[contractName] = proxiedContract;
@@ -133,9 +133,6 @@ export function compile(fullPath, selectedContracts, buildPath){
133
133
  [buildPath].forEach(check);
134
134
  }
135
135
 
136
- // Aggregated ABI container: { [contractName]: abiArray }
137
- const aggregatedAbis = {};
138
-
139
136
  let fileExt;
140
137
  if(!fullPath) {
141
138
  fullPath = path.resolve('.', 'contracts');
@@ -144,45 +141,56 @@ export function compile(fullPath, selectedContracts, buildPath){
144
141
  }
145
142
 
146
143
  if(!fileExt){
147
- // Directory: collect .sol files and compile each
148
144
  const solFiles = collectSolFiles(fullPath);
149
145
 
150
146
  if(!solFiles.length){
151
147
  throw 'There is no smart contract in the directory!';
152
148
  } else {
153
- solFiles.forEach((solFile) => {
154
- const contractAbis = build(solFile, selectedContracts, buildPath);
155
- // merge returned ABIs into aggregatedAbis
156
- Object.assign(aggregatedAbis, contractAbis);
157
- })
149
+ for(let i = 0; i < solFiles.length; i++){
150
+ build(solFiles[i], selectedContracts, buildPath);
151
+ }
158
152
  console.log(`Contracts compiled into ${path.resolve(buildPath)}`);
159
153
  }
160
154
  } else {
161
- // Single file
162
- const contractAbis = build(fullPath, selectedContracts, buildPath);
163
- // merge returned ABIs into aggregatedAbis
164
- Object.assign(aggregatedAbis, contractAbis);
155
+ build(fullPath, selectedContracts, buildPath);
165
156
  console.log(`Contract compiled into ${path.resolve(buildPath)}`);
166
157
  }
167
158
 
168
- // Write aggregated ABI file
169
- const abisDir = path.join(buildPath, 'abis');
170
- check(abisDir); // ensure dir exists (same util as builder.js)
171
- const aggregatedAbiPath = path.join(abisDir, 'aggregated.abi.json');
159
+ ////////////////////
160
+ // Generate aggregated ABI after compilation
161
+ const abisDir = path.join(buildPath, 'abis');
162
+ const aggregatedAbiPath = path.join(buildPath, 'aggregated.abi.json');
163
+
164
+ if (fs.existsSync(abisDir)) {
165
+ const files = fs.readdirSync(abisDir).filter(f => f.endsWith('.abi.json'));
166
+
167
+ const aggregated = [];
168
+ for (const file of files) {
169
+ const p = path.join(abisDir, file);
170
+ try {
171
+ const abi = JSON.parse(fs.readFileSync(p, 'utf8'));
172
+ if (Array.isArray(abi)) {
173
+ aggregated.push(...abi);
174
+ } else {
175
+ console.warn(`ABI file ${file} is not an array, skipping from aggregation`);
176
+ }
177
+ } catch (e) {
178
+ console.warn(`Failed to read ABI file ${file} for aggregation: ${e.message}`);
179
+ }
180
+ }
172
181
 
173
- // aggregatedAbis is { ContractName: abiArray }
174
- const flatAbi = Object.values(aggregatedAbis).flat();
182
+ fs.writeFileSync(aggregatedAbiPath, JSON.stringify(aggregated, null, 2));
183
+ console.log('Aggregated ABI generated at', path.resolve(aggregatedAbiPath));
184
+ } else {
185
+ console.warn('No ABI directory found, aggregated ABI not generated.');
186
+ }
175
187
 
176
- // Format: { "ContractName": [ ...abi... ], ... }
177
- fs.writeFileSync(aggregatedAbiPath, JSON.stringify(flatAbi, null, 2));
178
- console.log('Aggregated ABI written to', path.resolve(aggregatedAbiPath));
188
+ ////////////////////
179
189
 
180
190
  // Generate TypeScript types
181
191
  const typesOutputPath = path.join(buildPath, 'types');
182
192
  generateAllTypes(buildPath, typesOutputPath);
183
193
  console.log(`TypeScript types generated in ${path.resolve(typesOutputPath)}`);
184
-
185
- console.log(`Standard JSON Input generated in ${path.resolve(buildPath, 'standard-json')}`);
186
194
  } catch(err){
187
195
  console.error(err);
188
196
  }
@@ -196,4 +204,114 @@ export function changeCompPath(newPath) {
196
204
  compConfig.compilePath = newPath;
197
205
  configFile.compiler.compilePath = compConfig.compilePath;
198
206
  fs.writeFileSync(configPath, JSON.stringify(configFile, null, 2));
199
- }
207
+ }
208
+
209
+ /**
210
+ * Flatten a Solidity contract and its imports into a single file.
211
+ *
212
+ * @param {string} fullPath - Path to the root .sol file.
213
+ * @param {string} [outFile] - Optional path for the flattened output file.
214
+ * Defaults to `<dir>/<name>.flattened.sol`.
215
+ */
216
+ export function flatten(fullPath, outFile) {
217
+ if (!fullPath) {
218
+ throw new Error('flatten(): fullPath to the root Solidity file is required.');
219
+ }
220
+
221
+ const entryPath = path.resolve(fullPath);
222
+ if (!fs.existsSync(entryPath)) {
223
+ throw new Error(`flatten(): entry file does not exist: ${entryPath}`);
224
+ }
225
+
226
+ const visited = new Set();
227
+ const pieces = [];
228
+
229
+ let pragmaLine = null;
230
+ let hasSpdx = false;
231
+
232
+ function processFile(absPath, logicalName) {
233
+ if (visited.has(absPath)) return;
234
+ visited.add(absPath);
235
+
236
+ const raw = fs.readFileSync(absPath, 'utf8');
237
+
238
+ const lines = raw.split(/\r?\n/);
239
+
240
+ // Capture pragma and SPDX once from the entry or first file
241
+ for (const line of lines) {
242
+ const trimmed = line.trim();
243
+ if (!pragmaLine && trimmed.startsWith('pragma solidity')) {
244
+ pragmaLine = trimmed.replace(/[; ]+$/, ';');
245
+ }
246
+ if (!hasSpdx && trimmed.startsWith('// SPDX-License-Identifier:')) {
247
+ hasSpdx = true;
248
+ }
249
+ }
250
+
251
+ const imports = parseImports(raw);
252
+ for (const importPath of imports) {
253
+ const resolved = resolveImportPath(importPath, path.dirname(absPath));
254
+ processFile(resolved, importPath);
255
+ }
256
+
257
+ // Strip SPDX, pragma, and import lines from the body
258
+ const body = lines
259
+ .filter((line) => {
260
+ const trimmed = line.trim();
261
+ if (trimmed.startsWith('// SPDX-License-Identifier:')) return false;
262
+ if (trimmed.startsWith('pragma solidity')) return false;
263
+ if (trimmed.startsWith('import ')) return false;
264
+ return true;
265
+ })
266
+ .join('\n');
267
+
268
+ pieces.push(`\n\n// File: ${logicalName}\n\n${body}\n`);
269
+ }
270
+
271
+ const logicalName = path.basename(entryPath);
272
+ processFile(entryPath, logicalName);
273
+
274
+ let header = '';
275
+ if (hasSpdx) {
276
+ // Multiple different licenses may be mixed; explicit about it
277
+ header += '// SPDX-License-Identifier: MIXED\n';
278
+ }
279
+ if (pragmaLine) {
280
+ header += `${pragmaLine}\n\n`;
281
+ }
282
+
283
+ const flattened = `${header}${pieces.join('')}`;
284
+
285
+ const defaultOut =
286
+ outFile ||
287
+ path.join(
288
+ path.dirname(entryPath),
289
+ `${path.basename(entryPath, '.sol')}.flattened.sol`,
290
+ );
291
+
292
+ fs.writeFileSync(defaultOut, flattened);
293
+ console.log('Flattened contract written to', path.resolve(defaultOut));
294
+ }
295
+
296
+ /*============================= HELPER ==============================*/
297
+ // --- FLATTENING UTILITIES ---
298
+
299
+ function resolveImportPath(importPath, fromDir) {
300
+ if (importPath.startsWith('./') || importPath.startsWith('../')) {
301
+ return path.resolve(fromDir, importPath);
302
+ }
303
+ // Node-style imports from node_modules
304
+ return path.resolve(process.cwd(), 'node_modules', importPath);
305
+ }
306
+
307
+ function parseImports(content) {
308
+ const imports = [];
309
+ const importRegex =
310
+ /import\s+(?:(?:["']([^"']+)["'])|(?:.*?\sfrom\s+["']([^"']+)["']))\s*;/g;
311
+ let match;
312
+ while ((match = importRegex.exec(content))) {
313
+ const importPath = match[1] || match[2];
314
+ if (importPath) imports.push(importPath);
315
+ }
316
+ return imports;
317
+ }
@@ -81,39 +81,42 @@ export function build(fullPath, selectedContracts, buildPath){
81
81
 
82
82
  // Get the directory containing the contract
83
83
  const contractDir = path.dirname(fullPath);
84
- const filename = path.basename(fullPath, '.sol');
85
- // const source = fs.readFileSync(fullPath, 'utf8');
84
+ const filename = path.basename(fullPath); // keep extension here
85
+ const basename = path.basename(fullPath, '.sol');
86
+
87
+ // Build full standard JSON input, including all imports
88
+ const sources = collectSourcesForStandardJson(fullPath, filename);
86
89
 
87
- // Start collecting from the main contract
88
- let allSources = {}
89
- _collectSources(fullPath, allSources);
90
-
91
90
  const input = {
92
91
  language: 'Solidity',
93
- sources: allSources,
92
+ sources,
94
93
  settings: {
95
94
  outputSelection: {
96
95
  '*': {
97
96
  '*': ['*'],
98
97
  },
99
98
  },
100
- }
99
+ },
101
100
  };
102
101
 
103
102
  // Apply global compiler configuration
104
103
  if (compilerConfig.optimizer) {
105
104
  input.settings.optimizer = {
106
105
  enabled: true,
107
- runs: compilerConfig.optimizerRuns
106
+ runs: compilerConfig.optimizerRuns,
108
107
  };
109
108
  }
109
+
110
110
  if (compilerConfig.viaIR) {
111
111
  input.settings.viaIR = true;
112
112
  }
113
113
 
114
- // Compile without import callback
114
+ // Compile with import callback
115
115
  const output = JSON.parse(
116
- solc.compile(JSON.stringify(input))
116
+ solc.compile(
117
+ JSON.stringify(input),
118
+ { import: (importPath) => findImports(importPath, contractDir) }
119
+ )
117
120
  );
118
121
 
119
122
  if(output.errors) {
@@ -123,13 +126,15 @@ export function build(fullPath, selectedContracts, buildPath){
123
126
  throw errors;
124
127
  }
125
128
  }
126
-
129
+
130
+
131
+
127
132
  // Generate sub-paths of build
128
- const artifacts = path.join(buildPath, 'artifacts');
129
- const abis = path.join(buildPath, 'abis');
130
- const bytecode = path.join(buildPath, 'bytecode');
131
- const metadata = path.join(buildPath, 'metadata');
132
- const standardJsonDir = path.join(buildPath, 'standard-json');
133
+ const artifacts = path.join(buildPath, 'artifacts');
134
+ const abis = path.join(buildPath, 'abis');
135
+ const bytecode = path.join(buildPath, 'bytecode');
136
+ const metadata = path.join(buildPath, 'metadata');
137
+ const standardJsonDir = path.join(buildPath, 'standard-json');
133
138
  const subPaths = [
134
139
  artifacts,
135
140
  abis,
@@ -137,31 +142,17 @@ export function build(fullPath, selectedContracts, buildPath){
137
142
  metadata,
138
143
  standardJsonDir
139
144
  ];
140
- subPaths.forEach(check);
141
-
142
- // Save standard JSON input on standard-json
143
- const jsonInputPath = path.join(standardJsonDir, `${filename}.standard.json`);
144
- fs.writeFileSync(jsonInputPath, JSON.stringify(input, null, 2));
145
-
146
- // Determine the correct key for the main contract in the output
147
- const mainContractPath = path.relative(path.resolve('.'), path.resolve(fullPath)).split(path.sep).join('/');;
148
- const contractsInFile = output.contracts[mainContractPath];
149
-
150
- if (!contractsInFile) {
151
- throw new Error(`Could not find compiled output for ${mainContractPath}`);
152
- }
153
145
 
154
146
  // Ensure all sub-paths exist
155
147
  subPaths.forEach(check);
156
- const allContracts = Object.keys(contractsInFile);
148
+ const allContracts = Object.keys(output.contracts[`${filename}`]);
157
149
  const contractsToSave = selectedContracts.length > 0 ? allContracts.filter(
158
150
  (contractName) => {
159
151
  return selectedContracts.includes(contractName);
160
152
  }
161
153
  ): allContracts;
162
- const resultAbis = {}; // Collect ABIs to return
163
154
  contractsToSave.forEach((contractName) => {
164
- const contractsData = contractsInFile[contractName];
155
+ const contractsData = output.contracts[`${filename}`][contractName];
165
156
  // Save on artifacts
166
157
  const artifactsPath = path.join(artifacts, `${contractName}.json`);
167
158
  fs.writeFileSync(artifactsPath, JSON.stringify(contractsData, null, 2));
@@ -174,19 +165,13 @@ export function build(fullPath, selectedContracts, buildPath){
174
165
  // Save on metadata
175
166
  const metadataPath = path.join(metadata, `${contractName}.metadata.json`);
176
167
  fs.writeFileSync(metadataPath, JSON.stringify(contractsData.metadata, null, 2));
177
-
168
+ // Save standard JSON input for this entry file
169
+ const standardJsonPath = path.join(standardJsonDir,`${basename}.standard-input.json`);
170
+ fs.writeFileSync(standardJsonPath, JSON.stringify(input, null, 2));
178
171
  // Store abis and bytecode on local storage
179
172
  localStorage.setItem(`${contractName}_abi`, abisPath);
180
173
  localStorage.setItem(`${contractName}_bytecode`, bytecodePath);
181
-
182
- // Save ABI
183
- const abi = contractsData.abi || [];
184
- // Collect ABI in memory
185
- resultAbis[contractName] = abi;
186
174
  });
187
-
188
- // Return map of contractName -> abi
189
- return resultAbis;
190
175
  }
191
176
 
192
177
  /**
@@ -205,29 +190,49 @@ export function extractLoadableVersion(fullVersion) {
205
190
  return `v${match[1]}+commit.${match[2]}`;
206
191
  }
207
192
 
208
- /**
209
- * Helper to recursively collect all imports into the sources object
210
- */
211
- function _collectSources(filePath, allSourcesObj) {
212
- const absolutePath = path.resolve(filePath);
213
-
214
- // 1. Force POSIX style (forward slashes) for the map key
215
- let relativePath = path.relative(path.resolve('.'), absolutePath);
216
- relativePath = relativePath.split(path.sep).join('/');
217
-
218
- if (allSourcesObj[relativePath]) return allSourcesObj;
219
-
220
- const content = fs.readFileSync(absolutePath, 'utf8');
221
- allSourcesObj[relativePath] = { content };
222
-
223
- // 2. Resolve imports and recurse
224
- const importRegex = /import\s+(?:\{[^}]*\}\s+from\s+)?['"]([^'"]+)['"]/g;
225
- let match;
226
- while ((match = importRegex.exec(content)) !== null) {
227
- const importPath = match[1];
228
- const resolvedImportPath = path.resolve(path.dirname(absolutePath), importPath);
229
- _collectSources(resolvedImportPath, allSourcesObj);
193
+ /*=========================== HELPER =============================*/
194
+ function resolveImportPath(importPath, fromDir) {
195
+ if (importPath.startsWith('./') || importPath.startsWith('../')) {
196
+ return path.resolve(fromDir, importPath);
197
+ }
198
+
199
+ // Node-style import, resolve from node_modules
200
+ // e.g. '@openzeppelin/contracts/token/ERC20/ERC20.sol'
201
+ return path.resolve(process.cwd(), 'node_modules', importPath);
202
+ }
203
+
204
+ function collectSourcesForStandardJson(entryPath, logicalEntryName) {
205
+ const visited = new Set();
206
+ const sources = {};
207
+
208
+ function processFile(absPath, logicalName) {
209
+ if (visited.has(absPath)) return;
210
+ visited.add(absPath);
211
+
212
+ if (!fs.existsSync(absPath)) {
213
+ console.warn(`Warning: cannot resolve import "${logicalName}" at path "${absPath}"`);
214
+ return;
215
+ }
216
+
217
+ const content = fs.readFileSync(absPath, 'utf8');
218
+ sources[logicalName] = { content };
219
+
220
+ const importRegex =
221
+ /import\s+(?:(?:["']([^"']+)["'])|(?:.*?\sfrom\s+["']([^"']+)["']))\s*;/g;
222
+
223
+ let match;
224
+ while ((match = importRegex.exec(content))) {
225
+ const importPath = match[1] || match[2];
226
+ if (!importPath) continue;
227
+
228
+ const resolved = resolveImportPath(importPath, path.dirname(absPath));
229
+ // Use the import string itself as the logical source key,
230
+ // which is what solc/Etherscan expect
231
+ processFile(resolved, importPath);
232
+ }
230
233
  }
231
234
 
232
- return allSourcesObj;
235
+ processFile(entryPath, logicalEntryName);
236
+ return sources;
233
237
  }
238
+
@@ -22,12 +22,12 @@ export async function getContArr() {
22
22
 
23
23
  for (const x of contracts.values()) {
24
24
  let contract = {
25
- index: x.contract_index,
26
- name: x.contract_name,
25
+ index: x.index,
26
+ name: x.name,
27
27
  address: x.target,
28
- chain: x.contract_chain,
29
- chainId: x.contract_chainId,
30
- deployType: x.contract_deployType,
28
+ chain: x.chain,
29
+ chainId: x.chainId,
30
+ deployType: x.deployType,
31
31
  balance: await x.provider.getBalance(x.target)
32
32
  }
33
33
  contractsArray.push(contract);
@@ -26,39 +26,12 @@ import { eventOf } from './event.js';
26
26
  export function createContractProxy(contract, provider, allAccounts) {
27
27
  return new Proxy(contract, {
28
28
  get(target, prop) {
29
- // Explicit passthroughs for known non-ABI properties
30
29
  if (prop === 'provider') {
31
30
  return provider;
32
31
  }
33
- if (prop === 'target') {
34
- return target.target;
35
- }
36
- if (prop === 'interface') {
37
- return target.interface;
38
- }
39
- if (prop === 'runner') {
40
- return target.runner;
41
- }
42
- if (prop === 'connect') {
43
- return target.connect.bind(target);
44
- }
45
-
46
- // Allow internal metadata properties to pass through directly
47
- if (typeof prop === 'string' && prop.startsWith('contract_')) {
48
- return target[prop];
49
- }
50
-
51
- // Check if this prop is a contract ABI function
52
- const isContractMethod =
53
- target.interface &&
54
- typeof prop === 'string' &&
55
- (() => {
56
- try { target.interface.getFunction(prop); return true; }
57
- catch { return false; }
58
- })();
59
-
60
- // Pass through non-ABI, non-function properties (e.g. contract_name, contract_index)
61
- if (!isContractMethod && typeof target[prop] !== 'function') {
32
+
33
+ // Pass through non-function properties
34
+ if (typeof target[prop] !== 'function') {
62
35
  return target[prop];
63
36
  }
64
37
 
@@ -100,9 +73,8 @@ export function createContractProxy(contract, provider, allAccounts) {
100
73
 
101
74
  const options = hasOptions ? args.pop() : null;
102
75
 
103
- // Always resolve ABI methods via getFunction to avoid JS built-in property collisions
104
- let contractTarget = target;
105
- let method;
76
+ let method = target[prop];
77
+ let txOptions = {};
106
78
 
107
79
  // Handle 'from' option - switch signer if specified
108
80
  if (options && options.from) {
@@ -124,16 +96,10 @@ export function createContractProxy(contract, provider, allAccounts) {
124
96
 
125
97
  // Create new signer with the specified account
126
98
  const newSigner = new ethers.Wallet(account.privateKey, provider);
127
- contractTarget = target.connect(newSigner);
99
+ const connectedContract = target.connect(newSigner);
100
+ method = connectedContract[prop];
128
101
  }
129
102
 
130
- // Use getFunction for ABI methods to bypass JS name collisions
131
- method = isContractMethod
132
- ? contractTarget.getFunction(prop)
133
- : contractTarget[prop];
134
-
135
- let txOptions = {};
136
-
137
103
  // Build transaction options object with all supported ethers.js v6 options
138
104
  if (options) {
139
105
  // Value (for payable functions)
@@ -194,7 +160,7 @@ export function createContractProxy(contract, provider, allAccounts) {
194
160
  }
195
161
 
196
162
  // Call the method with remaining args and tx options
197
- const result = await method(...args);
163
+ const result = await method.apply(method, args);
198
164
 
199
165
  // Check if result is a transaction response (has wait method)
200
166
  if (result && typeof result.wait === 'function') {
@@ -49,7 +49,7 @@ export function generateAllTypes(buildPath, typesOutputPath = './src/types') {
49
49
  throw new Error(`ABIs directory not found at ${abisPath}`);
50
50
  }
51
51
 
52
- const abiFiles = fs.readdirSync(abisPath).filter(f => f.endsWith('.abi.json') && f !== 'aggregated.abi.json');
52
+ const abiFiles = fs.readdirSync(abisPath).filter(f => f.endsWith('.abi.json'));
53
53
  const generatedFiles = [];
54
54
 
55
55
  abiFiles.forEach(file => {
@@ -1,17 +0,0 @@
1
- Bytecode (what we are looking for)
2
-
3
- 608060405234610370576114d58038038061001981610374565b9283398101906060818303126103705780516001600160401b0381116103705782610045918301610399565b60208201519092906001600160401b03811161037057604091610069918401610399565b91015160ff8116809103610370575f80546001600160a01b0319163317905582516001600160401b03811161028157600254600181811c91168015610366575b602082101461026357601f8111610303575b506020601f82116001146102a057819293945f92610295575b50508160011b915f199060031b1c1916176002555b81516001600160401b03811161028157600354600181811c91168015610277575b602082101461026357601f8111610200575b50602092601f821160011461019f57928192935f92610194575b50508160011b915f199060031b1c1916176003555b60ff1960045416176004557f82488d8ab594db2178e4a45b7106aaa804836e608f001b5d7fcb6c3514730b3e60408051308152336020820152a16040516110ea90816103eb8239f35b015190505f80610136565b601f1982169360035f52805f20915f5b8681106101e857508360019596106101d0575b505050811b0160035561014b565b01515f1960f88460031b161c191690555f80806101c2565b919260206001819286850151815501940192016101af565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c81019160208410610259575b601f0160051c01905b81811061024e575061011c565b5f8155600101610241565b9091508190610238565b634e487b7160e01b5f52602260045260245ffd5b90607f169061010a565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100d4565b601f1982169060025f52805f20915f5b8181106102eb575095836001959697106102d3575b505050811b016002556100e9565b01515f1960f88460031b161c191690555f80806102c5565b9192602060018192868b0151815501940192016102b0565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c8101916020841061035c575b601f0160051c01905b81811061035157506100bb565b5f8155600101610344565b909150819061033b565b90607f16906100a9565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761028157604052565b81601f82011215610370578051906001600160401b038211610281576103c8601f8301601f1916602001610374565b928284526020838301011161037057815f9260208093018386015e830101529056fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610d765750806306fdde0314610ce4578063095ea7b314610bcd57806316dead1414610b7657806318160ddd14610b5957806323b872dd14610b02578063313ce56714610ae257806340c10f1914610a1c57806342966c68146109635780635353a2d81461074a57806362a09477146106c157806370a08231146106895780638da5cb5b1461066257806395d89b411461059b578063a3895fff1461036e578063a9059cbb14610287578063c112dfa31461021d578063c42069ec14610174578063dd62ed3e146101245763e30c3978146100f8575f80fd5b34610120575f366003190112610120576001546040516001600160a01b039091168152602090f35b5f80fd5b346101205760403660031901126101205761013d610df3565b610145610e09565b6001600160a01b039182165f908152600760209081526040808320949093168252928352819020549051908152f35b346101205760203660031901126101205761018d610df3565b5f546001600160a01b031633810361020757506001600160a01b031680156101f5576020817f7d5f578daab924f3f271d863dd8729e6970e9186812579e22f892146def80f67926bffffffffffffffffffffffff60a01b6001541617600155604051908152a1005b6334d7d10d60e21b5f5260045260245ffd5b63a3ee740f60e01b5f526004523360245260445ffd5b346101205760203660031901126101205760043560ff8116809103610120575f546001600160a01b0316338103610207577fa667a2c7cf0813fa2c1f7a0a0093db4cf6fc7e9c5264f29df1aa880b409a312e6020838060ff196004541617600455604051908152a1005b34610120576040366003190112610120576102a0610df3565b60243590336102bc576313053d9360e21b5f523360045260245ffd5b6001600160a01b031690816102de5750639cfea58360e01b5f5260045260245ffd5b335f908152600660205260409020548181106103555750815f52600660205261030b8160405f2054610ef1565b50335f52600660205260405f20818154039055815f52600660205260405f208181540190556040519081525f5160206110955f395f51905f5260203392a360405160018152602090f35b63db42144d60e01b5f523360045260245260445260645ffd5b346101205761037c36610e41565b5f546001600160a01b03163381036102075750805167ffffffffffffffff8111610587576103ab600354610eb9565b601f811161051f575b50602091601f82116001146104b4579181925f926104a9575b50508160011b915f199060031b1c1916176003555b604051602081525f6003546103f681610eb9565b908160208501526001811690815f14610487575060011461043d575b507fc5109575ebaf6138fc9735faca1c61ff8b7bf4f91870337266cc2bce01a75e15919081900390a1005b60035f9081525f5160206110755f395f51905f52939250905b80821061046c5750909150810160400181610412565b91926001816020925460408588010152019101909291610456565b60ff191660408086019190915291151560051b84019091019150829050610412565b0151905082806103cd565b601f1982169260035f525f5160206110755f395f51905f52915f5b858110610507575083600195106104ef575b505050811b016003556103e2565b01515f1960f88460031b161c191690558280806104e1565b919260206001819286850151815501940192016104cf565b60035f52601f820160051c5f5160206110755f395f51905f52019060208310610572575b601f0160051c5f5160206110755f395f51905f5201905b81811061056757506103b4565b5f815560010161055a565b5f5160206110755f395f51905f529150610543565b634e487b7160e01b5f52604160045260245ffd5b34610120575f366003190112610120576040515f6003546105bb81610eb9565b808452906001811690811561063e57506001146105f3575b6105ef836105e381850382610e1f565b60405191829182610dc9565b0390f35b91905060035f525f5160206110755f395f51905f52915f905b808210610624575090915081016020016105e36105d3565b91926001816020925483858801015201910190929161060c565b60ff191660208086019190915291151560051b840190910191506105e390506105d3565b34610120575f366003190112610120575f546040516001600160a01b039091168152602090f35b34610120576020366003190112610120576001600160a01b036106aa610df3565b165f526006602052602060405f2054604051908152f35b34610120575f366003190112610120576001546001600160a01b03811690338203610733575f80546001600160a01b0319908116841782559091166001556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91a1005b5063176f517960e01b5f526004523360245260445ffd5b346101205761075836610e41565b5f546001600160a01b03163381036102075750805167ffffffffffffffff811161058757610787600254610eb9565b601f81116108fb575b50602091601f8211600114610890579181925f92610885575b50508160011b915f199060031b1c1916176002555b604051602081525f6002546107d281610eb9565b908160208501526001811690815f146108635750600114610819575b507f2ae91ea06611bdd535a7ec999b4730beaa64fdbc044a50645c052153e55c3e2d919081900390a1005b60025f9081525f5160206110555f395f51905f52939250905b80821061084857509091508101604001816107ee565b91926001816020925460408588010152019101909291610832565b60ff191660408086019190915291151560051b840190910191508290506107ee565b0151905082806107a9565b601f1982169260025f525f5160206110555f395f51905f52915f5b8581106108e3575083600195106108cb575b505050811b016002556107be565b01515f1960f88460031b161c191690558280806108bd565b919260206001819286850151815501940192016108ab565b60025f52601f820160051c5f5160206110555f395f51905f5201906020831061094e575b601f0160051c5f5160206110555f395f51905f5201905b8181106109435750610790565b5f8155600101610936565b5f5160206110555f395f51905f52915061091f565b34610120576020366003190112610120576004353361098f576313053d9360e21b5f523360045260245ffd5b335f90815260066020526040902054818110610355575f826109b381600554611047565b6005553382526006602052604082206109cd828254611047565b90557f410c5c259085cde81fedf70c1aa308ec839373c26e9b7ada6560a2aca0254eb660406005548151908482526020820152a16040519081525f5160206110955f395f51905f5260203392a3005b3461012057604036600319011261012057610a35610df3565b5f5460243591906001600160a01b031633810361020757506001600160a01b03169081610a6f5750639cfea58360e01b5f5260045260245ffd5b5f5160206110955f395f51905f52602082610a8d5f94600554610ef1565b6005558484526006825260408420610aa6828254610ef1565b90557fcc9c58b575eabd3f6a1ee653e91fcea3ff546867ffc3782a3bbca1f9b6dbb8df604060055481519084825285820152a1604051908152a3005b34610120575f36600319011261012057602060ff60045416604051908152f35b34610120576060366003190112610120576020610b4f610b20610df3565b610b28610e09565b6044359160018060a01b0382165f5260068552610b498360405f2054610ef1565b50610f12565b6040519015158152f35b34610120575f366003190112610120576020600554604051908152f35b3461012057604036600319011261012057610b8f610df3565b610b97610e09565b9060018060a01b03165f52600860205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461012057604036600319011261012057610be6610df3565b6024359033610c02576322f051b160e21b5f523360045260245ffd5b6001600160a01b0316903382141580610cd0575b80610cc7575b15610cb457335f908152600660205260409020548181106103555750335f52600860205260405f20825f5260205260405f20600160ff19825416179055335f52600760205260405f20825f5260205260405f20610c7a828254610ef1565b90556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a360405160018152602090f35b5063270af7ed60e11b5f5260045260245ffd5b50811515610c1c565b505f546001600160a01b0316821415610c16565b34610120575f366003190112610120576040515f600254610d0481610eb9565b808452906001811690811561063e5750600114610d2b576105ef836105e381850382610e1f565b91905060025f525f5160206110555f395f51905f52915f905b808210610d5c575090915081016020016105e36105d3565b919260018160209254838588010152019101909291610d44565b34610120576020366003190112610120576004359063ffffffff60e01b8216809203610120576020916301ffc9a760e01b8114908115610db8575b5015158152f35b6336372b0760e01b14905083610db1565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012057565b602435906001600160a01b038216820361012057565b90601f8019910116810190811067ffffffffffffffff82111761058757604052565b60206003198201126101205760043567ffffffffffffffff811161012057816023820112156101205780600401359067ffffffffffffffff82116105875760405192610e97601f8401601f191660200185610e1f565b8284526024838301011161012057815f92602460209301838601378301015290565b90600182811c92168015610ee7575b6020831014610ed357565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ec8565b91908201809211610efe57565b634e487b7160e01b5f52601160045260245ffd5b6001600160a01b0316908115611034576001600160a01b0316918215611021575f828152600660205260409020548181106103555750338203610f8f575b60205f5160206110955f395f51905f5291835f526006825260405f20818154039055845f526006825260405f20818154019055604051908152a3600190565b5f82815260086020908152604080832033845290915290205460ff161561100e575f828152600760209081526040808320338452909152902054818110610ff557505f828152600760209081526040808320338452909152902080548290039055610f50565b630c95cf2760e11b5f523360045260245260445260645ffd5b6313053d9360e21b5f523360045260245ffd5b82639cfea58360e01b5f5260045260245ffd5b506313053d9360e21b5f5260045260245ffd5b91908203918211610efe5756fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acec2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85bddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200a75d1a4c912be5dc2d821991e5c0ea3009115e80fb66c939e1f3ac47c98f47964736f6c634300081d0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007506f6c79676f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003504f4c0000000000000000000000000000000000000000000000000000000000
4
-
5
-
6
-
7
- - vs what we got -
8
-
9
-
10
-
11
- We tried looking for a match from the list of compiled contract bytecode outputs (as listed below), but was unable to find an exact match.
12
-
13
-
14
-
15
- 1) contracts/ERC20.sol:ERC20
16
-
17
- 608060405234610370576113eb8038038061001981610374565b9283398101906060818303126103705780516001600160401b0381116103705782610045918301610399565b60208201519092906001600160401b03811161037057604091610069918401610399565b91015160ff8116809103610370575f80546001600160a01b0319163317905582516001600160401b03811161028157600254600181811c91168015610366575b602082101461026357601f8111610303575b506020601f82116001146102a057819293945f92610295575b50508160011b915f199060031b1c1916176002555b81516001600160401b03811161028157600354600181811c91168015610277575b602082101461026357601f8111610200575b50602092601f821160011461019f57928192935f92610194575b50508160011b915f199060031b1c1916176003555b60ff1960045416176004557f82488d8ab594db2178e4a45b7106aaa804836e608f001b5d7fcb6c3514730b3e60408051308152336020820152a1604051610fe890816104038239f35b015190505f80610136565b601f1982169360035f52805f20915f5b8681106101e857508360019596106101d0575b505050811b0160035561014b565b01515f1960f88460031b161c191690555f80806101c2565b919260206001819286850151815501940192016101af565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c81019160208410610259575b601f0160051c01905b81811061024e575061011c565b5f8155600101610241565b9091508190610238565b634e487b7160e01b5f52602260045260245ffd5b90607f169061010a565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100d4565b601f1982169060025f52805f20915f5b8181106102eb575095836001959697106102d3575b505050811b016002556100e9565b01515f1960f88460031b161c191690555f80806102c5565b9192602060018192868b0151815501940192016102b0565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c8101916020841061035c575b601f0160051c01905b81811061035157506100bb565b5f8155600101610344565b909150819061033b565b90607f16906100a9565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761028157604052565b81601f82011215610370578051906001600160401b038211610281576103c8601f8301601f1916602001610374565b9282845260208383010111610370575f5b8281106103ed57505060205f918301015290565b806020809284010151828287010152016103d956fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610b5b5750806306fdde0314610b38578063095ea7b314610a2157806316dead14146109ca57806318160ddd146109ad57806323b872dd14610956578063313ce5671461093657806340c10f191461087057806342966c68146107b75780635353a2d81461063057806362a09477146105a757806370a082311461056f5780638da5cb5b1461054857806395d89b411461050e578063a3895fff1461036e578063a9059cbb14610287578063c112dfa31461021d578063c42069ec14610174578063dd62ed3e146101245763e30c3978146100f8575f80fd5b34610120575f366003190112610120576001546040516001600160a01b039091168152602090f35b5f80fd5b346101205760403660031901126101205761013d610bf5565b610145610c0b565b6001600160a01b039182165f908152600760209081526040808320949093168252928352819020549051908152f35b346101205760203660031901126101205761018d610bf5565b5f546001600160a01b031633810361020757506001600160a01b031680156101f5576020817f7d5f578daab924f3f271d863dd8729e6970e9186812579e22f892146def80f67926bffffffffffffffffffffffff60a01b6001541617600155604051908152a1005b6334d7d10d60e21b5f5260045260245ffd5b63a3ee740f60e01b5f526004523360245260445ffd5b346101205760203660031901126101205760043560ff8116809103610120575f546001600160a01b0316338103610207577fa667a2c7cf0813fa2c1f7a0a0093db4cf6fc7e9c5264f29df1aa880b409a312e6020838060ff196004541617600455604051908152a1005b34610120576040366003190112610120576102a0610bf5565b60243590336102bc576313053d9360e21b5f523360045260245ffd5b6001600160a01b031690816102de5750639cfea58360e01b5f5260045260245ffd5b335f908152600660205260409020548181106103555750815f52600660205261030b8160405f2054610def565b50335f52600660205260405f20818154039055815f52600660205260405f208181540190556040519081525f516020610f935f395f51905f5260203392a360405160018152602090f35b63db42144d60e01b5f523360045260245260445260645ffd5b346101205761037c36610c43565b5f546001600160a01b03163381036102075750805167ffffffffffffffff81116104fa576103ab600354610cbb565b601f8111610492575b50602091601f8211600114610427579181925f9261041c575b50508160011b915f199060031b1c1916176003555b7fc5109575ebaf6138fc9735faca1c61ff8b7bf4f91870337266cc2bce01a75e15604051602081528061041760208201610d7f565b0390a1005b0151905082806103cd565b601f1982169260035f525f516020610f735f395f51905f52915f5b85811061047a57508360019510610462575b505050811b016003556103e2565b01515f1960f88460031b161c19169055828080610454565b91926020600181928685015181550194019201610442565b60035f52601f820160051c5f516020610f735f395f51905f520190602083106104e5575b601f0160051c5f516020610f735f395f51905f5201905b8181106104da57506103b4565b5f81556001016104cd565b5f516020610f735f395f51905f5291506104b6565b634e487b7160e01b5f52604160045260245ffd5b34610120575f366003190112610120576105446040516105388161053181610d7f565b0382610c21565b60405191829182610bae565b0390f35b34610120575f366003190112610120575f546040516001600160a01b039091168152602090f35b34610120576020366003190112610120576001600160a01b03610590610bf5565b165f526006602052602060405f2054604051908152f35b34610120575f366003190112610120576001546001600160a01b03811690338203610619575f80546001600160a01b0319908116841782559091166001556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91a1005b5063176f517960e01b5f526004523360245260445ffd5b346101205761063e36610c43565b5f546001600160a01b03163381036102075750805167ffffffffffffffff81116104fa5761066d600254610cbb565b601f811161074f575b50602091601f82116001146106e4579181925f926106d9575b50508160011b915f199060031b1c1916176002555b7f2ae91ea06611bdd535a7ec999b4730beaa64fdbc044a50645c052153e55c3e2d604051602081528061041760208201610cf3565b01519050828061068f565b601f1982169260025f525f516020610f535f395f51905f52915f5b8581106107375750836001951061071f575b505050811b016002556106a4565b01515f1960f88460031b161c19169055828080610711565b919260206001819286850151815501940192016106ff565b60025f52601f820160051c5f516020610f535f395f51905f520190602083106107a2575b601f0160051c5f516020610f535f395f51905f5201905b8181106107975750610676565b5f815560010161078a565b5f516020610f535f395f51905f529150610773565b3461012057602036600319011261012057600435336107e3576313053d9360e21b5f523360045260245ffd5b335f90815260066020526040902054818110610355575f8261080781600554610f45565b600555338252600660205260408220610821828254610f45565b90557f410c5c259085cde81fedf70c1aa308ec839373c26e9b7ada6560a2aca0254eb660406005548151908482526020820152a16040519081525f516020610f935f395f51905f5260203392a3005b3461012057604036600319011261012057610889610bf5565b5f5460243591906001600160a01b031633810361020757506001600160a01b031690816108c35750639cfea58360e01b5f5260045260245ffd5b5f516020610f935f395f51905f526020826108e15f94600554610def565b60055584845260068252604084206108fa828254610def565b90557fcc9c58b575eabd3f6a1ee653e91fcea3ff546867ffc3782a3bbca1f9b6dbb8df604060055481519084825285820152a1604051908152a3005b34610120575f36600319011261012057602060ff60045416604051908152f35b346101205760603660031901126101205760206109a3610974610bf5565b61097c610c0b565b6044359160018060a01b0382165f526006855261099d8360405f2054610def565b50610e10565b6040519015158152f35b34610120575f366003190112610120576020600554604051908152f35b34610120576040366003190112610120576109e3610bf5565b6109eb610c0b565b9060018060a01b03165f52600860205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461012057604036600319011261012057610a3a610bf5565b6024359033610a56576322f051b160e21b5f523360045260245ffd5b6001600160a01b0316903382141580610b24575b80610b1b575b15610b0857335f908152600660205260409020548181106103555750335f52600860205260405f20825f5260205260405f20600160ff19825416179055335f52600760205260405f20825f5260205260405f20610ace828254610def565b90556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a360405160018152602090f35b5063270af7ed60e11b5f5260045260245ffd5b50811515610a70565b505f546001600160a01b0316821415610a6a565b34610120575f366003190112610120576105446040516105388161053181610cf3565b34610120576020366003190112610120576004359063ffffffff60e01b8216809203610120576020916301ffc9a760e01b8114908115610b9d575b5015158152f35b6336372b0760e01b14905083610b96565b9190916020815282518060208301525f5b818110610bdf575060409293505f838284010152601f8019910116010190565b8060208092870101516040828601015201610bbf565b600435906001600160a01b038216820361012057565b602435906001600160a01b038216820361012057565b90601f8019910116810190811067ffffffffffffffff8211176104fa57604052565b60206003198201126101205760043567ffffffffffffffff811161012057816023820112156101205780600401359067ffffffffffffffff82116104fa5760405192610c99601f8401601f191660200185610c21565b8284526024838301011161012057815f92602460209301838601378301015290565b90600182811c92168015610ce9575b6020831014610cd557565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610cca565b6002545f9291610d0282610cbb565b8082529160018116908115610d635750600114610d1d575050565b60025f9081529293509091905f516020610f535f395f51905f525b838310610d49575060209250010190565b600181602092949394548385870101520191019190610d38565b9050602093945060ff929192191683830152151560051b010190565b6003545f9291610d8e82610cbb565b8082529160018116908115610d635750600114610da9575050565b60035f9081529293509091905f516020610f735f395f51905f525b838310610dd5575060209250010190565b600181602092949394548385870101520191019190610dc4565b91908201809211610dfc57565b634e487b7160e01b5f52601160045260245ffd5b6001600160a01b0316908115610f32576001600160a01b0316918215610f1f575f828152600660205260409020548181106103555750338203610e8d575b60205f516020610f935f395f51905f5291835f526006825260405f20818154039055845f526006825260405f20818154019055604051908152a3600190565b5f82815260086020908152604080832033845290915290205460ff1615610f0c575f828152600760209081526040808320338452909152902054818110610ef357505f828152600760209081526040808320338452909152902080548290039055610e4e565b630c95cf2760e11b5f523360045260245260445260645ffd5b6313053d9360e21b5f523360045260245ffd5b82639cfea58360e01b5f5260045260245ffd5b506313053d9360e21b5f5260045260245ffd5b91908203918211610dfc5756fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acec2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85bddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef{ipfs}64736f6c634300081b0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007506f6c79676f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003504f4c0000000000000000000000000000000000000000000000000000000000