mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
soliditycheck report
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 3.6v4.812c0 6.447 5.414 8.703 6.79 9.17 1.377-.467 6.791-2.723 6.791-9.17V3.6H3ZM1.506 2.091A1.714 1.714 0 0 1 2.708 1.6h14.165c.448 0 .88.175 1.202.491.322.317.506.75.506 1.206v5.115c0 8.015-6.912 10.66-8.246 11.097a1.647 1.647 0 0 1-1.089 0C7.912 19.072 1 16.427 1 8.412V3.297c0-.455.184-.889.506-1.206Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.9 5.4a1.1 1.1 0 0 0-1.1 1.1v3.8a1.1 1.1 0 0 0 2.2 0V6.5a1.1 1.1 0 0 0-1.1-1.1Zm1.1 8.343a1.1 1.1 0 1 1-2.2 0 1.1 1.1 0 0 1 2.2 0Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 670 B |
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 8.412V3.6h13.581v4.812c0 6.447-5.414 8.703-6.79 9.17C8.414 17.115 3 14.86 3 8.412ZM2.708 1.6c-.448 0-.88.175-1.202.491-.322.317-.506.75-.506 1.206v5.115c0 8.015 6.912 10.66 8.246 11.097.352.123.737.123 1.089 0 1.334-.437 8.246-3.082 8.246-11.097V3.297c0-.455-.184-.889-.506-1.206a1.714 1.714 0 0 0-1.202-.491H2.708ZM14.37 8.208a1 1 0 1 0-1.369-1.458L8.49 10.986 6.58 9.191a1 1 0 1 0-1.37 1.457l2.594 2.44a1 1 0 0 0 1.37 0l5.196-4.88Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 591 B |
@@ -31,7 +31,7 @@ import type { AddressesResponse } from 'types/api/addresses';
|
||||
import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters, BlockWithdrawalsResponse } from 'types/api/block';
|
||||
import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts';
|
||||
import type { BackendVersionConfig } from 'types/api/configs';
|
||||
import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig } from 'types/api/contract';
|
||||
import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig, SolidityscanReport } from 'types/api/contract';
|
||||
import type { VerifiedContractsResponse, VerifiedContractsFilters, VerifiedContractsCounters } from 'types/api/contracts';
|
||||
import type { IndexingStatus } from 'types/api/indexingStatus';
|
||||
import type { InternalTransactionsResponse } from 'types/api/internalTransaction';
|
||||
@@ -343,6 +343,10 @@ export const RESOURCES = {
|
||||
path: '/api/v2/smart-contracts/:hash/verification/via/:method',
|
||||
pathParams: [ 'hash' as const, 'method' as const ],
|
||||
},
|
||||
contract_solidityscan_report: {
|
||||
path: '/api/v2/smart-contracts/:hash/solidityscan-report',
|
||||
pathParams: [ 'hash' as const ],
|
||||
},
|
||||
|
||||
verified_contracts: {
|
||||
path: '/api/v2/smart-contracts',
|
||||
@@ -659,6 +663,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
|
||||
Q extends 'contract_methods_read_proxy' ? Array<SmartContractReadMethod> :
|
||||
Q extends 'contract_methods_write' ? Array<SmartContractWriteMethod> :
|
||||
Q extends 'contract_methods_write_proxy' ? Array<SmartContractWriteMethod> :
|
||||
Q extends 'contract_solidityscan_report' ? SolidityscanReport :
|
||||
Q extends 'verified_contracts' ? VerifiedContractsResponse :
|
||||
Q extends 'verified_contracts_counters' ? VerifiedContractsCounters :
|
||||
Q extends 'visualize_sol2uml' ? VisualizedContract :
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
export const solidityscanReport = {
|
||||
scan_report: {
|
||||
scan_status: 'scan_done',
|
||||
scan_summary: {
|
||||
issue_severity_distribution: {
|
||||
critical: 0,
|
||||
gas: 1,
|
||||
high: 0,
|
||||
informational: 0,
|
||||
low: 2,
|
||||
medium: 0,
|
||||
},
|
||||
lines_analyzed_count: 18,
|
||||
scan_time_taken: 1,
|
||||
score: '3.61',
|
||||
score_v2: '72.22',
|
||||
threat_score: '94.74',
|
||||
},
|
||||
scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout',
|
||||
},
|
||||
};
|
||||
+23
-1
@@ -1,4 +1,4 @@
|
||||
import type { SmartContract } from 'types/api/contract';
|
||||
import type { SmartContract, SolidityscanReport } from 'types/api/contract';
|
||||
import type { VerifiedContract } from 'types/api/contracts';
|
||||
|
||||
import { ADDRESS_PARAMS } from './addressParams';
|
||||
@@ -53,3 +53,25 @@ export const VERIFIED_CONTRACT_INFO: VerifiedContract = {
|
||||
tx_count: 565058,
|
||||
verified_at: '2023-04-10T13:16:33.884921Z',
|
||||
};
|
||||
|
||||
export const SOLIDITYSCAN_REPORT: SolidityscanReport = {
|
||||
scan_report: {
|
||||
scan_status: 'scan_done',
|
||||
scan_summary: {
|
||||
issue_severity_distribution: {
|
||||
critical: 0,
|
||||
gas: 1,
|
||||
high: 0,
|
||||
informational: 0,
|
||||
low: 2,
|
||||
medium: 0,
|
||||
},
|
||||
lines_analyzed_count: 18,
|
||||
scan_time_taken: 1,
|
||||
score: '3.61',
|
||||
score_v2: '72.22',
|
||||
threat_score: '94.74',
|
||||
},
|
||||
scanner_reference_url: 'https://solidityscan.com/quickscan/0xc1EF7811FF2ebFB74F80ed7423f2AdAA37454be2/blockscout/eth-goerli?ref=blockscout',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -156,3 +156,25 @@ export interface SmartContractVerificationError {
|
||||
constructor_arguments?: Array<string>;
|
||||
name?: Array<string>;
|
||||
}
|
||||
|
||||
export type SolidityscanReport = {
|
||||
scan_report: {
|
||||
scan_status: string;
|
||||
scan_summary: {
|
||||
issue_severity_distribution: {
|
||||
critical: number;
|
||||
gas: number;
|
||||
high: number;
|
||||
informational: number;
|
||||
low: number;
|
||||
medium: number;
|
||||
};
|
||||
lines_analyzed_count: number;
|
||||
scan_time_taken: number;
|
||||
score: string;
|
||||
score_v2: string;
|
||||
threat_score: string;
|
||||
};
|
||||
scanner_reference_url: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { test, expect } from '@playwright/experimental-ct-react';
|
||||
import React from 'react';
|
||||
|
||||
import { solidityscanReport as solidityscanReportMock } from 'mocks/contract/solidityscanReport';
|
||||
import TestApp from 'playwright/TestApp';
|
||||
import buildApiUrl from 'playwright/utils/buildApiUrl';
|
||||
|
||||
import SolidityscanReport from './SolidityscanReport';
|
||||
|
||||
const addressHash = 'hash';
|
||||
const REPORT_API_URL = buildApiUrl('contract_solidityscan_report', { hash: addressHash });
|
||||
|
||||
test('base view +@dark-mode +@mobile', async({ mount, page }) => {
|
||||
await page.route(REPORT_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify(solidityscanReportMock),
|
||||
}));
|
||||
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<SolidityscanReport hash={ addressHash }/>
|
||||
</TestApp>,
|
||||
);
|
||||
await component.getByLabel('SolidityScan score').click();
|
||||
|
||||
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 400, height: 500 } });
|
||||
});
|
||||
@@ -0,0 +1,159 @@
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Text,
|
||||
Grid,
|
||||
Button,
|
||||
Icon,
|
||||
chakra,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
PopoverBody,
|
||||
PopoverContent,
|
||||
useDisclosure,
|
||||
Skeleton,
|
||||
Center,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import { SolidityscanReport } from 'types/api/contract';
|
||||
|
||||
import scoreNotOkIcon from 'icons/score/score-not-ok.svg';
|
||||
import scoreOkIcon from 'icons/score/score-ok.svg';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import { SOLIDITYSCAN_REPORT } from 'stubs/contract';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
|
||||
type DistributionItem = {
|
||||
id: keyof SolidityscanReport['scan_report']['scan_summary']['issue_severity_distribution'];
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
const DISTRIBUTION_ITEMS: Array<DistributionItem> = [
|
||||
{ id: 'critical', name: 'Critical', color: '#891F11' },
|
||||
{ id: 'high', name: 'High', color: '#EC672C' },
|
||||
{ id: 'medium', name: 'Medium', color: '#FBE74D' },
|
||||
{ id: 'low', name: 'Low', color: '#68C88E' },
|
||||
{ id: 'informational', name: 'Informational', color: '#A3AEBE' },
|
||||
{ id: 'gas', name: 'Gas', color: '#A47585' },
|
||||
];
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
const { isOpen, onToggle, onClose } = useDisclosure();
|
||||
|
||||
const { data, isPlaceholderData, isError } = useApiQuery('contract_solidityscan_report', {
|
||||
pathParams: { hash },
|
||||
queryOptions: {
|
||||
enabled: Boolean(hash),
|
||||
placeholderData: SOLIDITYSCAN_REPORT,
|
||||
},
|
||||
});
|
||||
|
||||
const score = Number(data?.scan_report.scan_summary.score_v2);
|
||||
|
||||
const bgBar = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
|
||||
const chartGrayColor = useColorModeValue('gray.100', 'gray.700');
|
||||
const yetAnotherGrayColor = useColorModeValue('gray.400', 'gray.500');
|
||||
const popoverBgColor = useColorModeValue('white', 'gray.900');
|
||||
|
||||
if (isError || !score) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let scoreColor;
|
||||
let scoreLevel;
|
||||
if (score >= 80) {
|
||||
scoreColor = 'green.600';
|
||||
scoreLevel = 'GREAT';
|
||||
} else if (score >= 30) {
|
||||
scoreColor = 'orange.600';
|
||||
scoreLevel = 'AVERAGE';
|
||||
} else {
|
||||
scoreColor = 'red.600';
|
||||
scoreLevel = 'LOW';
|
||||
}
|
||||
|
||||
const vulnerabilities = data?.scan_report.scan_summary.issue_severity_distribution;
|
||||
const vulnerabilitiesCounts = vulnerabilities ? Object.values(vulnerabilities) : [];
|
||||
const vulnerabilitiesCount = vulnerabilitiesCounts.reduce((acc, val) => acc + val, 0);
|
||||
|
||||
return (
|
||||
<Popover isOpen={ isOpen } onClose={ onClose } placement="bottom-start" isLazy>
|
||||
<PopoverTrigger>
|
||||
<Skeleton isLoaded={ !isPlaceholderData }>
|
||||
<Button
|
||||
className={ className }
|
||||
color={ scoreColor }
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
onClick={ onToggle }
|
||||
aria-label="SolidityScan score"
|
||||
fontWeight={ 500 }
|
||||
px={ 2 }
|
||||
h="32px"
|
||||
flexShrink={ 0 }
|
||||
>
|
||||
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } mr={ 1 }/>
|
||||
{ score }
|
||||
</Button>
|
||||
</Skeleton>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent w={{ base: '100vw', lg: '328px' }}>
|
||||
<PopoverBody px="26px" py="20px" fontSize="sm">
|
||||
<Box mb={ 5 }>Contract analyzed for 140+ vulnerability patterns by SolidityScan</Box>
|
||||
<Flex alignItems="center" mb={ 5 }>
|
||||
<Box
|
||||
w={ 12 }
|
||||
h={ 12 }
|
||||
bgGradient={ `conic-gradient(${ scoreColor } 0, ${ scoreColor } ${ score }%, ${ chartGrayColor } 0, ${ chartGrayColor } 100%)` }
|
||||
borderRadius="24px"
|
||||
position="relative"
|
||||
mr={ 3 }
|
||||
>
|
||||
<Center position="absolute" w="38px" h="38px" top="5px" right="5px" bg={ popoverBgColor } borderRadius="20px">
|
||||
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } color={ scoreColor }/>
|
||||
</Center>
|
||||
</Box>
|
||||
<Box>
|
||||
<Flex>
|
||||
<Text color={ scoreColor } fontSize="lg" fontWeight={ 500 }>{ score }</Text>
|
||||
<Text color={ yetAnotherGrayColor } fontSize="lg" fontWeight={ 500 } whiteSpace="pre"> / 100</Text>
|
||||
</Flex>
|
||||
<Text color={ scoreColor } fontWeight={ 500 }>Security score is { scoreLevel }</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
{ vulnerabilities && vulnerabilitiesCount && (
|
||||
<Box mb={ 5 }>
|
||||
<Text py="7px" variant="secondary" fontSize="xs" fontWeight={ 500 }>Vulnerabilities distribution</Text>
|
||||
<Grid templateColumns="20px 1fr 100px" alignItems="center" rowGap={ 2 }>
|
||||
{ DISTRIBUTION_ITEMS.map(item => (
|
||||
<>
|
||||
<Box w={ 3 } h={ 3 } bg={ item.color } borderRadius="6px" mr={ 2 }></Box>
|
||||
<Flex justifyContent="space-between" mr={ 3 }>
|
||||
<Text>{ item.name }</Text>
|
||||
<Text color={ vulnerabilities[item.id] > 0 ? 'text' : yetAnotherGrayColor }>{ vulnerabilities[item.id] }</Text>
|
||||
</Flex>
|
||||
<Box bg={ bgBar } h="10px" borderRadius="8px">
|
||||
<Box bg={ item.color } w={ vulnerabilities[item.id] / vulnerabilitiesCount } h="10px" borderRadius="8px"/>
|
||||
</Box>
|
||||
</>
|
||||
)) }
|
||||
</Grid>
|
||||
</Box>
|
||||
) }
|
||||
<LinkExternal href={ data?.scan_report.scanner_reference_url }>View full report</LinkExternal>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default chakra(SolidityscanReport);
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Icon } from '@chakra-ui/react';
|
||||
import { Box, Flex, HStack, Icon } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
@@ -25,6 +25,7 @@ import AddressTxs from 'ui/address/AddressTxs';
|
||||
import AddressWithdrawals from 'ui/address/AddressWithdrawals';
|
||||
import AddressFavoriteButton from 'ui/address/details/AddressFavoriteButton';
|
||||
import AddressQrCode from 'ui/address/details/AddressQrCode';
|
||||
import SolidityscanReport from 'ui/address/SolidityscanReport';
|
||||
import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu';
|
||||
import TextAd from 'ui/shared/ad/TextAd';
|
||||
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
|
||||
@@ -194,7 +195,9 @@ const AddressPageContent = () => {
|
||||
) }
|
||||
<AddressQrCode address={{ hash }} isLoading={ isLoading }/>
|
||||
<AccountActionsMenu isLoading={ isLoading }/>
|
||||
<NetworkExplorers type="address" pathParam={ hash } ml="auto"/>
|
||||
<HStack ml="auto" gap={ 2 }/>
|
||||
<SolidityscanReport hash={ hash }/>
|
||||
<NetworkExplorers type="address" pathParam={ hash }/>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user