chore: scan delegation delegate address in trust middleware
Description
This PR extends the trust signals middleware to scan delegate addresses when processing delegation signatures (EIP-7710 Delegations).
Reason for the change: When a user signs a delegation, the delegate address is a critical security parameter—it determines who will have delegated authority over the user's account. Currently, the trust signals middleware scans verifying contracts and spender addresses (for permits), but does not scan the delegate address in delegation signatures. This leaves a gap in our security scanning coverage.
Improvement/solution:
- Extended
handleEthSignTypedDatain the trust signals middleware to detect delegation signatures (viaPRIMARY_TYPE_DELEGATION) and scan the delegate address using the existingscanAddressAndAddToCachemechanism - Exported
PRIMARY_TYPE_DELEGATIONconstant fromdelegation.tsto enable reuse across modules - Added comprehensive test coverage for the new functionality, including:
- Verifying both the verifying contract and delegate addresses are scanned
- Graceful error handling when delegate scanning fails
- Edge case handling when delegate address is not present
The implementation follows the existing patterns established for permit signature scanning.
Changelog
CHANGELOG entry: null
Manual testing steps
- Create a new permission and sign it.
- In the signing step delegate scan should be triggered.
Screenshots/Recordings
Before
After
Pre-merge author checklist
- [x] I've followed MetaMask Contributor Docs and MetaMask Extension Coding Standards.
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using JSDoc format if applicable
- [x] I’ve applied the right labels on the PR (see labeling guidelines). Not required for external contributors.
Pre-merge reviewer checklist
- [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
[!NOTE] Scan delegate addresses for delegation typed-data signatures and export PRIMARY_TYPE_DELEGATION, with comprehensive tests and error handling.
- Trust Signals Middleware:
- Scan
delegateaddress for EIP-712 delegation signatures (primaryType: "Delegation") alongside theverifyingContract.- Leverages
PRIMARY_TYPE_DELEGATIONfor detection and adds graceful error handling on delegate scan failures.- Transactions/Delegation:
- Export
PRIMARY_TYPE_DELEGATIONfromapp/scripts/lib/transaction/delegation.tsfor cross-module use.- Tests:
- Add tests to verify scanning of both
verifyingContractanddelegate, error handling on delegate scan failures, and no-scan whendelegateis absent.- Introduce
DELEGATEtest address constant.Written by Cursor Bugbot for commit 80403528581456031b2d522ea83ce9245cd6a359. This will update automatically on new commits. Configure here.
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.
Builds ready [8040352]
- builds: chrome, firefox
- builds (beta): chrome, firefox
- builds (flask): chrome, firefox
- builds (test): chrome, firefox
- builds (test-flask): chrome, firefox
- bundle size: Bundle Size Stats
- user-actions-benchmark: User Actions Stats
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
UI Startup Metrics (1261 ± 102 ms)
| Platform | BuildType | Page | Metric | Mean (ms) | Min (ms) | Max (ms) | Std Dev (ms) | P 75 (ms) | P 95 (ms) |
|---|---|---|---|---|---|---|---|---|---|
| Chrome | Browserify | Standard Home | uiStartup | 1261 | 1059 | 1536 | 102 | 1321 | 1428 |
| load | 1034 | 864 | 1290 | 89 | 1082 | 1218 | |||
| domContentLoaded | 1026 | 858 | 1283 | 86 | 1072 | 1200 | |||
| domInteractive | 25 | 15 | 117 | 20 | 20 | 82 | |||
| firstPaint | 509 | 78 | 1242 | 404 | 1001 | 1167 | |||
| backgroundConnect | 214 | 198 | 280 | 14 | 218 | 242 | |||
| firstReactRender | 49 | 31 | 235 | 24 | 54 | 81 | |||
| getState | 43 | 18 | 140 | 27 | 47 | 125 | |||
| initialActions | 1 | 0 | 4 | 1 | 1 | 2 | |||
| loadScripts | 820 | 660 | 1082 | 85 | 864 | 996 | |||
| setupStore | 13 | 6 | 29 | 5 | 16 | 23 | |||
| numNetworkReqs | 14 | 6 | 89 | 20 | 6 | 75 | |||
| Browserify | Power User Home | uiStartup | - | - | - | - | - | - | |
| load | - | - | - | - | - | - | |||
| domContentLoaded | - | - | - | - | - | - | |||
| domInteractive | - | - | - | - | - | - | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | - | - | - | - | - | - | |||
| firstReactRender | - | - | - | - | - | - | |||
| getState | - | - | - | - | - | - | |||
| initialActions | - | - | - | - | - | - | |||
| loadScripts | - | - | - | - | - | - | |||
| setupStore | - | - | - | - | - | - | |||
| numNetworkReqs | - | - | - | - | - | - | |||
| Webpack | Standard Home | uiStartup | 819 | 680 | 1230 | 94 | 871 | 954 | |
| load | 657 | 572 | 1020 | 87 | 705 | 796 | |||
| domContentLoaded | 651 | 569 | 1016 | 86 | 700 | 789 | |||
| domInteractive | 26 | 15 | 93 | 18 | 23 | 84 | |||
| firstPaint | 243 | 85 | 1009 | 175 | 229 | 647 | |||
| backgroundConnect | 11 | 6 | 80 | 9 | 12 | 28 | |||
| firstReactRender | 54 | 33 | 214 | 29 | 67 | 118 | |||
| getState | 28 | 14 | 63 | 11 | 37 | 47 | |||
| initialActions | 1 | 0 | 4 | 1 | 1 | 2 | |||
| loadScripts | 648 | 566 | 1014 | 85 | 696 | 780 | |||
| setupStore | 12 | 4 | 57 | 7 | 13 | 27 | |||
| numNetworkReqs | 13 | 6 | 79 | 19 | 6 | 68 | |||
| Webpack | Power User Home | uiStartup | 1425 | 1086 | 2053 | 199 | 1584 | 1744 | |
| load | 741 | 604 | 985 | 98 | 830 | 904 | |||
| domContentLoaded | 734 | 598 | 975 | 98 | 824 | 896 | |||
| domInteractive | 32 | 17 | 131 | 26 | 27 | 108 | |||
| firstPaint | 272 | 84 | 867 | 181 | 287 | 680 | |||
| backgroundConnect | 84 | 7 | 716 | 169 | 47 | 583 | |||
| firstReactRender | 51 | 40 | 72 | 6 | 54 | 64 | |||
| getState | 194 | 137 | 699 | 63 | 205 | 276 | |||
| initialActions | 1 | 0 | 3 | 1 | 1 | 2 | |||
| loadScripts | 730 | 596 | 973 | 97 | 817 | 894 | |||
| setupStore | 17 | 7 | 46 | 9 | 16 | 36 | |||
| numNetworkReqs | 72 | 56 | 214 | 25 | 67 | 135 | |||
| Firefox | Browserify | Standard Home | uiStartup | 1348 | 1072 | 2299 | 192 | 1418 | 1696 |
| load | 1086 | 907 | 2030 | 140 | 1143 | 1277 | |||
| domContentLoaded | 1086 | 907 | 2030 | 140 | 1143 | 1277 | |||
| domInteractive | 75 | 31 | 958 | 97 | 86 | 139 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 56 | 20 | 263 | 46 | 66 | 169 | |||
| firstReactRender | 39 | 29 | 67 | 8 | 39 | 60 | |||
| getState | 13 | 7 | 90 | 11 | 12 | 36 | |||
| initialActions | 1 | 0 | 2 | 1 | 2 | 2 | |||
| loadScripts | 1055 | 892 | 1928 | 128 | 1114 | 1205 | |||
| setupStore | 15 | 5 | 151 | 21 | 13 | 40 | |||
| numNetworkReqs | 15 | 6 | 82 | 21 | 8 | 76 | |||
| Browserify | Power User Home | uiStartup | 2638 | 1678 | 3402 | 516 | 3048 | 3311 | |
| load | 1642 | 936 | 2504 | 502 | 2124 | 2391 | |||
| domContentLoaded | 1641 | 936 | 2503 | 502 | 2122 | 2390 | |||
| domInteractive | 172 | 31 | 990 | 283 | 95 | 979 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 176 | 20 | 1187 | 205 | 185 | 467 | |||
| firstReactRender | 66 | 36 | 973 | 93 | 60 | 96 | |||
| getState | 122 | 65 | 346 | 45 | 138 | 219 | |||
| initialActions | 2 | 0 | 3 | 1 | 2 | 3 | |||
| loadScripts | 1552 | 921 | 2488 | 474 | 2009 | 2236 | |||
| setupStore | 43 | 4 | 467 | 73 | 43 | 223 | |||
| numNetworkReqs | 74 | 54 | 131 | 19 | 79 | 117 | |||
| Webpack | Standard Home | uiStartup | 1603 | 1300 | 2842 | 195 | 1711 | 1899 | |
| load | 1320 | 1112 | 2590 | 159 | 1382 | 1465 | |||
| domContentLoaded | 1320 | 1107 | 2590 | 159 | 1382 | 1464 | |||
| domInteractive | 78 | 28 | 231 | 40 | 106 | 144 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 57 | 22 | 204 | 36 | 66 | 149 | |||
| firstReactRender | 43 | 33 | 98 | 10 | 47 | 56 | |||
| getState | 17 | 8 | 114 | 18 | 14 | 60 | |||
| initialActions | 1 | 0 | 3 | 1 | 2 | 2 | |||
| loadScripts | 1290 | 1098 | 2569 | 158 | 1354 | 1433 | |||
| setupStore | 18 | 6 | 145 | 24 | 15 | 78 | |||
| numNetworkReqs | 15 | 6 | 79 | 20 | 8 | 72 | |||
| Webpack | Power User Home | uiStartup | 2830 | 1732 | 4455 | 571 | 3265 | 3592 | |
| load | 1926 | 1096 | 2816 | 464 | 2318 | 2624 | |||
| domContentLoaded | 1926 | 1096 | 2816 | 464 | 2318 | 2623 | |||
| domInteractive | 179 | 32 | 988 | 276 | 127 | 918 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 183 | 27 | 1162 | 233 | 196 | 887 | |||
| firstReactRender | 62 | 42 | 133 | 15 | 66 | 97 | |||
| getState | 139 | 67 | 895 | 92 | 161 | 231 | |||
| initialActions | 3 | 1 | 40 | 5 | 3 | 7 | |||
| loadScripts | 1830 | 1080 | 2714 | 444 | 2216 | 2504 | |||
| setupStore | 62 | 7 | 470 | 100 | 61 | 351 | |||
| numNetworkReqs | 71 | 47 | 146 | 25 | 65 | 125 |
📊 Page Load Benchmark Results
Current Commit: 8040352 | Date: 12/10/2025
📄 Localhost MetaMask Test Dapp
Samples: 100
Summary
- pageLoadTime-> current mean value: 1.03s (±39ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
- domContentLoaded-> current mean value: 719ms (±37ms) 🟢 | historical mean value: 721ms ⬇️ (historical data)
- firstContentfulPaint-> current mean value: 77ms (±14ms) 🟢 | historical mean value: 79ms ⬇️ (historical data)
📈 Detailed Results
| Metric | Mean | Std Dev | Min | Max | P95 | P99 |
|---|---|---|---|---|---|---|
| pageLoadTime | 1.03s | 39ms | 1.00s | 1.32s | 1.08s | 1.32s |
| domContentLoaded | 719ms | 37ms | 692ms | 990ms | 739ms | 990ms |
| firstPaint | 77ms | 14ms | 60ms | 200ms | 84ms | 200ms |
| firstContentfulPaint | 77ms | 14ms | 60ms | 200ms | 84ms | 200ms |
| largestContentfulPaint | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms |
Bundle size diffs [🚨 Warning! Bundle size has increased!]
- background: 3.08 KiB (0.06%)
- ui: -2.55 KiB (-0.03%)
- common: -739 Bytes (-0.01%)
Builds ready [8040352]
- builds: chrome, firefox
- builds (beta): chrome, firefox
- builds (flask): chrome, firefox
- builds (test): chrome, firefox
- builds (test-flask): chrome, firefox
- bundle size: Bundle Size Stats
- user-actions-benchmark: User Actions Stats
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
UI Startup Metrics (1261 ± 102 ms)
| Platform | BuildType | Page | Metric | Mean (ms) | Min (ms) | Max (ms) | Std Dev (ms) | P 75 (ms) | P 95 (ms) |
|---|---|---|---|---|---|---|---|---|---|
| Chrome | Browserify | Standard Home | uiStartup | 1261 | 1059 | 1536 | 102 | 1321 | 1428 |
| load | 1034 | 864 | 1290 | 89 | 1082 | 1218 | |||
| domContentLoaded | 1026 | 858 | 1283 | 86 | 1072 | 1200 | |||
| domInteractive | 25 | 15 | 117 | 20 | 20 | 82 | |||
| firstPaint | 509 | 78 | 1242 | 404 | 1001 | 1167 | |||
| backgroundConnect | 214 | 198 | 280 | 14 | 218 | 242 | |||
| firstReactRender | 49 | 31 | 235 | 24 | 54 | 81 | |||
| getState | 43 | 18 | 140 | 27 | 47 | 125 | |||
| initialActions | 1 | 0 | 4 | 1 | 1 | 2 | |||
| loadScripts | 820 | 660 | 1082 | 85 | 864 | 996 | |||
| setupStore | 13 | 6 | 29 | 5 | 16 | 23 | |||
| numNetworkReqs | 14 | 6 | 89 | 20 | 6 | 75 | |||
| Browserify | Power User Home | uiStartup | 1905 | 1637 | 2235 | 140 | 1981 | 2156 | |
| load | 1060 | 885 | 1335 | 119 | 1153 | 1264 | |||
| domContentLoaded | 1051 | 872 | 1317 | 119 | 1143 | 1257 | |||
| domInteractive | 29 | 17 | 125 | 22 | 25 | 89 | |||
| firstPaint | 533 | 100 | 1348 | 417 | 998 | 1231 | |||
| backgroundConnect | 256 | 198 | 677 | 105 | 238 | 567 | |||
| firstReactRender | 47 | 38 | 107 | 8 | 49 | 57 | |||
| getState | 186 | 137 | 353 | 31 | 199 | 244 | |||
| initialActions | 1 | 0 | 8 | 1 | 1 | 2 | |||
| loadScripts | 840 | 674 | 1119 | 118 | 936 | 1058 | |||
| setupStore | 15 | 7 | 64 | 8 | 15 | 35 | |||
| numNetworkReqs | 72 | 57 | 137 | 19 | 70 | 133 | |||
| Webpack | Standard Home | uiStartup | 819 | 680 | 1230 | 94 | 871 | 954 | |
| load | 657 | 572 | 1020 | 87 | 705 | 796 | |||
| domContentLoaded | 651 | 569 | 1016 | 86 | 700 | 789 | |||
| domInteractive | 26 | 15 | 93 | 18 | 23 | 84 | |||
| firstPaint | 243 | 85 | 1009 | 175 | 229 | 647 | |||
| backgroundConnect | 11 | 6 | 80 | 9 | 12 | 28 | |||
| firstReactRender | 54 | 33 | 214 | 29 | 67 | 118 | |||
| getState | 28 | 14 | 63 | 11 | 37 | 47 | |||
| initialActions | 1 | 0 | 4 | 1 | 1 | 2 | |||
| loadScripts | 648 | 566 | 1014 | 85 | 696 | 780 | |||
| setupStore | 12 | 4 | 57 | 7 | 13 | 27 | |||
| numNetworkReqs | 13 | 6 | 79 | 19 | 6 | 68 | |||
| Webpack | Power User Home | uiStartup | 1425 | 1086 | 2053 | 199 | 1584 | 1744 | |
| load | 741 | 604 | 985 | 98 | 830 | 904 | |||
| domContentLoaded | 734 | 598 | 975 | 98 | 824 | 896 | |||
| domInteractive | 32 | 17 | 131 | 26 | 27 | 108 | |||
| firstPaint | 272 | 84 | 867 | 181 | 287 | 680 | |||
| backgroundConnect | 84 | 7 | 716 | 169 | 47 | 583 | |||
| firstReactRender | 51 | 40 | 72 | 6 | 54 | 64 | |||
| getState | 194 | 137 | 699 | 63 | 205 | 276 | |||
| initialActions | 1 | 0 | 3 | 1 | 1 | 2 | |||
| loadScripts | 730 | 596 | 973 | 97 | 817 | 894 | |||
| setupStore | 17 | 7 | 46 | 9 | 16 | 36 | |||
| numNetworkReqs | 72 | 56 | 214 | 25 | 67 | 135 | |||
| Firefox | Browserify | Standard Home | uiStartup | 1348 | 1072 | 2299 | 192 | 1418 | 1696 |
| load | 1086 | 907 | 2030 | 140 | 1143 | 1277 | |||
| domContentLoaded | 1086 | 907 | 2030 | 140 | 1143 | 1277 | |||
| domInteractive | 75 | 31 | 958 | 97 | 86 | 139 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 56 | 20 | 263 | 46 | 66 | 169 | |||
| firstReactRender | 39 | 29 | 67 | 8 | 39 | 60 | |||
| getState | 13 | 7 | 90 | 11 | 12 | 36 | |||
| initialActions | 1 | 0 | 2 | 1 | 2 | 2 | |||
| loadScripts | 1055 | 892 | 1928 | 128 | 1114 | 1205 | |||
| setupStore | 15 | 5 | 151 | 21 | 13 | 40 | |||
| numNetworkReqs | 15 | 6 | 82 | 21 | 8 | 76 | |||
| Browserify | Power User Home | uiStartup | 2638 | 1678 | 3402 | 516 | 3048 | 3311 | |
| load | 1642 | 936 | 2504 | 502 | 2124 | 2391 | |||
| domContentLoaded | 1641 | 936 | 2503 | 502 | 2122 | 2390 | |||
| domInteractive | 172 | 31 | 990 | 283 | 95 | 979 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 176 | 20 | 1187 | 205 | 185 | 467 | |||
| firstReactRender | 66 | 36 | 973 | 93 | 60 | 96 | |||
| getState | 122 | 65 | 346 | 45 | 138 | 219 | |||
| initialActions | 2 | 0 | 3 | 1 | 2 | 3 | |||
| loadScripts | 1552 | 921 | 2488 | 474 | 2009 | 2236 | |||
| setupStore | 43 | 4 | 467 | 73 | 43 | 223 | |||
| numNetworkReqs | 74 | 54 | 131 | 19 | 79 | 117 | |||
| Webpack | Standard Home | uiStartup | 1603 | 1300 | 2842 | 195 | 1711 | 1899 | |
| load | 1320 | 1112 | 2590 | 159 | 1382 | 1465 | |||
| domContentLoaded | 1320 | 1107 | 2590 | 159 | 1382 | 1464 | |||
| domInteractive | 78 | 28 | 231 | 40 | 106 | 144 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 57 | 22 | 204 | 36 | 66 | 149 | |||
| firstReactRender | 43 | 33 | 98 | 10 | 47 | 56 | |||
| getState | 17 | 8 | 114 | 18 | 14 | 60 | |||
| initialActions | 1 | 0 | 3 | 1 | 2 | 2 | |||
| loadScripts | 1290 | 1098 | 2569 | 158 | 1354 | 1433 | |||
| setupStore | 18 | 6 | 145 | 24 | 15 | 78 | |||
| numNetworkReqs | 15 | 6 | 79 | 20 | 8 | 72 | |||
| Webpack | Power User Home | uiStartup | 2830 | 1732 | 4455 | 571 | 3265 | 3592 | |
| load | 1926 | 1096 | 2816 | 464 | 2318 | 2624 | |||
| domContentLoaded | 1926 | 1096 | 2816 | 464 | 2318 | 2623 | |||
| domInteractive | 179 | 32 | 988 | 276 | 127 | 918 | |||
| firstPaint | - | - | - | - | - | - | |||
| backgroundConnect | 183 | 27 | 1162 | 233 | 196 | 887 | |||
| firstReactRender | 62 | 42 | 133 | 15 | 66 | 97 | |||
| getState | 139 | 67 | 895 | 92 | 161 | 231 | |||
| initialActions | 3 | 1 | 40 | 5 | 3 | 7 | |||
| loadScripts | 1830 | 1080 | 2714 | 444 | 2216 | 2504 | |||
| setupStore | 62 | 7 | 470 | 100 | 61 | 351 | |||
| numNetworkReqs | 71 | 47 | 146 | 25 | 65 | 125 |
📊 Page Load Benchmark Results
Current Commit: 8040352 | Date: 12/10/2025
📄 Localhost MetaMask Test Dapp
Samples: 100
Summary
- pageLoadTime-> current mean value: 1.03s (±39ms) 🟡 | historical mean value: 1.03s ⬇️ (historical data)
- domContentLoaded-> current mean value: 719ms (±37ms) 🟢 | historical mean value: 722ms ⬇️ (historical data)
- firstContentfulPaint-> current mean value: 77ms (±14ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)
📈 Detailed Results
| Metric | Mean | Std Dev | Min | Max | P95 | P99 |
|---|---|---|---|---|---|---|
| pageLoadTime | 1.03s | 39ms | 1.00s | 1.32s | 1.08s | 1.32s |
| domContentLoaded | 719ms | 37ms | 692ms | 990ms | 739ms | 990ms |
| firstPaint | 77ms | 14ms | 60ms | 200ms | 84ms | 200ms |
| firstContentfulPaint | 77ms | 14ms | 60ms | 200ms | 84ms | 200ms |
| largestContentfulPaint | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms |
Bundle size diffs [🚨 Warning! Bundle size has increased!]
- background: 3.08 KiB (0.06%)
- ui: -2.55 KiB (-0.03%)
- common: -739 Bytes (-0.01%)