Git Product home page Git Product logo

sol2uml's Introduction

Solidity 2 UML

npm (tag) Twitter Follow

A visualisation tool for Solidity contracts featuring:

  1. Unified Modeling Language (UML) class diagram generator for Solidity contracts.
  2. Contract storage layout diagrams.
  3. Flatten Solidity files on Etherscan-like explorers to a local file.
  4. Diff contracts on Etherscan-like explorers.

UML class diagram of Open Zeppelin's ERC20 token contracts generated from version 4.7.3 Open Zeppelin ERC20

See more contract diagrams here.

Storage layout diagram of USDC's verified source code on Etherscan. USDC

See an explanation of how storage diagrams work with lots of examples here.

Install

The following installation assumes Node.js has already been installed which comes with Node Package Manager (NPM). sol2uml works with node 14 or above.

To install globally so you can run sol2uml from anywhere

npm link sol2uml --only=production

To upgrade run

npm upgrade sol2uml -g

To see which version you are using

npm ls sol2uml -g

Usage

Command Line Interface (CLI)

Usage: sol2uml [command] <options>

Generate UML class or storage diagrams from local Solidity code or verified Solidity code on Etherscan-like explorers.
Can also flatten or compare verified source files on Etherscan-like explorers.

Options:
  -sf, --subfolders <value>                       number of subfolders that will be recursively searched for Solidity files. (default: all)
  -f, --outputFormat <value>                      output file format. (choices: "svg", "png", "dot", "all", default: "svg")
  -o, --outputFileName <value>                    output file name
  -i, --ignoreFilesOrFolders <names>              comma-separated list of files or folders to ignore
  -n, --network <network>                         Ethereum network which maps to a blockchain explorer (choices: "mainnet", "holesky", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", "celo", "scroll", "base", default: "mainnet", env: ETH_NETWORK)
  -e, --explorerUrl <url>                         Override the `network` option with a custom blockchain explorer API URL. eg Polygon Mumbai testnet https://api-testnet.polygonscan.com/api (env: EXPLORER_URL)
  -k, --apiKey <key>                              Blockchain explorer API key. eg Etherscan, Arbiscan, Optimism, BscScan, CronoScan, FTMScan, PolygonScan or SnowTrace API key (env: SCAN_API_KEY)
  -bc, --backColor <color>                        Canvas background color. "none" will use a transparent canvas. (default: "white")
  -sc, --shapeColor <color>                       Basic drawing color for graphics, not text (default: "black")
  -fc, --fillColor <color>                        Color used to fill the background of a node (default: "gray95")
  -tc, --textColor <color>                        Color used for text (default: "black")
  -v, --verbose                                   run with debugging statements (default: false)
  -V, --version                                   output the version number
  -h, --help                                      display help for command

Commands:
  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 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> <fileFoldersAddress>  Compare verified Solidity code to another verified contract, a local file 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

Class usage

Usage: sol2uml class [options] <fileFolderAddress>

Generates a UML class diagram from Solidity source code.

Arguments:
  fileFolderAddress                file name, folder(s) or contract address.
                                  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
                                  If an Ethereum address with a 0x prefix is passed, the verified source code from Etherscan will be used. For example
                                        sol2uml 0x79fEbF6B9F76853EDBcBc913e6aAE8232cFB9De9

Options:
  -b, --baseContractNames <names>  only output contracts connected to these comma separated base contract names
  -d, --depth <value>              depth of connected classes to the base contracts. 1 will only show directly connected contracts, interfaces, libraries, structs and enums. (default: all)
  -c, --clusterFolders             cluster contracts into source folders (default: false)
  -hv, --hideVariables             hide variables from contracts, interfaces, structs and enums (default: false)
  -hf, --hideFunctions             hide functions from contracts, interfaces and libraries (default: false)
  -hp, --hidePrivates              hide private and internal attributes and operators (default: false)
  -hm, --hideModifiers             hide modifier functions from contracts (default: false)
  -ht, --hideEvents                hide events from contracts, interfaces and libraries (default: false)
  -hc, --hideConstants             hide file level constants (default: false)
  -hx, --hideContracts             hide contracts (default: false)
  -he, --hideEnums                 hide enum types (default: false)
  -hs, --hideStructs               hide data structures (default: false)
  -hl, --hideLibraries             hide libraries (default: false)
  -hi, --hideInterfaces            hide interfaces (default: false)
  -ha, --hideAbstracts             hide abstract contracts (default: false)
  -hn, --hideFilename              hide relative path and file name (default: false)
  -s, --squash                     squash inherited contracts to the base contract(s) (default: false)
  -hsc, --hideSourceContract       hide the source contract when using squash (default: false)
  -h, --help                       display help for command

Storage usage

Usage: sol2uml 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.

Arguments:
  fileFolderAddress               file name, folder(s) or contract address.
                                  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
                                  If an Ethereum address with a 0x prefix is passed, the verified source code from Etherscan will be used. For example
                                        sol2uml 0x79fEbF6B9F76853EDBcBc913e6aAE8232cFB9De9

Options:
  -c, --contract <name>           Contract name in the local Solidity files. Not needed when using an address as the first argument as the contract name can be derived from Etherscan.
  -cf, --contractFile <filename>  Filename the contract is located in. This can include the relative path to the desired file.
  -d, --data                      Gets the values in the storage slots from an Ethereum node. (default: false)
  -s, --storage <address>         The address of the contract with the storage values. This will be different from the contract with the code if a proxy contract is used. This is not needed if `fileFolderAddress` is an address and the contract is not proxied.
  -u, --url <url>                 URL of the Ethereum node to get storage values if the `data` option is used. (default: "http://localhost:8545", env: NODE_URL)
  -bn, --block <number>           Block number to get the contract storage values from. (default: "latest")
  -sn, --slotNames <names>        Comma-separated list of slot names when accessed by assembly. The names can be a string, which will be hashed to a slot, or a 32 bytes hexadecimal string with a 0x prefix.
  -st, --slotTypes <types>        Comma-separated list of types for the slots listed in the `slotNames` option. eg address,uint256,bool. If all types are the same, a single type can be used. eg address (default: ["bytes32"])
  -a, --array <number>            Number of slots to display at the start and end of arrays. (default: "2")
  -hx, --hideExpand <variables>   Comma-separated list of storage variables to not expand. That's arrays, structs, strings or bytes.
  -hv, --hideValues               Hide storage slot value column. (default: false)
  -h, --help                      display help for command

Flatten usage

Usage: sol2uml 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.

Arguments:
  contractAddress  Contract address in hexadecimal format with a 0x prefix.

Options:
  -h, --help       display help for command

Diff usage

Usage: sol2uml diff [options] <addressA> <addressB or comma-separated folders>

Compare verified contract code on Etherscan-like explorers to another verified contract, a local file or multiple local 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.

Arguments:
  addressA                   Contract address in hexadecimal format with a 0x prefix of the first contract
  fileFoldersAddress         Location of the contract source code to compare against. Can be a filename, comma-separated list of local folders or a contract address. Examples:
    "flat.sol" will compare against a local file called "flat.sol". This must be used when address A's verified source code is a single, flat file.
    ".,node_modules" will compare against local files under the current working folder and the node_modules folder. This is used when address A's verified source code is multiple files.
    0x1091588Cc431275F99DC5Df311fd8E1Ab81c89F3 will compare against the verified source code from Etherscan.

Options:
  -s, --summary              Only show a summary of the file differences (default: false)
  -af --aFile <value>        Limit code compare to contract A source file with the full path and extension as displayed in the file summary (default: compares all source files)
  -bf --bFile <value>        Contract B source file with the full path and extension as displayed in the file summary. Used if aFile is specified and the source file has been renamed (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", "holesky", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", "celo", "base")
  -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)
  --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

UML Class diagram examples

To generate a diagram of all contracts under the contracts folder and its sub folders

sol2uml class ./contracts

To generate a diagram of EtherDelta's contract from the verified source code on Etherscan. The output will be a svg file 0x8d12A197cB00D4747a1fe03395095ce2A5CC6819.svg in the working folder.

sol2uml class 0x8d12A197cB00D4747a1fe03395095ce2A5CC6819

To generate a diagram of EtherDelta's contract from the verified source code on Etherscan Ropsten. The output will be a svg file 0xa19833bd291b66aB0E17b9C6d46D2Ec5fEC15190.svg in the working folder.

sol2uml class 0xa19833bd291b66aB0E17b9C6d46D2Ec5fEC15190 -n ropsten

To generate all Solidity files under some root folder and output the svg file to a specific location

sol2uml class path/to/contracts/root/folder -o ./outputFile.svg

To generate a diagram of all contracts in a single Solidity file, the output file in png format to output file ./someFile.png

sol2uml class path/to/contracts/root/folder/solidity/file.sol -f png -o ./someFile.png

To generate a diagram of all Solidity files under the contracts and node_modules/@openzeppelin folders. The output will be contracts.svg and contracts.png files in the working folder.

sol2uml class ./contracts,node_modules/@openzeppelin -f all -v

To generate a diagram of all Solidity files under the working folder ignoring and files under the solparse, @solidity-parser and ethlint folders, which will be under the node_modules folder.

sol2uml class -i solparse,@solidity-parser,ethlint

UML Class Diagram Syntax

Good online resources for learning UML

Terminology differences

A Solidity variable becomes an attribute in UML and a Solidity function becomes an operation in UML.

Stereotypes

Class stereotypes

  • Interface
  • Abstract - if any of the contract's functions are abstract, the class will have an Abstract stereotype. Child contracts of abstract contracts that do not implement all the abstract functions are currently not marked as Abstract.
  • Library

Operator stereotypes

  • event
  • modifier
  • abstract - if there is no function body on a contract, the operator is marked as abstract. Operators on an Interface do not have an abstract stereotype as all operators are abstract.
  • fallback - abstract fallback functions will just have an abstract stereotype.
  • payable - payable fallback functions will just have a fallback stereotype.

UML Associations

Lines:

  • Solid lines for
    • link the contract types of storage (state) variables. This can be linked to contracts, interfaces, libraries or file level structs and enums.
    • generalisations of contracts and abstract contracts.
    • aggregated contract level structs and enums.
  • Dashed lines for
    • generalisations of interfaces.
    • types of memory variables.

Heads/Tails:

  • An empty triangle head for generalisations of contracts, interfaces and abstract contracts.
  • An open arrow head for storage or memory variable dependencies
  • A diamond tail for aggregations of contract level structs and enums

Storage diagram

FileLevel-storage

See more storage slot diagrams here.

Styling Colors

The colors use by the diagrams can be configured using the backColor, shapeColor, fillColor and textColor options. sol2uml uses the X11 color scheme for named colors. Other color formats like Red-Green-Blue (RGB) can also be used. For example, #ffffff for white and #000000 for black. See Graphviz color documentation for more details.

Here's an example using the color options

sol2uml storage -sc deeppink -tc #ffffff -fc dimgrey -bc black 0xfCc00A1e250644d89AF0df661bC6f04891E21585

Aave V3 Pool

Version 2.x changes

The biggest change with 2.x is the introduction of subcommands as sol2uml can now draw contract storage diagrams.

See version 2.x for a list of changes from 1.x.

Contribution

To build the test contracts in this repository, run the following. This assumes you have the Solidity compiler solc installed on your machine.

npm run buildSol

To build the TypeScript files

npm run build

To run the Jest tests

npm run test

To access your local changes on your machine globally.

npm link

Publish

Commands to publish a new package version.

npm run prettier
npm run clean
npm run package-lock
npm run build
npm run permit
# make tx2uml globally available for local testing
npm link
# check all the files are included in the npm package
npm pack --dry-run
npm publish

Then create a new release on GitHub https://github.com/naddison36/sol2uml/releases

About

This is a rewrite of the Richard Ramos's solidity-diagram-gen tool which no longer works as it uses solidity-parser which cannot handle newer Solidity syntax like constructor.

sol2uml uses @solidity-parser/parser which is maintained by the Solidity tool community lead by Franco Victorio (@fvictorio). This is a fork of Federico Bond's (GitHub @federicobond) solidity-parser-antlr. The logic to generate the dot syntax has been rewritten and different UML syntax is now used to Richard Ramos's original implementation.

The Solidity language grammar is published with each major release.

The diagrams are generated using viz.js which uses Graphviz to render a Scalable Vector Graphics (SVG) file. Graphviz Online allows dot files to be edited and rendered into a SVG dynamically.

The diff command use's Google's Diff Match and Patch library.

sol2uml's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sol2uml's Issues

Don't parse folders with .sol extension

Foundry's forge creates folders in the out folder with the same name as the Solidity source file. eg Monoaco.sol and Car.sol under the out folder are folders and not files.

sol2uml needs to not parse folders with a .sol extension.

Add empty bytes to the storage slots

For storage diagrams, when a full 32-byte slot is not used, show the bytes in the slot that are not used. For example, an address is 20 bytes so will have 12 bytes unused in the slot if the next storage variable is greater than 12 bytes.

Does it work on the remix platform?

I am using the remix platform for my smart contracts in solidity and when I activate the sol2uml plugin it does not activate, is there an error? can you help me? thank you very much.

Storage for contracts with the same name

Running sol2uml storage -c *same name* on folder with files, containing contracts with the same name, will return storage diagram for contract with the smallest filename in sort order.

Example:

main.sol:

pragma solidity ^0.8.7;

import {A as A1} from "./Lib1.sol";
import {A as A2} from "./Lib2.sol";

contract A is A1, Math2 {
    uint32 C1 = 0;
}

Lib1.sol:

pragma solidity ^0.8.7;

contract A {
    uint32 C2 = 0;
}

Lib2.sol:

pragma solidity ^0.8.7;

contract A {
    uint32 C3 = 0;
}

In this example storage will be generated for A from Lib1.sol. But if you rename main.sol in amain.sol result will be for A from amain.sol.

Maybe it can be fixed by choosing both filename and contract name?

Dependency arrows are missing

I have two classes, one interface and one abstract class. Each of them depends the other, but in the generated diagram there is no dependency link. I guess it doesn't draw dependencies.

sol2uml storage: `Failed to generate storage diagram`, while uml diagram generates without error

sol2uml storage shows this error: Failed to generate storage diagram,
while the uml diagram generates without error, as well as sol2uml flatten.
Note: the @openzeppelin contracts are not installed locally.

>sol2uml 0x2762e676a9f17c7de34fe4b124424837c7e18e1c
Generated svg file KoiosECDSA.svg

>sol2uml flatten 0x2762e676a9f17c7de34fe4b124424837c7e18e1c
Solidity written to KoiosECDSA.sol

>sol2uml storage 0x2762e676a9f17c7de34fe4b124424837c7e18e1c
Failed to generate storage diagram.
Error: Failed to find inherited contract "ERC721" of "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"
at C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\converterClasses2Storage.js:70:19
at Array.forEach ()
at parseVariables (C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\converterClasses2Storage.js:67:27)
at C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\converterClasses2Storage.js:73:9
at Array.forEach ()
at parseVariables (C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\converterClasses2Storage.js:67:27)
at convertClasses2Storages (C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\converterClasses2Storage.js:41:23)
at Command. (C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\lib\sol2uml.js:118:81)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Command.parseAsync (C:\Users...\AppData\Roaming\npm\node_modules\sol2uml\node_modules\commander\lib\command.js:917:5)

Output Solidity from Etherscan verified source code

Add a new sol outputFormat option that will write the verified Solidity code on Etherscan to a file

For example
sol2uml 0xC6845a5C768BF8D7681249f8927877Efda425baf -f sol

Which will write all the Aave files loaded on Etherscan into one file called 0xC6845a5C768BF8D7681249f8927877Efda425baf.sol

Error: Cannot find module '@solidity-parser/parser'

cosmos@ubuntu:~$ sol2uml -h
internal/modules/cjs/loader.js:583
throw err;
^

Error: Cannot find module '@solidity-parser/parser'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object. (/usr/local/lib/node_modules/sol2uml/lib/etherscanParser.js:7:18)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)

"Failed to find parent contract" error

Hey there!

I was trying to run the sol2uml storage command on the 0x72fb5253ad16307b9e773d2a78cac58e309d5ba4 address. But I'm getting an error:

sol2uml storage 0x72fb5253ad16307b9e773d2a78cac58e309d5ba4
Failed to generate storage diagram Error: Failed to find parent contract IForwarder of contracts/Voting.sol

Spent some time trying to debug but i've hit a dead end. Seems like the contracts are not being parsed correctly? Perhaps this has to do with the fact that it's an old Solidity version ?

Just for context, though I don't think it's related to the specific error, the address contains an implementation contract that's sitting behind the proxy at 0x2e59a20f205bb85a89c53f1936454680651e618e.

viz.js error

When executing with no arguments:
(node:24148) V8: /usr/local/lib/node_modules/sol2uml/node_modules/viz.js/viz.js:33 Invalid asm.js: Function definition doesn't match use

Flatten: Inherited contracts need to be defined before Derived contracts

Using flatten on the Replica.sol contract of Nomad bridge.
sol2uml flatten 0xB92336759618F55bd0F8313bd843604592E27bd8

Attempted to compile with foundry suite:
forge build

Error:

error[2449]: src/Replica.sol:19:21: TypeError: Definition of base has to precede definition of derived contract
contract Replica is Version0, NomadBase {
                    ^------^

contract Replica declaration is L19
contract Version0 declaration is L341

Can there be logic inside sol2uml flatten to rearrange contracts from {most inherited -> most derived} inside the flattened file?

Error: Cannot find module './utils/regEx'

Seems that the utils subfolder is missing from the npm package? ๐Ÿค”

$ yarn init -y
$ yarn add sol2uml
$ yarn sol2uml --help
yarn run v1.22.18
$ /home/user/node_modules/.bin/sol2uml --help
node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module './utils/regEx'
Require stack:
- /home/user/node_modules/sol2uml/lib/converterClass2Dot.js
- /home/user/node_modules/sol2uml/lib/converterClasses2Dot.js
- /home/user/node_modules/sol2uml/lib/sol2uml.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/home/user/node_modules/sol2uml/lib/converterClass2Dot.js:6:17)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/user/node_modules/sol2uml/lib/converterClass2Dot.js',
    '/home/user/node_modules/sol2uml/lib/converterClasses2Dot.js',
    '/home/user/node_modules/sol2uml/lib/sol2uml.js'
  ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
$ ls -la node_modules/sol2uml/lib/
total 155
drwxr-xr-x 1 user 1049089     0 Jul 25 13:17 ./
drwxr-xr-x 1 user 1049089     0 Jul 25 13:17 ../
-rw-r--r-- 1 user 1049089   184 Jul 25 12:48 associations.d.ts
-rw-r--r-- 1 user 1049089  1608 Jul 25 12:48 associations.js
-rw-r--r-- 1 user 1049089   227 Jul 25 12:48 converterAST2Classes.d.ts
-rw-r--r-- 1 user 1049089 22567 Jul 25 12:48 converterAST2Classes.js
-rw-r--r-- 1 user 1049089   422 Jul 25 12:48 converterClass2Dot.d.ts
-rw-r--r-- 1 user 1049089  8618 Jul 25 12:48 converterClass2Dot.js
-rw-r--r-- 1 user 1049089   333 Jul 25 12:48 converterClasses2Dot.d.ts
-rw-r--r-- 1 user 1049089  5246 Jul 25 12:48 converterClasses2Dot.js
-rw-r--r-- 1 user 1049089   990 Jul 25 12:48 converterClasses2Storage.d.ts
-rw-r--r-- 1 user 1049089 14976 Jul 25 12:48 converterClasses2Storage.js
-rw-r--r-- 1 user 1049089   253 Jul 25 12:48 converterStorage2Dot.d.ts
-rw-r--r-- 1 user 1049089  3860 Jul 25 12:48 converterStorage2Dot.js
-rw-r--r-- 1 user 1049089   423 Jul 25 12:48 filterClasses.d.ts
-rw-r--r-- 1 user 1049089  2364 Jul 25 12:48 filterClasses.js
-rw-r--r-- 1 user 1049089   350 Jul 25 12:48 index.d.ts
-rw-r--r-- 1 user 1049089  1320 Jul 25 12:48 index.js
-rw-r--r-- 1 user 1049089  1780 Jul 25 12:48 parserEtherscan.d.ts
-rw-r--r-- 1 user 1049089  7122 Jul 25 12:48 parserEtherscan.js
-rw-r--r-- 1 user 1049089   647 Jul 25 12:48 parserFiles.d.ts
-rw-r--r-- 1 user 1049089  4541 Jul 25 12:48 parserFiles.js
-rw-r--r-- 1 user 1049089   192 Jul 25 12:48 parserGeneral.d.ts
-rw-r--r-- 1 user 1049089  1538 Jul 25 12:48 parserGeneral.js
-rwxr-xr-x 1 user 1049089    32 Jul 25 12:48 sol2uml.d.ts*
-rwxr-xr-x 1 user 1049089  7724 Jul 25 12:48 sol2uml.js*
-rw-r--r-- 1 user 1049089   866 Jul 25 12:48 typeGuards.d.ts
-rw-r--r-- 1 user 1049089  1338 Jul 25 12:48 typeGuards.js
-rw-r--r-- 1 user 1049089  2373 Jul 25 12:48 umlClass.d.ts
-rw-r--r-- 1 user 1049089  4336 Jul 25 12:48 umlClass.js
-rw-r--r-- 1 user 1049089   614 Jul 25 12:48 writerFiles.d.ts
-rw-r--r-- 1 user 1049089  5527 Jul 25 12:48 writerFiles.js

Get folder remappings from Solidity config file

This is for filesystem source code and from Etherscan

An example contract on Etherscan with remappings is the Replica contract from Nomad https://etherscan.io/address/0xB92336759618F55bd0F8313bd843604592E27bd8

{
  "remappings": [
    "@ensdomains/=node_modules/@ensdomains/",
    "@nomad-xyz/=packages/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@summa-tx/=node_modules/@summa-tx/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "prettier-plugin-solidity/=node_modules/prettier-plugin-solidity/",
    "solscripts/=packages/upgrade/solscripts/",
    "test/=packages/upgrade/solscripts/test/",
    "solscripts/=packages/upgrade/solscripts/",
    "test/=packages/upgrade/solscripts/test/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "metadata": {
    "bytecodeHash": "none"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "istanbul",
  "libraries": {}
}

Add more colours

Would help if function signatures weren't just single font color. I mean, function name could be one color, argument names different color, argument types different color. It would help the reading quite a lot.

New feature to generate documentation using the NatSpec in contract source code

sol2uml already has the logic to pull the verified source code for a contract from Etherscan or get the source code from the local filesystem. This can be used to then generate contract documentation using a Solidity document generator like solidity-docgen.

A new option would be used to do this.
-g, --genDocs

Will also need an option to specify the folder the HTML files should be written to.

Handle circular import dependencies

sol2uml currently fails to generate diagrams for the Monaco contract that is used in the 0xMonaco on-chain pvp racing game.

The problem is the Monaco.sol file imports the Car.sol file with import "./cars/Car.sol"; and the Cars.sol file has a circular import back to the Monaco.sol file with import "../Monaco.sol";.

sol2uml -b Monaco .    
RangeError: Maximum call stack size exceeded
    at /workspaces/sol2uml/lib/associations.js:7:36
    at Array.find (<anonymous>)
    at findAssociatedClass (/workspaces/sol2uml/lib/associations.js:7:31)
    at findImplicitImport (/workspaces/sol2uml/lib/associations.js:69:58)
    at findAssociatedClass (/workspaces/sol2uml/lib/associations.js:31:12)
    at findImplicitImport (/workspaces/sol2uml/lib/associations.js:69:58)
    at findAssociatedClass (/workspaces/sol2uml/lib/associations.js:31:12)
    at findImplicitImport (/workspaces/sol2uml/lib/associations.js:69:58)
    at findAssociatedClass (/workspaces/sol2uml/lib/associations.js:31:12)
    at findImplicitImport (/workspaces/sol2uml/lib/associations.js:69:58)

Error: Failed to find contract with name "undefined"

On both Linux (ubuntu 20.04.4 wsl on windows) and Windows 11, I still get this error message with version 2.1.7 of sol2uml:

> npm ls | grep sol2uml
โ”œโ”€โ”€ sol2uml@2.1.7 extraneous -> ./.nvm/versions/node/v16.15.1/lib/node_modules/sol2uml

> sol2uml flatten 0x2762e676a9f17c7de34fe4b124424837c7e18e1c
Solidity written to KoiosECDSA.sol

> sol2uml storage KoiosECDSA.sol -v
  sol2uml verbose on +0ms
  sol2uml About to get Solidity files under KoiosECDSA.sol +0ms
  sol2uml Got Solidity file to be parsed: KoiosECDSA.sol +1ms
  sol2uml Added contract Context +0ms
  sol2uml Added contract IERC165 +0ms
  sol2uml Added contract ERC165 +0ms
  sol2uml Added contract IERC721 +1ms
  sol2uml Added contract IERC721Metadata +0ms
  sol2uml Added contract Address +0ms
  sol2uml Added contract Strings +0ms
  sol2uml Added contract ERC721 +1ms
  sol2uml Added contract IERC721Enumerable +0ms
  sol2uml Added contract ERC721Enumerable +0ms
  sol2uml Added contract Ownable +0ms
  sol2uml Added contract ECDSA +0ms
  sol2uml Added contract SignedTokenVerifier +1ms
  sol2uml Added contract KoiosECDSA +0ms
  sol2uml Added contract IERC721Receiver +0ms
Error: Failed to find contract with name "undefined"
    at convertClasses2Storages (/home/gerard/.nvm/versions/node/v16.15.1/lib/node_modules/sol2uml/lib/converterClasses2Storage.js:52:15)
    at Command.<anonymous> (/home/gerard/.nvm/versions/node/v16.15.1/lib/node_modules/sol2uml/lib/sol2uml.js:115:81)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Command.parseAsync (/home/gerard/.nvm/versions/node/v16.15.1/lib/node_modules/sol2uml/node_modules/commander/lib/command.js:917:5)
    at async main (/home/gerard/.nvm/versions/node/v16.15.1/lib/node_modules/sol2uml/lib/sol2uml.js:180:5)

file level constants

sol2uml doesn't currently look for constants declared in a file. ie outside a contract.

This is useful for class diagrams but is essential for storage diagrams if the constant is used to declare the size of a storage array.

There is a good example in issue #85 (comment)

Incorrect storage slots for arrays declared with a constant or expression

The TestStorage contract has two examples

    uint256 public constant N_COINS = 3;

    address[N_COINS] coins;
    IERC20[2 * N_COINS] doubleTokens;
    IERC20[N_COINS ** 2] powerTokens;

The coins variable is currently showing as only taking one slot but it actually takes three.
The doubleTokens variable is currently showing as only taking one slot but it actually takes six.

Request has been deprecated

Sol2uml throws an error since request has been deprecated (request/request#3142).

i.e.

sol2uml ./contracts
internal/modules/cjs/loader.js:638
throw err;
^

Error: Cannot find module 'request'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (C:\U...\npm\node_modules\sol2uml\lib\etherscanParser.js:6:35)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)

Error returned when smart contract includes assembly code

When ran against a smart contract that has some assembly code, the following error is returned. But commenting out the assembly code allows the tool to generate an SVG file as expected.

(node:22591) UnhandledPromiseRejectionWarning: VError: Failed to parse solidity file /contracts/ERC20_Asset_Pool.sol.: index parameter must be between >= 0 and <= number of children.
    at parseSolidityFile (/usr/local/lib/node_modules/sol2uml/lib/fileParser.js:93:15)
    at Object.parseUmlClassesFromFiles (/usr/local/lib/node_modules/sol2uml/lib/fileParser.js:18:28)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async sol2uml (/usr/local/lib/node_modules/sol2uml/lib/sol2uml.js:78:22)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:22591) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22591) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

sol2uml run on Windows produces different output to Mac

An example is
sol2uml 0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208

On Mac the method parameters will be included. eg Exchange.assert(assertion: bool)
On Window the method parameters are not included. eg Exchange.assert()

Feature request: version flag

Could a -V or similar flag be added to the CLI tool (and corresponding help text) to quickly check the version of sol2uml installed? I can manually check my package.json file but a flag would be faster.

Edit: I see npm ls sol2uml -g is suggested in the README, which is faster than finding the package.json. Still, a -V flag would be nice.

Contract dependencies in code

Some dependencies to contracts in code blocks are not being picked up. For example, Open Zeppelin's ERC777 contract is missing a dependency to the IERC777Recipient interface from the _callTokensReceived function.

UML generation incorrect when Contracts with same names in different folders with relative imports are used

Problem

If the set of folders that are being used to generate the UML contain contracts with the same name but are subsequently imported differently as dictated by their relative imports, the generated UML shows that all contracts that inherit a contract with such a name all inherit from the same contract.

Reproduction

Set up

Create a folder set up as below:

uml
 โ”œโ”€โ”€ 1
 โ”‚   โ”œโ”€โ”€ Parent.sol
 โ”‚   โ””โ”€โ”€ sub
 โ”‚        โ””โ”€โ”€ Child.sol
 โ””โ”€โ”€ 2
     โ”œโ”€โ”€ Parent.sol
     โ””โ”€โ”€ sub
          โ””โ”€โ”€ Child.sol

The contracts themselves can contain anything --- they can be the same code or completely different, the result is unchanged.

For this example we just used blank contracts:

Parent.sol:

pragma solidity ^0.6.2;

contract Parent {
}

Child.sol

pragma solidity ^0.6.2;

import "../Parent.sol";

contract Child is Parent {

}

Note the relative import in Child.sol. This means that each Child inherits specifically from the Parent in the parent folder and nowhere else. solc compiles the contracts in this way.

Command

Now run sol2uml uml/ -f png to get:

issue

As shown, even when both Children do not inherit from the same Parent, the generated UML reports that they do.

Additional Notes

If the offending contracts have different/same file names, the problem does not change.

If the offending contracts have different contract names, the problem goes away regardless of file name:

changed

What we expect is the above image to be generated with the contract names staying the same.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.