UNPKG

solidity-audit

Version:
519 lines (448 loc) โ€ข 18.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div class="header" style="display: flex; position: relative;"> <div style="z-index: 0;"> <img class="bgr-header" src="/Volumes/Extreme SSD/nextjs/solidity-metrics/public/images/bgr-header.png" alt="Background Header" style=" position: absolute; width: 100%; height: 100vh; background-repeat: no-repeat; object-fit: cover; " /> <div style="position: absolute; top: 72px; bottom: 0; left: 64px; height: 80vh;"> <div style="margin-bottom: auto; justify-content: space-between;"> <img class="ic-logo" src="/Volumes/Extreme SSD/nextjs/solidity-metrics/public/images/Logo.svg" /> <p id="p-security" style="color: #6B7280; padding: 0; margin: 0; margin-top: 64px;">Security Assessment</p> <h2 id="h2-defi" style="color: white; z-index: 100; padding: 4px 0 8px 0; margin: 0;">DeFi Exchange - Audit</h2> <p id="p-verified" style="color: #6B7280; z-index: 100; padding: 0; margin: 0;" color: white;>TechRight Verified on Mar 18th, 2023</p> </div> <img src="/Volumes/Extreme SSD/nextjs/solidity-metrics/public/images/ic-qr.png" style="height: 98px; width: 98px; margin-bottom: 64px; margin-top: calc(80vh - 248px);" /> </div> </div> </div> <!-- <a onclick="/*toggleVisibility('doppelganger-contracts', this)*/">[โž•]</a> --> <div id="doppelganger-contracts" style="display: none"> <img src="./public/images/bgr-header.png" alt="Background Header" style="width: 100%; height: 100vh" /> <img width="200" alt="get in touch with Consensys Diligence" src="https://user-images.githubusercontent.com/2865694/56826101-91dcf380-685b-11e9-937c-af49c2510aa0.png" />(https://diligence.consensys.net)<br /> <div> <a href="https://diligence.consensys.net"> <img src="๐ŸŒ" alt="https://diligence.consensys.net" /></a> <a href="mailto:diligence@consensys.net" ><img src="๐Ÿ“ฉ" alt="mailto:diligence@consensys.net" /></a> <a href="https://consensys.github.io/diligence/" ><img src="๐Ÿ”ฅ" alt="https://consensys.github.io/diligence/" /></a> </div> <!-- [[ ๐ŸŒ ](https://diligence.consensys.net) [ ๐Ÿ“ฉ ](mailto:diligence@consensys.net) [ ๐Ÿ”ฅ ](https://consensys.github.io/diligence/)] --> </div> <!-- # Solidity Metrics for ${this.name} ## Table of contents - [Scope](#t-scope) - [Source Units in Scope](#t-source-Units-in-Scope) - [Out of Scope](#t-out-of-scope) - [Excluded Source Units](#t-out-of-scope-excluded-source-units) - [Duplicate Source Units](#t-out-of-scope-duplicate-source-units)${doppelgangerToC} - [Report Overview](#t-report) - [Risk Summary](#t-risk) - [Source Lines](#t-source-lines) - [Inline Documentation](#t-inline-documentation) - [Components](#t-components) - [Exposed Functions](#t-exposed-functions) - [StateVariables](#t-statevariables) - [Capabilities](#t-capabilities) - [Dependencies](#t-package-imports) - [Totals](#t-totals) ## <span id=t-scope>Scope</span> This section lists files that are in scope for the metrics report. - **Project:** \`${this.name}\` - **Included Files:** ${ `\n` + this.inputFileGlob .replace("{", "") .replace("}", "") .split(",") .map((g) => ` - \`${g}\``) .join("\n") } - **Excluded Paths:** ${ `\n` + this.inputFileGlobExclusions .replace("{", "") .replace("}", "") .split(",") .map((g) => ` - \`${g}\``) .join("\n") } - **File Limit:** \`${this.inputFileGlobLimit}\` - **Exclude File list Limit:** \`${this.excludeFileGlobLimit}\` - **Workspace Repository:** \`${this.repoInfo.remote || "unknown"}\` (\`${ this.repoInfo.branch }\`@\`${this.repoInfo.commit}\`) ### <span id=t-source-Units-in-Scope>Source Units in Scope</span> Source Units Analyzed: **\`${this.seenFiles.length}\`**<br> Source Units in Scope: **\`${this.metrics.length}\`** (**${Math.round( (this.metrics.length / this.seenFiles.length) * 100 )}%**) | Type | File | Logic Contracts | Interfaces | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities | | ---- | ------ | --------------- | ---------- | ----- | ------ | ----- | ------------- | -------------- | ------------ | ${this.metrics .map( (m) => `| ${m.metrics.num.contracts ? "๐Ÿ“" : ""}${ m.metrics.num.libraries ? "๐Ÿ“š" : "" }${m.metrics.num.interfaces ? "๐Ÿ”" : ""}${ m.metrics.num.abstract ? "๐ŸŽจ" : "" } | ${m.filename.replace(this.basePath, "")} | ${ m.metrics.num.contracts + m.metrics.num.libraries + m.metrics.num.abstract || "****" } | ${m.metrics.num.interfaces || "****"} | ${ m.metrics.sloc.total || "****" } | ${m.metrics.nsloc.total || "****"} | ${ m.metrics.nsloc.source || "****" } | ${m.metrics.sloc.comment || "****"} | ${ m.metrics.complexity.perceivedNaiveScore || "****" } | **${ m.metrics.capabilities.assembly ? "<abbr title='Uses Assembly'>๐Ÿ–ฅ</abbr>" : "" }${ m.metrics.capabilities.experimental.length ? "<abbr title='Experimental Features'>๐Ÿงช</abbr>" : "" }${ m.metrics.capabilities.canReceiveFunds ? "<abbr title='Payable Functions'>๐Ÿ’ฐ</abbr>" : "" }${ m.metrics.capabilities.destroyable ? "<abbr title='Destroyable Contract'>๐Ÿ’ฃ</abbr>" : "" }${ m.metrics.capabilities.explicitValueTransfer ? "<abbr title='Initiates ETH Value Transfer'>๐Ÿ“ค</abbr>" : "" }${ m.metrics.capabilities.lowLevelCall ? "<abbr title='Performs Low-Level Calls'>โšก</abbr>" : "" }${ m.metrics.capabilities.delegateCall ? "<abbr title='DelegateCall'>๐Ÿ‘ฅ</abbr>" : "" }${ m.metrics.capabilities.hashFuncs ? "<abbr title='Uses Hash-Functions'>๐Ÿงฎ</abbr>" : "" }${ m.metrics.capabilities.ecrecover ? "<abbr title='Handles Signatures: ecrecover'>๐Ÿ”–</abbr>" : "" }${ m.metrics.capabilities.deploysContract ? "<abbr title='create/create2'>๐ŸŒ€</abbr>" : "" }${ doppelGanger !== undefined && pathToDoppelganger && pathToDoppelganger[m.filename.replace(this.basePath, "")] ? "<abbr title='doppelganger(" + pathToDoppelganger[m.filename.replace(this.basePath, "")] .map((r) => r.target.name) .join(", ") + ")'>๐Ÿ”†</abbr>" : "" }${ m.metrics.capabilities.tryCatchBlocks ? "<abbr title='TryCatch Blocks'>โ™ป๏ธ</abbr>" : "" }${ m.metrics.capabilities.uncheckedBlocks ? "<abbr title='Unchecked Blocks'>ฮฃ</abbr>" : "" }** |` ) .join("\n")} | ${totals.totals.num.contracts ? "๐Ÿ“" : ""}${ totals.totals.num.libraries ? "๐Ÿ“š" : "" }${totals.totals.num.interfaces ? "๐Ÿ”" : ""}${ totals.totals.num.abstract ? "๐ŸŽจ" : "" } | **Totals** | **${ totals.totals.num.contracts + totals.totals.num.libraries + totals.totals.num.abstract || "" }** | **${totals.totals.num.interfaces || ""}** | **${ totals.totals.sloc.total }** | **${totals.totals.nsloc.total}** | **${ totals.totals.nsloc.source }** | **${totals.totals.sloc.comment}** | **${ totals.totals.complexity.perceivedNaiveScore }** | **${ totals.totals.capabilities.assembly ? "<abbr title='Uses Assembly'>๐Ÿ–ฅ</abbr>" : "" }${ totals.totals.capabilities.experimental.length ? "<abbr title='Experimental Features'>๐Ÿงช</abbr>" : "" }${ totals.totals.capabilities.canReceiveFunds ? "<abbr title='Payable Functions'>๐Ÿ’ฐ</abbr>" : "" }${ totals.totals.capabilities.destroyable ? "<abbr title='Destroyable Contract'>๐Ÿ’ฃ</abbr>" : "" }${ totals.totals.capabilities.explicitValueTransfer ? "<abbr title='Initiates ETH Value Transfer'>๐Ÿ“ค</abbr>" : "" }${ totals.totals.capabilities.lowLevelCall ? "<abbr title='Performs Low-Level Calls'>โšก</abbr>" : "" }${ totals.totals.capabilities.delegateCall ? "<abbr title='DelegateCall'>๐Ÿ‘ฅ</abbr>" : "" }${ totals.totals.capabilities.hashFuncs ? "<abbr title='Uses Hash-Functions'>๐Ÿงฎ</abbr>" : "" }${ totals.totals.capabilities.ecrecover ? "<abbr title='Handles Signatures: ecrecover'>๐Ÿ”–</abbr>" : "" }${ totals.totals.capabilities.deploysContract ? "<abbr title='create/create2'>๐ŸŒ€</abbr>" : "" }${ doppelGanger !== undefined && pathToDoppelganger && Object.keys(pathToDoppelganger).length ? "<abbr title='doppelganger'>๐Ÿ”†</abbr>" : "" }${ totals.totals.capabilities.tryCatchBlocks ? "<abbr title='TryCatch Blocks'>โ™ป๏ธ</abbr>" : "" }${ totals.totals.capabilities.uncheckedBlocks ? "<abbr title='Unchecked Blocks'>ฮฃ</abbr>" : "" }** | <sub> Legend: <a onclick="toggleVisibility('table-legend', this)">[โž•]</a> <div id="table-legend" style="display:none"> <ul> <li> <b>Lines</b>: total lines of the source unit </li> <li> <b>nLines</b>: normalized lines of the source unit (e.g. normalizes functions spanning multiple lines) </li> <li> <b>nSLOC</b>: normalized source lines of code (only source-code lines; no comments, no blank lines) </li> <li> <b>Comment Lines</b>: lines containing single or block comments </li> <li> <b>Complexity Score</b>: a custom complexity score derived from code statements that are known to introduce code complexity (branches, loops, calls, external interfaces, ...) </li> </ul> </div> </sub> #### <span id=t-out-of-scope>Out of Scope</span> ##### <span id=t-out-of-scope-excluded-source-units>Excluded Source Units</span> Source Units Excluded: **\`${this.excludedFiles.length}\`** <a onclick="toggleVisibility('excluded-files', this)">[โž•]</a> <div id="excluded-files" style="display:none"> | File | | ------ | ${ this.excludedFiles.length ? this.excludedFiles .map((f) => `|${f.replace(this.basePath, "")}|`) .join("\n") : "| None |" } </div> ##### <span id=t-out-of-scope-duplicate-source-units>Duplicate Source Units</span> Duplicate Source Units Excluded: **\`${this.seenDuplicates.length}\`** <a onclick="toggleVisibility('duplicate-files', this)">[โž•]</a> <div id="duplicate-files" style="display:none"> | File | | ------ | ${ this.seenDuplicates.length ? this.seenDuplicates .map((f) => `|${f.replace(this.basePath, "")}|`) .join("\n") : "| None |" } </div> ${doppelgangerSection} </div> ## <span id=t-report>Report</span> ### Overview The analysis finished with **\`${this.errors.length}\`** errors and **\`${ this.seenDuplicates.length }\`** duplicate files. ${this.errors.length ? "**Errors:**\n\n" + this.errors.join("\n* ") : ""} ${ this.truffleProjectLocations.length ? "**Truffle Project Locations Observed:**\n* " + this.truffleProjectLocations .map((f) => "./" + f.replace(this.basePath, "")) .join("\n* ") : "" } #### <span id=t-risk>Risk</span> <div class="wrapper" style="max-width: 512px; margin: auto"> <canvas id="chart-risk-summary"></canvas> </div> #### <span id=t-source-lines>Source Lines (sloc vs. nsloc)</span> <div class="wrapper" style="max-width: 512px; margin: auto"> <canvas id="chart-nsloc-total"></canvas> </div> #### <span id=t-inline-documentation>Inline Documentation</span> - **Comment-to-Source Ratio:** On average there are\`${ Math.round( (totals.totals.sloc.source / totals.totals.sloc.comment) * 100 ) / 100 }\` code lines per comment (lower=better). - **ToDo's:** \`${totals.totals.sloc.todo}\` #### <span id=t-components>Components</span> | ๐Ÿ“Contracts | ๐Ÿ“šLibraries | ๐Ÿ”Interfaces | ๐ŸŽจAbstract | | ------------- | ----------- | ------------ | ---------- | | ${totals.totals.num.contracts} | ${totals.totals.num.libraries} | ${ totals.totals.num.interfaces } | ${totals.totals.num.abstract} | #### <span id=t-exposed-functions>Exposed Functions</span> This section lists functions that are explicitly declared public or payable. Please note that getter methods for public stateVars are not included. | ๐ŸŒPublic | ๐Ÿ’ฐPayable | | ---------- | --------- | | ${totals.totals.num.functionsPublic} | ${ totals.totals.num.functionsPayable } | | External | Internal | Private | Pure | View | | ---------- | -------- | ------- | ---- | ---- | | ${totals.totals.ast["FunctionDefinition:External"] || 0} | ${ totals.totals.ast["FunctionDefinition:Internal"] || 0 } | ${totals.totals.ast["FunctionDefinition:Private"] || 0} | ${ totals.totals.ast["FunctionDefinition:Pure"] || 0 } | ${totals.totals.ast["FunctionDefinition:View"] || 0} | #### <span id=t-statevariables>StateVariables</span> | Total | ๐ŸŒPublic | | ---------- | --------- | | ${totals.totals.num.stateVars} | ${totals.totals.num.stateVarsPublic} | #### <span id=t-capabilities>Capabilities</span> | Solidity Versions observed | ๐Ÿงช Experimental Features | ๐Ÿ’ฐ Can Receive Funds | ๐Ÿ–ฅ Uses Assembly | ๐Ÿ’ฃ Has Destroyable Contracts | | -------------------------- | ------------------------ | -------------------- | ---------------- | ---------------------------- | | ${totals.totals.capabilities.solidityVersions .map((v) => `\`${v}\``) .join("<br/>")} | ${totals.totals.capabilities.experimental .map((v) => `\`${v}\``) .join("<br/>")} | ${ totals.totals.capabilities.canReceiveFunds ? "`yes`" : "****" } | ${ totals.totals.capabilities.assembly ? `\`yes\` <br/>(${totals.totals.num.assemblyBlocks} asm blocks)` : "****" } | ${totals.totals.capabilities.destroyable ? "`yes`" : "****"} | | ๐Ÿ“ค Transfers ETH | โšก Low-Level Calls | ๐Ÿ‘ฅ DelegateCall | ๐Ÿงฎ Uses Hash Functions | ๐Ÿ”– ECRecover | ๐ŸŒ€ New/Create/Create2 | | ---------------- | ----------------- | --------------- | ---------------------- | ------------ | --------------------- | | ${totals.totals.capabilities.explicitValueTransfer ? "`yes`" : "****"} | ${ totals.totals.capabilities.lowLevelCall ? "`yes`" : "****" } | ${totals.totals.capabilities.delegateCall ? "`yes`" : "****"} | ${ totals.totals.capabilities.hashFuncs ? "`yes`" : "****" } | ${totals.totals.capabilities.ecrecover ? "`yes`" : "****"} | ${ totals.totals.capabilities.deploysContract ? "`yes`<br>" : "****" }${Object.keys(totals.totals.ast) .filter((k) => k.match( /(NewContract:|AssemblyCall:Name:create|AssemblyCall:Name:create2)/g ) ) .map((k) => `โ†’ \`${k}\``) .join("<br/>")} | | โ™ป๏ธ TryCatch | ฮฃ Unchecked | | ---------- | ----------- | | ${totals.totals.capabilities.tryCatchBlocks ? "`yes`" : "****"} | ${ totals.totals.capabilities.uncheckedBlocks ? "`yes`" : "****" } | #### <span id=t-package-imports>Dependencies / External Imports</span> | Dependency / Import Path | Count | | ------------------------ | ------ | ${Object.keys(totals.totals.ast) .filter((k) => k.startsWith("ImportDirective:Path:")) .sort() .map( (ki) => `| ${ki.replace("ImportDirective:Path:", "")} | ${ totals.totals.ast[ki] } |` ) .join("\n")} #### <span id=t-totals>Totals</span> ##### Summary <div class="wrapper" style="max-width: 90%; margin: auto"> <canvas id="chart-num-bar"></canvas> </div> ##### AST Node Statistics ###### Function Calls <div class="wrapper" style="max-width: 90%; margin: auto"> <canvas id="chart-num-bar-ast-funccalls"></canvas> </div> ###### Assembly Calls <div class="wrapper" style="max-width: 90%; margin: auto"> <canvas id="chart-num-bar-ast-asmcalls"></canvas> </div> ###### AST Total <div class="wrapper" style="max-width: 90%; margin: auto"> <canvas id="chart-num-bar-ast"></canvas> </div> ##### Inheritance Graph <a onclick="toggleVisibility('surya-inherit', this)">[โž•]</a> <div id="surya-inherit" style="display:none"> <div class="wrapper" style="max-width: 512px; margin: auto"> <div id="surya-inheritance" style="text-align: center;"></div> </div> </div> ##### CallGraph <a onclick="toggleVisibility('surya-call', this)">[โž•]</a> <div id="surya-call" style="display:none"> <div class="wrapper" style="max-width: 512px; margin: auto"> <div id="surya-callgraph" style="text-align: center;"></div> </div> </div> ###### Contract Summary <a onclick="toggleVisibility('surya-mdreport', this)">[โž•]</a> <div id="surya-mdreport" style="display:none"> ${suryamdreport} </div> ____ <sub> Thinking about smart contract security? We can provide training, ongoing advice, and smart contract auditing. [Contact us](https://diligence.consensys.net/contact/). </sub> --> </body> </html>