Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sol2uml

Package Overview
Dependencies
Maintainers
1
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sol2uml - npm Package Compare versions

Comparing version 2.5.10 to 2.5.11

21

lib/diffContracts.d.ts
import { EtherscanParser } from './parserEtherscan';
interface DiffOptions {
network: string;
bNetwork?: string;
lineBuffer: number;
summary?: boolean;
}

@@ -20,9 +22,12 @@ interface FlattenAndDiffOptions extends DiffOptions {

contractNameA: string;
contractNameB?: string;
}
export declare const compareVerifiedContracts: (addressA: string, aEtherscanParser: EtherscanParser, addressB: string, bEtherscanParser: EtherscanParser, options: DiffOptions) => Promise<void>;
export declare const compareVerified2Local: (addressA: string, aEtherscanParser: EtherscanParser, localFolders: string[], options: DiffOptions) => Promise<void>;
export declare const compareFlattenContracts: (addressA: string, addressB: string, aEtherscanParser: EtherscanParser, bEtherscanParser: EtherscanParser, options: FlattenAndDiffOptions) => Promise<{
contractNameA: string;
contractNameB: string;
}
export declare const compareContracts: (addressA: string, addressB: string, etherscanParserA: EtherscanParser, etherscanParserB: EtherscanParser, options: DiffOptions) => Promise<CompareContracts>;
export declare const displayContractNames: (addressA: string, addressB: string, contractNameA: string, contractNameB: string, options: {
network: string;
bNetwork?: string;
}) => void;
}>;
export declare const diffVerified2Local: (addressA: string, etherscanParserA: EtherscanParser, baseFolders: string[], ignoreFilesOrFolders?: string[]) => Promise<CompareContracts>;
export declare const diffVerifiedContracts: (addressA: string, addressB: string, etherscanParserA: EtherscanParser, etherscanParserB: EtherscanParser, options: DiffOptions) => Promise<CompareContracts>;
export declare const displayFileDiffSummary: (fileDiffs: DiffFiles[]) => void;

@@ -32,6 +37,2 @@ export declare const displayFileDiffs: (fileDiffs: DiffFiles[], options?: {

}) => void;
export declare const flattenAndDiff: (addressA: string, addressB: string, aEtherscanParser: EtherscanParser, bEtherscanParser: EtherscanParser, options: FlattenAndDiffOptions) => Promise<{
contractNameA: string;
contractNameB: string;
}>;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.flattenAndDiff = exports.displayFileDiffs = exports.displayFileDiffSummary = exports.displayContractNames = exports.compareContracts = void 0;
const regEx_1 = require("./utils/regEx");
exports.displayFileDiffs = exports.displayFileDiffSummary = exports.diffVerifiedContracts = exports.diffVerified2Local = exports.compareFlattenContracts = exports.compareVerified2Local = exports.compareVerifiedContracts = void 0;
const clc = require('cli-color');
const fs_1 = require("fs");
const path_1 = require("path");
const parserFiles_1 = require("./parserFiles");
const writerFiles_1 = require("./writerFiles");
const regEx_1 = require("./utils/regEx");
const diff_1 = require("./utils/diff");
const compareContracts = async (addressA, addressB, etherscanParserA, etherscanParserB, options) => {
const debug = require('debug')('sol2uml');
const compareVerifiedContracts = async (addressA, aEtherscanParser, addressB, bEtherscanParser, options) => {
const { contractNameA, contractNameB, files } = await (0, exports.diffVerifiedContracts)(addressA, addressB, aEtherscanParser, bEtherscanParser, options);
if (!options.summary) {
(0, exports.displayFileDiffs)(files, options);
}
console.log(`Compared the "${contractNameA}" contract with address ${addressA} on ${options.network}`);
console.log(`to the "${contractNameB}" contract with address ${addressB} on ${options.bNetwork || options.network}\n`);
(0, exports.displayFileDiffSummary)(files);
};
exports.compareVerifiedContracts = compareVerifiedContracts;
const compareVerified2Local = async (addressA, aEtherscanParser, localFolders, options) => {
// compare verified contract to local files
const { contractNameA, files } = await (0, exports.diffVerified2Local)(addressA, aEtherscanParser, localFolders);
if (!options.summary) {
(0, exports.displayFileDiffs)(files, options);
}
console.log(`Compared the "${contractNameA}" contract with address ${addressA} on ${options.network}`);
console.log(`to local files under folders "${localFolders}"\n`);
(0, exports.displayFileDiffSummary)(files);
};
exports.compareVerified2Local = compareVerified2Local;
const compareFlattenContracts = async (addressA, addressB, aEtherscanParser, bEtherscanParser, options) => {
// Get verified Solidity code from Etherscan and flatten
const { solidityCode: codeA, contractName: contractNameA } = await aEtherscanParser.getSolidityCode(addressA, options.aFile);
const { solidityCode: codeB, contractName: contractNameB } = await bEtherscanParser.getSolidityCode(addressB, options.bFile || options.aFile);
(0, diff_1.diffCode)(codeA, codeB, options.lineBuffer);
if (options.saveFiles) {
await (0, writerFiles_1.writeSolidity)(codeA, addressA);
await (0, writerFiles_1.writeSolidity)(codeB, addressB);
}
console.log(`Compared the flattened "${contractNameA}" contract with address ${addressA} on ${options.network}`);
console.log(`to the flattened "${contractNameB}" contract with address ${addressB} on ${options.bNetwork || options.network}\n`);
return { contractNameA, contractNameB };
};
exports.compareFlattenContracts = compareFlattenContracts;
const diffVerified2Local = async (addressA, etherscanParserA, baseFolders, ignoreFilesOrFolders = []) => {
const files = [];
// Get all the source files for the verified contract from Etherscan
const { files: aFiles, contractName: contractNameA } = await etherscanParserA.getSourceCode(addressA);
const bFiles = await (0, parserFiles_1.getSolidityFilesFromFolderOrFiles)(baseFolders, ignoreFilesOrFolders);
// For each file in the A contract
for (const aFile of aFiles) {
// Look for A contract filename in local filesystem
let bFile;
// for each of the base folders
for (const baseFolder of baseFolders) {
bFile = bFiles.find((bFile) => {
const resolvedPath = (0, path_1.resolve)(process.cwd(), baseFolder, aFile.filename);
return bFile === resolvedPath;
});
if (bFile) {
break;
}
}
if (bFile) {
try {
debug(`Matched verified file ${aFile.filename} to local file ${bFile}`);
// Try and read code from bFile
const bCode = (0, fs_1.readFileSync)(bFile, 'utf8');
// The A contract filename exists in the B contract
if (aFile.code !== bCode) {
// console.log(`${aFile.filename} ${clc.red('different')}:`)
files.push({
filename: aFile.filename,
aCode: aFile.code,
bCode,
result: 'changed',
});
}
else {
files.push({
filename: aFile.filename,
aCode: aFile.code,
bCode,
result: 'match',
});
}
}
catch (err) {
throw Error(`Failed to read local file ${bFile}`);
}
}
else {
debug(`Failed to find local file for verified files ${aFile.filename}`);
// The A contract filename does not exist in the B contract
files.push({
filename: aFile.filename,
aCode: aFile.code,
result: 'removed',
});
}
}
// Sort by filename
return {
files: files.sort((a, b) => a.filename.localeCompare(b.filename)),
contractNameA,
};
};
exports.diffVerified2Local = diffVerified2Local;
const diffVerifiedContracts = async (addressA, addressB, etherscanParserA, etherscanParserB, options) => {
const files = [];
const { files: aFiles, contractName: contractNameA } = await etherscanParserA.getSourceCode(addressA);
const { files: bFiles, contractName: contractNameB } = await etherscanParserB.getSourceCode(addressB);

@@ -79,8 +182,3 @@ if (aFiles.length === 1 && bFiles.length === 1) {

};
exports.compareContracts = compareContracts;
const displayContractNames = (addressA, addressB, contractNameA, contractNameB, options) => {
console.log(`Contract A: ${addressA} ${contractNameA} on ${options.network}`);
console.log(`Contract B: ${addressB} ${contractNameB} on ${options.bNetwork || options.network}\n`);
};
exports.displayContractNames = displayContractNames;
exports.diffVerifiedContracts = diffVerifiedContracts;
const displayFileDiffSummary = (fileDiffs) => {

@@ -122,16 +220,2 @@ for (const file of fileDiffs) {

exports.displayFileDiffs = displayFileDiffs;
const flattenAndDiff = async (addressA, addressB, aEtherscanParser, bEtherscanParser, options) => {
// Get verified Solidity code from Etherscan and flatten
const { solidityCode: codeA, contractName: contractNameA } = await aEtherscanParser.getSolidityCode(addressA, options.aFile);
const { solidityCode: codeB, contractName: contractNameB } = await bEtherscanParser.getSolidityCode(addressB, options.bFile || options.aFile);
(0, exports.displayContractNames)(addressA, addressB, contractNameA, contractNameB, options);
(0, diff_1.diffCode)(codeA, codeB, options.lineBuffer);
if (options.saveFiles) {
await (0, writerFiles_1.writeSolidity)(codeA, addressA);
await (0, writerFiles_1.writeSolidity)(codeB, addressB);
}
(0, exports.displayContractNames)(addressA, addressB, contractNameA, contractNameB, options);
return { contractNameA, contractNameB };
};
exports.flattenAndDiff = flattenAndDiff;
//# sourceMappingURL=diffContracts.js.map

@@ -60,3 +60,3 @@ "use strict";

.on('end', () => {
debug(`Got Solidity files to be parsed: ${files}`);
// debug(`Got Solidity files to be parsed: ${files}`)
resolve(files);

@@ -63,0 +63,0 @@ });

@@ -50,4 +50,4 @@ #! /usr/bin/env node

\t\t\t\t When a folder is used, all *.sol files in that folder and all sub folders are used.
\t\t\t\t A comma-separated list of files and folders can also be used. For example
\t\t\t\t\tsol2uml contracts,node_modules/openzeppelin-solidity
\t\t\t\t A comma-separated list of files and folders can also be used. For example,
\t\t\t\t\tsol2uml contracts,node_modules/@openzeppelin
\t\t\t\t If an Ethereum address with a 0x prefix is passed, the verified source code from Etherscan will be used. For example

@@ -222,4 +222,4 @@ \t\t\t\t\tsol2uml 0x79fEbF6B9F76853EDBcBc913e6aAE8232cFB9De9`;

.command('diff')
.usage('[options] <addressA> <addressB>')
.description(`Compare verified Solidity code differences between two contracts.
.usage('[options] <addressA> <addressB or comma-separated folders>')
.description(`Compare verified Solidity code to another verified contract or local source files.

@@ -231,4 +231,6 @@ The results show the comparison of contract A to B.

.argument('<addressA>', 'Contract address in hexadecimal format with a 0x prefix of the first contract', validators_1.validateAddress)
.argument('<addressB>', 'Contract address in hexadecimal format with a 0x prefix of the second contract', validators_1.validateAddress)
.option('-l, --lineBuffer <value>', 'Minimum number of lines before and after changes (default: 4)', validators_1.validateLineBuffer)
.argument('<addressB_folders>', `Location of the contract source code to compare against. Can be a contract address or comma-separated list of local folders.
For example, 0x1091588Cc431275F99DC5Df311fd8E1Ab81c89F3 will get the verified source code from Etherscan
or ".,node_modules" will compare against local files in the current folder and the node_modules folder.`)
.option('-s, --summary', 'Only show a summary of the file differences', false)
.option('-af --aFile <value>', 'Contract A source code filename without the .sol extension (default: compares all source files)')

@@ -239,8 +241,8 @@ .option('-bf --bFile <value>', 'Contract B source code filename without the .sol extension (default: aFile if specified)')

.option('-bk, --bApiKey <key>', 'Blockchain explorer API key for contract B if on a different blockchain to contract A. Contract A uses the `apiKey` option (default: value of `apiKey` option)')
.option('-s, --summary', 'Only show a summary of the file differences', false)
.option('--flatten', 'Flatten into a single file before comparing', false)
.option('--flatten', 'Flatten into a single file before comparing. Only works when comparing two verified contracts, not to local files', false)
.option('--saveFiles', 'Save the flattened contract code to the filesystem when using the `flatten` option. The file names will be the contract address with a .sol extension', false)
.action(async (addressA, addressB, options, command) => {
.option('-l, --lineBuffer <value>', 'Minimum number of lines before and after changes (default: 4)', validators_1.validateLineBuffer)
.action(async (addressA, addressB_folders, options, command) => {
try {
debug(`About to diff ${addressA} and ${addressB}`);
debug(`About to compare ${addressA} to ${addressB_folders}`);
const combinedOptions = {

@@ -251,20 +253,16 @@ ...command.parent._optionValues,

const aEtherscanParser = new parserEtherscan_1.EtherscanParser(combinedOptions.apiKey, combinedOptions.network, combinedOptions.explorerUrl);
const bEtherscanParser = new parserEtherscan_1.EtherscanParser(combinedOptions.bApiKey || combinedOptions.apiKey, combinedOptions.bNetwork || combinedOptions.network, combinedOptions.bExplorerUrl || combinedOptions.explorerUrl);
if (options.flatten || options.aFile) {
await (0, diffContracts_1.flattenAndDiff)(addressA, addressB, aEtherscanParser, bEtherscanParser, combinedOptions);
if ((0, regEx_1.isAddress)(addressB_folders)) {
const addressB = addressB_folders;
const bEtherscanParser = new parserEtherscan_1.EtherscanParser(combinedOptions.bApiKey || combinedOptions.apiKey, combinedOptions.bNetwork || combinedOptions.network, combinedOptions.bExplorerUrl || combinedOptions.explorerUrl);
// If flattening or just comparing a single file
if (options.flatten || options.aFile) {
await (0, diffContracts_1.compareFlattenContracts)(addressA, addressB, aEtherscanParser, bEtherscanParser, combinedOptions);
}
else {
await (0, diffContracts_1.compareVerifiedContracts)(addressA, aEtherscanParser, addressB, bEtherscanParser, combinedOptions);
}
}
else {
const { contractNameA, contractNameB, files } = await (0, diffContracts_1.compareContracts)(addressA, addressB, aEtherscanParser, bEtherscanParser, combinedOptions);
(0, diffContracts_1.displayContractNames)(addressA, addressB, contractNameA, contractNameB, combinedOptions);
(0, diffContracts_1.displayFileDiffSummary)(files);
if (!options.summary) {
// Just show the summary if all the files are the same
const diffFiles = files.filter((f) => f.result !== 'match');
if (diffFiles.length === 0)
return;
console.log();
(0, diffContracts_1.displayFileDiffs)(files, combinedOptions);
(0, diffContracts_1.displayContractNames)(addressA, addressB, contractNameA, contractNameB, combinedOptions);
(0, diffContracts_1.displayFileDiffSummary)(files);
}
const localFolders = addressB_folders.split(',');
await (0, diffContracts_1.compareVerified2Local)(addressA, aEtherscanParser, localFolders, combinedOptions);
}

@@ -271,0 +269,0 @@ }

{
"name": "sol2uml",
"version": "2.5.10",
"version": "2.5.11",
"description": "Solidity contract visualisation tool.",

@@ -5,0 +5,0 @@ "main": "./lib/index.js",

@@ -71,21 +71,21 @@ # Solidity 2 UML

Commands:
class [options] <fileFolderAddress> Generates a UML class diagram from Solidity source code.
storage [options] <fileFolderAddress> Visually display a contract's storage slots.
class [options] <fileFolderAddress> Generates a UML class diagram from Solidity source code.
storage [options] <fileFolderAddress> Visually display a contract's storage slots.
WARNING: sol2uml does not use the Solidity compiler so may differ with solc. A known example is fixed-sized arrays declared with an expression will fail to be sized.
flatten <contractAddress> Merges verified source files for a contract from a Blockchain explorer into one local file.
WARNING: sol2uml does not use the Solidity compiler so may differ with solc. A known example is fixed-sized arrays declared with an expression will fail to be sized.
flatten <contractAddress> Merges verified source files for a contract from a Blockchain explorer into one local Solidity file.
In order for the merged code to compile, the following is done:
1. pragma solidity is set using the compiler of the verified contract.
2. All pragma solidity lines in the source files are commented out.
3. File imports are commented out.
4. "SPDX-License-Identifier" is renamed to "SPDX--License-Identifier".
5. Contract dependencies are analysed so the files are merged in an order that will compile.
diff [options] <addressA> <addressB> Compare verified Solidity code differences between two contracts.
In order for the merged code to compile, the following is done:
1. pragma solidity is set using the compiler of the verified contract.
2. All pragma solidity lines in the source files are commented out.
3. File imports are commented out.
4. "SPDX-License-Identifier" is renamed to "SPDX--License-Identifier".
5. Contract dependencies are analysed so the files are merged in an order that will compile.
diff [options] <addressA> <addressB_folders> Compare verified Solidity code to another verified contract or local source files.
The results show the comparison of contract A to B.
The green sections are additions to contract B that are not in contract A.
The red sections are removals from contract A that are not in contract B.
The line numbers are from contract B. There are no line numbers for the red sections as they are not in contract B.
help [command] display help for command
The results show the comparison of contract A to B.
The green sections are additions to contract B that are not in contract A.
The red sections are removals from contract A that are not in contract B.
The line numbers are from contract B. There are no line numbers for the red sections as they are not in contract B.
help [command] display help for command
```

@@ -103,4 +103,4 @@

When a folder is used, all *.sol files in that folder and all sub folders are used.
A comma-separated list of files and folders can also be used. For example
sol2uml contracts,node_modules/openzeppelin-solidity
A comma-separated list of files and folders can also be used. For example,
sol2uml contracts,node_modules/@openzeppelin
If an Ethereum address with a 0x prefix is passed, the verified source code from Etherscan will be used. For example

@@ -185,5 +185,5 @@ sol2uml 0x79fEbF6B9F76853EDBcBc913e6aAE8232cFB9De9

```
Usage: sol2uml diff [options] <addressA> <addressB>
Usage: sol2uml diff [options] <addressA> <addressB or comma-separated folders>
Compare verified Solidity code differences between two contracts.
Compare verified Solidity code to another verified contract or local source files.

@@ -197,15 +197,17 @@ The results show the comparison of contract A to B.

addressA Contract address in hexadecimal format with a 0x prefix of the first contract
addressB Contract address in hexadecimal format with a 0x prefix of the second contract
addressB_folders Location of the contract source code to compare against. Can be a contract address or comma-separated list of local folders.
For example, 0x1091588Cc431275F99DC5Df311fd8E1Ab81c89F3 will get the verified source code from Etherscan
or ".,node_modules" will compare against local files in the current folder and the node_modules folder.
Options:
-l, --lineBuffer <value> Minimum number of lines before and after changes (default: 4)
-s, --summary Only show a summary of the file differences (default: false)
-af --aFile <value> Contract A source code filename without the .sol extension (default: compares all source files)
-bf --bFile <value> Contract B source code filename without the .sol extension (default: aFile if specified)
-bn, --bNetwork <network> Ethereum network which maps to a blockchain explorer for contract B if on a different blockchain to contract A. Contract A uses the `network` option (default: value of `network` option) (choices: "mainnet",
"goerli", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", "celo")
-bn, --bNetwork <network> Ethereum network which maps to a blockchain explorer for contract B if on a different blockchain to contract A. Contract A uses the `network` option (default: value of `network` option) (choices: "mainnet", "goerli", "sepolia", "polygon", "arbitrum", "avalanche",
"bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", "celo")
-be, --bExplorerUrl <url> Override the `bNetwork` option with custom blockchain explorer API URL for contract B if on a different blockchain to contract A. Contract A uses the `explorerUrl` (default: value of `explorerUrl` option)
-bk, --bApiKey <key> Blockchain explorer API key for contract B if on a different blockchain to contract A. Contract A uses the `apiKey` option (default: value of `apiKey` option)
-s, --summary Only show a summary of the file differences. (default: false)
--flatten Flatten into a single file before comparing (default: false)
--flatten Flatten into a single file before comparing. Only works when comparing two verified contracts, not to local files (default: false)
--saveFiles Save the flattened contract code to the filesystem when using the `flatten` option. The file names will be the contract address with a .sol extension (default: false)
-l, --lineBuffer <value> Minimum number of lines before and after changes (default: 4)
-h, --help display help for command

@@ -212,0 +214,0 @@ ```

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc