sol scan working

pull/4921/head
aniket-engg 5 months ago committed by Aniket
parent 2d8ad1552e
commit e361ff07b0
  1. 9
      apps/remix-ide/src/app/tabs/locales/en/solidity.json
  2. 10
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  3. 103
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  4. 103
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  5. 53
      libs/remix-ui/solidity-compiler/src/lib/solScanTable.tsx

@ -53,7 +53,16 @@
"solidity._comment_contract-selection.tsx": "libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx",
"solidity.publishOn": "Publish on",
"solidity.runStaticAnalysis": "Run Static Analysis",
"solidity.runSolidityScan": "Run Solidity Scan",
"solidity.solScan.iconTooltip": "Click to scan this contract for vulnerabilities using SolidityScan, a third-party provider [BETA]",
"solidity.solScan.modalTitle": "Permission to share code",
"solidity.solScan.modalMessage": "To scan and analyze the contract for risks and vulnerabilities, its code will be shared with SolidityScan, a third-party provider. ",
"solidity.solScan.likeToContinue": "Would you like to continue?",
"solidity.solScan.modalOkLabel": "Continue",
"solidity.solScan.modalCancelLabel": "Cancel",
"solidity.solScan.errModalTitle": "Scan error",
"solidity.solScan.successModalTitle": "Scan result",
"solidity.flatten": "Flatten contracts before UML generation.",
"solidity.generateUML": "Generate a UML diagram of your contract.",
"solidity.flattenLabel": "Flatten",

@ -80,16 +80,6 @@
"udapp.pinnedAt": "Pinned at",
"udapp.filePath": "File path",
"udapp.solScan.iconTooltip": "Click to scan this contract for vulnerabilities using SolidityScan, a third-party provider [BETA]",
"udapp.solScan.modalTitle": "Permission to share code",
"udapp.solScan.modalMessage": "To scan and analyze the contract for risks and vulnerabilities, its code will be shared with SolidityScan, a third-party provider. ",
"udapp.solScan.likeToContinue": "Would you like to continue?",
"udapp.solScan.modalOkLabel": "Continue",
"udapp.solScan.modalCancelLabel": "Cancel",
"udapp.solScan.errModalTitle": "Scan error",
"udapp.solScan.successModalTitle": "Scan result",
"udapp._comment_recorderCardUI.tsx": "libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx",
"udapp.transactionsRecorded": "Transactions recorded",
"udapp.transactionsCountTooltip": "The number of recorded transactions",

@ -6,10 +6,7 @@ import { FuncABI } from '@remix-project/core-plugin'
import { CopyToClipboard } from '@remix-ui/clipboard'
import * as remixLib from '@remix-project/remix-lib'
import * as ethJSUtil from '@ethereumjs/util'
import axios from 'axios'
import { AppModal } from '@remix-ui/app'
import { ContractGUI } from './contractGUI'
import { SolScanTable } from './solScanTable'
import { TreeView, TreeViewItem } from '@remix-ui/tree-view'
import { BN } from 'bn.js'
import { CustomTooltip, is0XPrefixed, isHexadecimal, isNumeric, shortenAddress } from '@remix-ui/helper'
@ -218,103 +215,6 @@ export function UniversalDappUI(props: UdappProps) {
setCalldataValue(value)
}
const handleScanContinue = async () => {
await props.plugin.call('notification', 'toast', 'Processing data to scan...')
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'initiateScan'])
const workspace = await props.plugin.call('filePanel', 'getCurrentWorkspace')
const fileName = props.instance.filePath || `${workspace.name}/${props.instance.contractData.contract.file}`
const filePath = `.workspaces/${fileName}`
const file = await props.plugin.call('fileManager', 'readFile', filePath)
const urlResponse = await axios.post(`https://solidityscan.remixproject.org/uploadFile`, { file, fileName })
if (urlResponse.data.status === 'success') {
const ws = new WebSocket('wss://solidityscan.remixproject.org/solidityscan')
ws.addEventListener('error', console.error);
ws.addEventListener('open', async (event) => {
await props.plugin.call('notification', 'toast', 'Initiating scan...')
})
ws.addEventListener('message', async (event) => {
const data = JSON.parse(event.data)
if (data.type === "auth_token_register" && data.payload.message === "Auth token registered.") {
// Message on Bearer token successful registration
const reqToInitScan = {
"action": "message",
"payload": {
"type": "private_project_scan_initiate",
"body": {
"file_urls": [
urlResponse.data.result.url
],
"project_name": "RemixProject",
"project_type": "new"
}
}
}
ws.send(JSON.stringify(reqToInitScan))
} else if (data.type === "scan_status" && data.payload.scan_status === "download_failed") {
// Message on failed scan
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'scanFailed'])
const modal: AppModal = {
id: 'SolidityScanError',
title: <FormattedMessage id="udapp.solScan.errModalTitle" />,
message: data.payload.scan_status_err_message,
okLabel: 'Close'
}
await props.plugin.call('notification', 'modal', modal)
} else if (data.type === "scan_status" && data.payload.scan_status === "scan_done") {
// Message on successful scan
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'scanSuccess'])
const url = data.payload.scan_details.link
const { data: scanData } = await axios.post('https://solidityscan.remixproject.org/downloadResult', { url })
const scanDetails: Record<string, any>[] = scanData.scan_report.multi_file_scan_details
let modal: AppModal
if (scanDetails && scanDetails.length) {
await props.plugin.call('terminal', 'logHtml', <SolScanTable scanDetails={scanDetails} fileName={fileName}/>)
} else {
modal = {
id: 'SolidityScanError',
title: <FormattedMessage id="udapp.solScan.errModalTitle" />,
message: "Some error occurred! Please try again",
okLabel: 'Close'
}
}
await props.plugin.call('notification', 'modal', modal)
}
})
}
}
const askPermissionToScan = async () => {
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'askPermissionToScan'])
const modal: AppModal = {
id: 'SolidityScanPermissionHandler',
title: <FormattedMessage id="udapp.solScan.modalTitle" />,
message: <div className='d-flex flex-column'>
<span><FormattedMessage id="udapp.solScan.modalMessage" />
<a href={'https://solidityscan.com'}
target="_blank"
onClick={() => _paq.push(['trackEvent', 'udapp', 'solidityScan', 'learnMore'])}>
Learn more
</a>
</span>
<br/>
<FormattedMessage id="udapp.solScan.likeToContinue" />
</div>,
okLabel: <FormattedMessage id="udapp.solScan.modalOkLabel" />,
okFn: handleScanContinue,
cancelLabel: <FormattedMessage id="udapp.solScan.modalCancelLabel" />
}
await props.plugin.call('notification', 'modal', modal)
}
const label = (key: string | number, value: string) => {
return (
<div className="d-flex mt-2 flex-row label_item">
@ -407,9 +307,6 @@ export function UniversalDappUI(props: UdappProps) {
></i>
</CustomTooltip>
)}
<CustomTooltip placement="top" tooltipClasses="text-nowrap" tooltipId="udapp_udappSolScanTooltip" tooltipText={<FormattedMessage id="udapp.solScan.iconTooltip" />}>
<i className="fas fa-qrcode p-0" style={{ padding: "0.15rem" }} onClick={askPermissionToScan}></i>
</CustomTooltip>
</div>
</div>
{ props.isPinnedContract && props.instance.pinnedAt ? (

@ -5,6 +5,10 @@ import {PublishToStorage} from '@remix-ui/publish-to-storage' // eslint-disable-
import {TreeView, TreeViewItem} from '@remix-ui/tree-view' // eslint-disable-line
import {CopyToClipboard} from '@remix-ui/clipboard' // eslint-disable-line
import { saveAs } from 'file-saver'
import { AppModal } from '@remix-ui/app'
import { SolScanTable } from './solScanTable'
import axios from 'axios'
import './css/style.css'
import { CustomTooltip } from '@remix-ui/helper'
@ -249,8 +253,101 @@ export const ContractSelection = (props: ContractSelectionProps) => {
console.log('runStaticAnalysis')
}
const runSolidityScan = () => {
console.log('runSolidityScan')
const handleScanContinue = async () => {
const plugin = api as any
await plugin.call('notification', 'toast', 'Processing data to scan...')
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'initiateScan'])
const workspace = await plugin.call('filePanel', 'getCurrentWorkspace')
const fileName = `${workspace.name}/${props.compiledFileName}`
const filePath = `.workspaces/${fileName}`
const file = await plugin.call('fileManager', 'readFile', filePath)
const urlResponse = await axios.post(`https://solidityscan.remixproject.org/uploadFile`, { file, fileName })
if (urlResponse.data.status === 'success') {
const ws = new WebSocket('wss://solidityscan.remixproject.org/solidityscan')
ws.addEventListener('error', console.error);
ws.addEventListener('open', async (event) => {
await plugin.call('notification', 'toast', 'Fetching result in terminal ...')
})
ws.addEventListener('message', async (event) => {
const data = JSON.parse(event.data)
if (data.type === "auth_token_register" && data.payload.message === "Auth token registered.") {
// Message on Bearer token successful registration
const reqToInitScan = {
"action": "message",
"payload": {
"type": "private_project_scan_initiate",
"body": {
"file_urls": [
urlResponse.data.result.url
],
"project_name": "RemixProject",
"project_type": "new"
}
}
}
ws.send(JSON.stringify(reqToInitScan))
} else if (data.type === "scan_status" && data.payload.scan_status === "download_failed") {
// Message on failed scan
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'scanFailed'])
const modal: AppModal = {
id: 'SolidityScanError',
title: <FormattedMessage id="solidity.solScan.errModalTitle" />,
message: data.payload.scan_status_err_message,
okLabel: 'Close'
}
await plugin.call('notification', 'modal', modal)
} else if (data.type === "scan_status" && data.payload.scan_status === "scan_done") {
// Message on successful scan
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'scanSuccess'])
const url = data.payload.scan_details.link
const { data: scanData } = await axios.post('https://solidityscan.remixproject.org/downloadResult', { url })
const scanDetails: Record<string, any>[] = scanData.scan_report.multi_file_scan_details
if (scanDetails && scanDetails.length) {
await plugin.call('terminal', 'logHtml', <SolScanTable scanDetails={scanDetails} fileName={fileName}/>)
} else {
const modal: AppModal = {
id: 'SolidityScanError',
title: <FormattedMessage id="solidity.solScan.errModalTitle" />,
message: "Some error occurred! Please try again",
okLabel: 'Close'
}
await plugin.call('notification', 'modal', modal)
}
}
})
}
}
const runSolidityScan = async () => {
_paq.push(['trackEvent', 'udapp', 'solidityScan', 'askPermissionToScan'])
const modal: AppModal = {
id: 'SolidityScanPermissionHandler',
title: <FormattedMessage id="solidity.solScan.modalTitle" />,
message: <div className='d-flex flex-column'>
<span><FormattedMessage id="solidity.solScan.modalMessage" />
<a href={'https://solidityscan.com'}
target="_blank"
onClick={() => _paq.push(['trackEvent', 'udapp', 'solidityScan', 'learnMore'])}>
Learn more
</a>
</span>
<br/>
<FormattedMessage id="solidity.solScan.likeToContinue" />
</div>,
okLabel: <FormattedMessage id="solidity.solScan.modalOkLabel" />,
okFn: handleScanContinue,
cancelLabel: <FormattedMessage id="solidity.solScan.modalCancelLabel" />
}
await (api as any).call('notification', 'modal', modal)
}
return (
@ -304,7 +401,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
tooltipId="runSolidityScanTooltip"
tooltipClasses="text-nowrap"
tooltipText={`${intl.formatMessage({
id: 'solidity.runSolidityScan'
id: 'solidity.solScan.iconTooltip'
})}`}
>
<span>

@ -0,0 +1,53 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import parse from 'html-react-parser'
const _paq = (window._paq = window._paq || [])
interface SolScanTableProps {
scanDetails: Record<string, any>[],
fileName: string
}
export function SolScanTable(props: SolScanTableProps) {
const { scanDetails, fileName } = props
return (
<>
<p>Scanning successful! <b>{scanDetails.length} warnings </b> found for file: <b>{fileName}</b></p>
<p>See the warning details below. For more details,&nbsp;
<a href="https://solidityscan.com/signup"
target='_blank'
onClick={() => _paq.push(['trackEvent', 'udapp', 'solidityScan', 'goToSolidityScan'])}>
go to SolidityScan.
</a>
</p>
<table className="table table-bordered table-hover">
<thead>
<tr>
<td scope="col" style={{ wordBreak: "keep-all" }}>NAME</td>
<td scope="col" style={{ wordBreak: "keep-all" }}>SEVERITY</td>
<td scope="col" style={{ wordBreak: "keep-all" }}>CONFIDENCE</td>
<td scope="col" style={{ wordBreak: "keep-all" }}>DESCRIPTION</td>
<td scope="col" style={{ wordBreak: "keep-all" }}>REMEDIATION</td>
</tr>
</thead>
<tbody>
{
Array.from(scanDetails, (template) => {
return (
<tr key={template.template_details.issue_id}>
<td scope="col">{template.template_details.issue_name}</td>
<td scope="col">{template.template_details.issue_severity}</td>
<td scope="col">{template.template_details.issue_confidence}</td>
<td scope="col">{parse(template.template_details.static_issue_description)}</td>
<td scope="col">{template.template_details.issue_remediation ? parse(template.template_details.issue_remediation) : 'Not Available' }</td>
</tr>
)
})
}
</tbody>
</table>
</>
)
}
Loading…
Cancel
Save