mirror of
https://github.com/luxfi/safe-wallet.git
synced 2026-10-30 15:19:21 +00:00
* feat(web): add SECURITY_HUB feature flag and route plumbing Adds SECURITY_HUB to the FEATURES enum, registers the value in MSW chain fixtures (mainnet + all), bumps the gateway schema hash, marks /spaces/security as a recognised space route, and applies minor PageLayout/useRouterGuard touch-ups. Foundation for the SecurityHub feature; subsequent stacked PRs build on top of this. Part 1/8 of the security-hub split (originally PR #7820). * feat(security): scanner infrastructure (#7840) * feat(security): scanner infrastructure — types, utils, constants, test helpers Introduces the core scanner module shape that subsequent stacked PRs plug into: - types: ScanContext, ScanResult, SecurityScanner contract - constants: thresholds, version data, environment guards - utils: computeSummary, severityRank, scanKey, formatTimestamp - test-helpers: shared scaffolding for scanner unit tests Forward refs to securityTypes/securityScoring resolve in PR 4/8. Part 2/8 of the security-hub split (originally PR #7820). * fix(web): move definitions to contants and types * refactor(security): address scanner-infra review feedback - Move SCANNER_TIMEOUT_MS from utils.ts to constants.ts (review #3217986422) - Drop unused local ZERO_ADDRESS — consumers can import it from @safe-global/utils/utils/constants when needed (review #3217891868) - Normalize address in scanKey via toLowerCase so checksummed and lowercase inputs yield the same key (review #3217958268) - Add tests for withScannerTimeout and getSafeGrade (review body) * feat(security): individual safe-state scanners + registry (#7841) * feat(security): individual safe-state scanners + registry Implements the 11 scanners that inspect a Safe and produce ScanResults: - accountSetup, multichainSetup, contractVersion - modules, guard, fallbackHandler, factoryValidation - pendingTx, recovery, transactionScanning, signerIntegrity Plus the registry that aggregates them into the SCANNERS array consumed by the scoring engine. Each scanner ships with its own unit tests, plus a shared defaultValues regression test. Builds on PR 2/8 (scanner infra). Feature public API lands in PR 4/8. Part 3/8 of the security-hub split (originally PR #7820). * refactor(security): address safe-state-scanner review feedback accountSetup: extract baseEvidence, recommend 2+ for 1/N threshold (review #3218059833, #3218097369) guard: rename local isHypernativeGuard to nameSuggestsHypernativeGuard, tighten to startsWith (review #3219227551). Add getSeverityFromScore helper to constants (review #3218213953). fallbackHandler: import TWAP_FALLBACK_HANDLER(_NETWORKS) from @/features/swap (review #3219147109). Move handlerLabel above the match check so both branches reuse it (review #3219191990). modules: extract ALLOWANCE_MODULE_VERSIONS (review #3219257831) and trusted/untrusted evidence arrays (review #3219273672). recovery: replace substring "delay" check with exact match against DELAY_MODIFIER_NAMES (review #3219297536). Source ZERO_ADDRESS from @safe-global/utils/utils/constants across all scanners (carries over from PR 7840's local-const removal). * fix(security): import TWAP constants from helpers/utils to avoid cycle Importing from '@/features/swap' pulls createFeatureHandle into the scanner module graph, which causes a circular dependency with @/features/__core__ when consumers (e.g. SecurityHub tests) mock the core module. Importing directly from helpers/utils keeps the dedup intent of review #3219147109 while sidestepping the feature handle. * feat(security): scoring engine + feature public API (#7842) * feat(security): scoring engine + feature public API Wraps the scanners from PR 3/8 into a consumable feature: - securityTypes / securityChecks: dimension definitions and CheckStatus taxonomy that scanners and the UI share. - securityScoring: aggregates ScanResult[] into per-Safe SecurityGrade. - feature/contract/index/testing/types: the feature-architecture public surface (createFeatureHandle, exported types, testing stubs). - SECURITY_CHECKS_MATRIX.md: the source-of-truth matrix mapping each scanner to severity/weight/grade. Resolves PR 2/8's forward refs to securityTypes and securityScoring. Hooks consuming this API land in PR 5/8. Part 4/8 of the security-hub split (originally PR #7820). * refactor(security): unify scoring thresholds in a single source of truth Replace the duplicated ternary thresholds in getGrade / getStrengthLevel with a single SCORING_THRESHOLDS table that pairs each clear-ratio threshold with both a SecurityGrade and a StrengthLevel. Resolves review #3219362052 on PR 7842. * fix(security): repair stale imports after ZERO_ADDRESS / SafeGrade moves PR 7840's review fixes dropped ZERO_ADDRESS from the local scanners/constants.ts and moved SafeGrade out of scanners/utils.ts into scanners/types.ts. The feature contract/types files were added on this branch (PR 7842) and still imported from the old locations — silently breaking module resolution at runtime, which prevented the SecurityHub sidebar entry from rendering. - feature.ts / contract.ts: import ZERO_ADDRESS from @safe-global/utils/utils/constants instead of the local constants - types.ts: re-export SafeGrade from data/scanners/types (where it lives now); GradeSummary stays in data/scanners/utils * feat(security): scan + feature-redirect hooks (#7843) * feat(security): scan + feature-redirect hooks Adds the React hooks that consume the scoring engine from PR 4/8: - features/security/hooks/useSecurityScan: runs SCANNERS against a Safe and exposes ScanResult[] with cache + loading metadata. - features/security/hooks/useSecurityHubFeatureRedirect: gates the /spaces/security route behind the SECURITY_HUB flag. - features/spaces/hooks/useAutoScan: queues per-Safe scans across a space with throttling + cancellation. - features/spaces/hooks/useSafeScanContext: builds the per-Safe ScanContext required by the scanners (RTK Query data, chain, owners, threshold, etc). Each hook ships with unit tests. SecurityHub container that orchestrates these lands in PR 6/8. Part 5/8 of the security-hub split (originally PR #7820). * refactor(security): address review feedback on scan hook + cache - Extract scanResultsCache into its own module with private Map and get/set accessors so consumers can't mutate it by reference. - Prefer newer timestamp on cache writes so a slow scan can't overwrite a faster, fresher one. - Tighten SecurityScanner.id to a ScannerId literal union. - Replace `err: any` with `err: unknown` in useSecurityScan catch. - Fix initial-render progress reading 100% by counting settled scanners (results + errors) over total, not (total - loadingCount). Updates feature.ts/contract.ts/useAutoScan callers to the new setCachedScan/getCachedScan API. * feat(security-hub): SecurityHub container + orchestrator hooks (#7844) * feat(security-hub): SecurityHub container + orchestrator hooks Adds the SecurityHub feature container under features/spaces, plus the four hooks that drive its state machine: - Page / index / types / utils: container entrypoint and shared shape - useAutoScanOrchestrator: schedules and reconciles per-Safe scans - useReconciledSpaceSafes: zips space membership with chain Safe state - useReportDrawer: drawer open/close + selected scan target - useScanResultsState: aggregates ScanResults across Safes for the panel Forward refs to SecurityPanelView / SecurityReportDrawer / SecuritySafesTable / WorkspaceHealthCard resolve in PR 7/8. Part 6/8 of the security-hub split (originally PR #7820). * refactor(security-hub): address review feedback on container hooks - useReportDrawer: use sameAddress for address comparisons and require the selected chain to be one of the safe's chainEntries so multichain groups don't match across chains. - utils.flattenSafes: drop the mainnet fallback for empty multichain groups — skip them instead so we don't synthesise a bogus chain that would queue scans against a non-existent Safe. - Migrate AutoScanServices wiring to the new setCachedScan API introduced in part 5. * feat(security-hub): UI components — panel, drawer, table, health card (#7845) * feat(security-hub): UI components — panel, drawer, table, health card Adds the four visual components rendered inside the SecurityHub container (PR 6/8): - WorkspaceHealthCard: aggregate space score + grade chips + re-scan - SecuritySafesTable: per-Safe row table with status / score / actions - SecurityPanelView: shell + primitives + useSecurityChecks state hook - SecurityReportDrawer: accordion-based drawer with per-check CTAs Each component ships with its Storybook story, story-derived snapshot test, and __snapshots__ file. Adds container-level tests for SecurityPanelView and SecuritySafesTable that exercise the wired-up flow. Last piece before the routing PR (8/8) wires this into the sidebar. Part 7/8 of the security-hub split (originally PR #7820). * tests(security-hub): align SecuritySafesTable test scanKey with real impl The test's local scanKey helper used `${address}:${chainId}` but security.scanKey lowercases the address. The mismatch meant scanResults[key] resolved to undefined inside the component, so cells rendered dashes instead of either skeletons (scanning state) or evidence values — failing two assertions. * feat(security-hub): wire SecurityHub into sidebar + routing Final integration PR — connects the SecurityHub container from PR 6/8 and its panel components from PR 7/8 to the rest of the app: - pages/spaces/security.tsx: Next.js page entry - features/spaces/components/Sidebar/config: registers Security item - features/spaces/components/SpaceSidebarNavigation: nav item + active state handling - features/spaces/contract.ts / feature.ts: feature-flag plumbing After this PR is merged on top of 1-7, the resulting state is byte-for-byte identical to PR #7820. Part 8/8 of the security-hub split (originally PR #7820). * chore(web): move badge component to its own folder * refactor(security-hub): extract SafeGradeChip + shared grade tokens Move the SafeGrade label and palette out of StatusCell and the WorkspaceHealthCard filter chips into a single primitive at components/SafeGradeChip/. The primitive owns the soft-vs-active variant and label/palette lookup; both consumers reduce to a one-liner (StatusCell static, WHC interactive with active + onClick). * refactor(security): colocate SAFE_GRADE_RANK with SEVERITY_RANK Move SAFE_GRADE_RANK from SecuritySafesTable.tsx into the canonical scanner constants file, right next to SEVERITY_RANK. The two ranks operate over different unions (SafeGrade vs SecurityGrade); sitting them side by side with a docblock makes the distinction obvious at the declaration site. * refactor(security-hub): dedupe SEVERITY_RANK + split SecuritySafesTable - primitives.tsx: drop the duplicate SEVERITY_RANK and import the canonical one from data/scanners/constants. - SecuritySafesTable: extract cells (ScoreCell / ThresholdCell / VersionCell / BalanceCell), helpers (formatBalance, getEvidence, getAggregateSummary, getAggregateSafeGrade, hasMultichainWarning, isAnyChainScanning), and visual constants (DASH, ROW_VARIANTS, MotionTableRow, MotionTbody) into three sibling files. The main file drops from 684 → 482 lines. * refactor(security-hub): extract row components from SecuritySafesTable Pull the two row variants and the table chrome out of the main file: - SingleSafeRow.tsx: single-chain Safe row. - MultichainSafeRow.tsx: collapsed parent row + per-chain children rendered when expanded (child row lives as a sub-component in the same file since it is tightly coupled to the parent). - constants.tsx: add TABLE_SX and the COLUMNS list so the table chrome config sits beside the other visual constants. SecuritySafesTable.tsx is now 148 lines (was 684 originally) and just owns the feature handle, animation/expand state, grade filter, and the single-vs-multichain dispatch. Storybook snapshot tests pass unchanged. * refactor(security-hub): split SecurityPanelView into view + hooks Pull the panel apart along the view/logic seam: Views (sibling files): - SectionPanel.tsx — animated section wrapper. - PanelHeader.tsx — score gauge + strength chip + action line. - SignersSection.tsx — signers + multichain accordion. - SecurityChecksSection.tsx — security-checks accordion. Business logic (hooks/ subfolder): - usePanelHeader.ts — derives score/level/color/actionLine from results. - useSignerRows.tsx — signer + multichain row bucketing and sorting. - useSecurityChecks.tsx — moved here; per-check row builder. Plus a constants.ts holding STRENGTH_DESCRIPTIONS / GRADE_BG_BY_STRENGTH / ROW_STAGGER. SecurityPanelView.tsx drops from 421 → 58 lines and now just composes the three sub-sections + skeleton fallback. Storybook snapshot tests pass unchanged. * refactor(security-hub): address review feedback on panel components - Use maybePlural for signer / check / issue plurals - buildExpanded reuses isPassingStatus (inconclusive no longer shows remediation) - useSecurityChecks memoizes the failing/passing row derivation - MultichainSafeRow uses sameAddress for the selection check - Derive SecuritySafesTable's rank → grade lookup from SEVERITY_RANK - Re-export SEVERITY_RANK and SAFE_GRADE_RANK from @/features/security so primitives.tsx and SecuritySafesTable/utils.ts stop reaching into the feature's internals --------- --------- --------- --------- --------- * feat(web): reuse severityScore utility function * fix(web): remove unnecessary file --------- * fix(web): remove console.log --------- Co-authored-by: Hanzo Dev <[email protected]>
112 lines
2.9 KiB
JSON
112 lines
2.9 KiB
JSON
{
|
|
"chainId": "1",
|
|
"chainName": "Ethereum",
|
|
"description": "",
|
|
"chainLogoUri": "https://safe-transaction-assets.staging.5afe.dev/chains/1/chain_logo.png",
|
|
"l2": false,
|
|
"isTestnet": false,
|
|
"zk": false,
|
|
"nativeCurrency": {
|
|
"name": "Ether",
|
|
"symbol": "ETH",
|
|
"decimals": 18,
|
|
"logoUri": "https://safe-transaction-assets.staging.5afe.dev/chains/1/currency_logo.png"
|
|
},
|
|
"transactionService": "https://api.5afe.dev/tx-service/eth",
|
|
"blockExplorerUriTemplate": {
|
|
"address": "https://etherscan.io/address/{{address}}",
|
|
"txHash": "https://etherscan.io/tx/{{txHash}}",
|
|
"api": "https://api.etherscan.io/v2/api?chainid=1&module={{module}}&action={{action}}&address={{address}}&apiKey={{apiKey}}"
|
|
},
|
|
"beaconChainExplorerUriTemplate": {
|
|
"publicKey": null
|
|
},
|
|
"disabledWallets": ["socialSigner", "trezor"],
|
|
"ensRegistryAddress": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
|
|
"balancesProvider": {
|
|
"chainName": "ethereum",
|
|
"enabled": true
|
|
},
|
|
"contractAddresses": {
|
|
"safeSingletonAddress": null,
|
|
"safeProxyFactoryAddress": null,
|
|
"multiSendAddress": null,
|
|
"multiSendCallOnlyAddress": null,
|
|
"fallbackHandlerAddress": null,
|
|
"signMessageLibAddress": null,
|
|
"createCallAddress": null,
|
|
"simulateTxAccessorAddress": null,
|
|
"safeWebAuthnSignerFactoryAddress": null
|
|
},
|
|
"features": [
|
|
"BRIDGE",
|
|
"COUNTERFACTUAL",
|
|
"CSV_TX_EXPORT",
|
|
"DEFAULT_TOKENLIST",
|
|
"DELETE_TX",
|
|
"DOMAIN_LOOKUP",
|
|
"EARN",
|
|
"EIP1271",
|
|
"EIP1559",
|
|
"ERC721",
|
|
"EURCV_BOOST",
|
|
"HYPERNATIVE",
|
|
"LENDING",
|
|
"MASS_PAYOUTS",
|
|
"MIXPANEL",
|
|
"MULTI_CHAIN_SAFE_ADD_NETWORK",
|
|
"MULTI_CHAIN_SAFE_CREATION",
|
|
"NATIVE_COW_SWAP_FEE_V2",
|
|
"NATIVE_SWAPS",
|
|
"NATIVE_SWAPS_COW",
|
|
"NATIVE_SWAPS_FEE_ENABLED",
|
|
"NATIVE_SWAPS_USE_COW_STAGING_SERVER",
|
|
"NATIVE_WALLETCONNECT",
|
|
"NESTED_SAFES",
|
|
"NEW_MOBILE_APP_AVAILABLE",
|
|
"PORTFOLIO_ENDPOINT",
|
|
"POSITIONS",
|
|
"PROPOSERS",
|
|
"PUSH_NOTIFICATIONS",
|
|
"RECOVERY",
|
|
"RISK_MITIGATION",
|
|
"SAFE_APPS",
|
|
"SAP_BANNER",
|
|
"SECURITY_HUB",
|
|
"SPACES",
|
|
"SPENDING_LIMIT",
|
|
"STAKE_TEASER",
|
|
"STAKING",
|
|
"STAKING_BANNER",
|
|
"TX_NOTES",
|
|
"TX_SIMULATION",
|
|
"ZODIAC_ROLES"
|
|
],
|
|
"gasPrice": [
|
|
{
|
|
"type": "oracle",
|
|
"uri": "https://api.etherscan.io/v2/api?chainid=1&module=gastracker&action=gasoracle&apikey=JNFAU892RF9TJWBU3EV7DJCPIWZY8KEMY1",
|
|
"gasParameter": "FastGasPrice",
|
|
"gweiFactor": "1000000000.000000000"
|
|
}
|
|
],
|
|
"publicRpcUri": {
|
|
"authentication": "NO_AUTHENTICATION",
|
|
"value": "https://cloudflare-eth.com"
|
|
},
|
|
"rpcUri": {
|
|
"authentication": "API_KEY_PATH",
|
|
"value": "https://mainnet.infura.io/v3/"
|
|
},
|
|
"safeAppsRpcUri": {
|
|
"authentication": "API_KEY_PATH",
|
|
"value": "https://mainnet.infura.io/v3/"
|
|
},
|
|
"shortName": "eth",
|
|
"theme": {
|
|
"textColor": "#ffffff",
|
|
"backgroundColor": "#627EEA"
|
|
},
|
|
"recommendedMasterCopyVersion": "1.4.1"
|
|
}
|