{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"47d43340-e5d8-4497-ba2c-8b9833e32cdd","kind":"skill:research-report","nodes":[{"acceptedSubmissionHash":"2e02b1acb37e79efde75a70b0d5f513b24ac6b9f4426a435286a92786f9e5412","dependsOn":[],"execution":{"network":true,"profile":"none","requires":["network"],"skillHash":"3ddca93330036359dd721585e58e67820336a0398b7927b3c89369d6134f30f6","skillId":"research-report","tools":[]},"key":"research_report","kind":"code","role":"implement","skillHash":"3ddca93330036359dd721585e58e67820336a0398b7927b3c89369d6134f30f6","skillId":"research-report","state":"accepted"}],"objective":"Compare Uniswap v4 hook permission patterns for IMD Sepolia launches. Focus on what is safe for the Identity MD factory (PoolManager.initialize called by factory, not by a pad).\n\nSources (public):\n- Uniswap v4 Hooks.sol permission bit layout / BaseHook patterns\n- Live Sepolia reference: BurnShareHook-style swap-path hooks vs hooks that use beforeInitialize\n- Document why beforeInitialize that gates on pad/sender fails factory launch (WrappedError / pad-gated pattern)\n- Recommend a default permission set for (A) no-op smoke hook, (B) fixed fee skim hook, (C) burn-share hook\n\nDeliverables (required):\n1) HOOK_PERMISSIONS.md — table of the 14 hook permissions with one-line when-to-use; call out beforeInitialize risk for IMD factory; three recommended permission sets A/B/C with rationale; attestation note: hook.constructorArgs must be PoolManager-only literals (no $pad/$token placeholders).\n2) HOOK_PERMISSIONS.json — { asOf, recommendations: { noop, feeSkim, burnShare: { permissions: string[] } }, factorySafeRules: string[] }\n\nSuccess = both files present, JSON parses, every permission in A/B/C is a real Hooks.Permissions name, and md recommendations match json. Do not deploy contracts. Do not invent live addresses; if citing Sepolia examples, label them as examples and prefer well-known PoolManager 0xE03A1074c86CFeDd5C142C4F04F1a1536e203543 on chainId 11155111.","parentJobId":null,"planHash":"069146d94374e398f369e543cc29d4e1cdf8544111a681d974ccc4ec33c153bb","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"47d43340-e5d8-4497-ba2c-8b9833e32cdd","publication":{"commit":null,"deliveredAt":null,"repoUrl":null},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51336","feedbackHash":"2474927206b77900c0e9fdaff5b51243998176b06c309fc7a9a195a3fcf3f32c","nodeKey":"research_report","submissionHash":"2e02b1acb37e79efde75a70b0d5f513b24ac6b9f4426a435286a92786f9e5412","tag1":"verification:structural","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"086a00832ab35207503996f488046030495a7dfbccb8e68908cae4c55c46dcec","state":"completed","submissions":[{"artifacts":[{"bytes":3891,"hash":"cbc714f289657754595ffdc713cd4e099d12e9a3ca777e6c2361e9f4eafc6c0e","mediaType":"text/markdown","name":"report","path":"artifacts/report.md"}],"attempt":1,"bundleHash":"5e46fba7d11f080c50d7b8621cbe7f0f09a4c9f5bd79958eba862520245570c0","device":"00d95fd75f8b224c","findings":[],"hash":"2e02b1acb37e79efde75a70b0d5f513b24ac6b9f4426a435286a92786f9e5412","nodeId":"100b77a0-c179-4799-84c3-a69e2df31165","outcome":"completed","summary":"I've written both deliverables, and the report is at `artifacts/report.md`. My local checks pass: the JSON parses, every recommended permission is a real `Hooks.Permissions` name, the flag bits are correct, and the recommendations in the `.md` match the JSON.\n\n**Recommended permission sets**\n\n| Set | Permissions | Address flag bits |\n|---|---|---|\n| (A) no-op smoke hook | `afterSwap` | `0x0040` |\n| (B) fixed fee skim hook | `afterSwap`, `afterSwapReturnDelta` | `0x0044` |\n| (C) burn-share hook | `afterSwap`, `afterSwapReturnDelta` | `0x0044` |\n\n- **(A)** can't have zero flags: without a dynamic fee, the pool fails to initialize.\n- **(B)** matches the permission set of OpenZeppelin's `BaseHookFee`.\n- **(C)** uses the same mechanism as (B). It should read which currency is the IMD token from the pool's key at swap time, not from constructor arguments.\n\n**Why `beforeInitialize` breaks factory launches** (from reading the v4-core source)\n- `PoolManager.initialize` passes its own caller as `sender`, and under the IMD factory that caller is the factory. So a hook that checks `sender == pad` always reverts.\n- The revert comes back as `WrappedError` (`0x90bfb865`), with the hook's function selector (`0xdc98354e`) and `HookCallFailed` (`0xa9e35b2f`). The real reason is nested inside, so tooling that only decodes the outer error shows a generic failure.\n- The whole launch transaction reverts. I recommend leaving both `beforeInitialize` and `afterInitialize` off.\n\n**Constructor arguments:** `hook.constructorArgs` must contain only the PoolManager address, never `$pad` or `$token`. The hook's address, and so its permission bits, is derived from its full deployment code including those arguments. A value filled in per launch changes the address and breaks the mined salt and the attestation.\n\n**Sources:** v4-core `Hooks.sol`, `PoolManager.sol` and `CustomRevert.sol`, plus OpenZeppelin uniswap-hooks `BaseHook` and `BaseHookFee`, all linked at fixed commits. The Sepolia PoolManager `0xE03A1074c86CFeDd5C142C4F04F1a1536e203543` (chainId 11155111) is confirmed on the Uniswap deployments page and has code on-chain. Uniswap's `v4-periphery` no longer has `BaseHook.sol` (the path returns 404), so I cited OpenZeppelin's version instead.\n\n**What's inference or unverified** (each claim is labelled as fact, inference or uncertain in the docs)\n- I found no public \"BurnShareHook\" deployment, so it is treated as a pattern and no hook addresses are cited.\n- The failure mode comes from reading the source, not from reproducing a failed launch on-chain. Nothing was deployed.\n- That the factory calls `initialize` is taken from the task, not verified.\n- Open questions:\n  - how the factory adds its first liquidity, which decides whether liquidity permissions could ever be safe;\n  - how the IMD attestation fills in `$pad`/`$token`;\n  - whether burns should apply to buys, sells or both, and where burned tokens go.\n\n`HOOK_PERMISSIONS.md` and `HOOK_PERMISSIONS.json` are committed in `9ad87e4`. Git had no identity configured, so the commit uses your email as author. `artifacts/` is gitignored, so `report.md` and a short `README.md` there are left untracked for upload. That means the README won't be in the commit either. No independent review has been done.","treeHash":"9dbf361697c355c82ffac26d727771bd2f5866fa","usage":{"cachedInputTokens":550409,"inputTokens":34,"model":"claude-opus-5-5","outputTokens":16235,"runtime":"claude","turns":19,"wallClockMs":173691}}],"verification":[{"checks":[],"detail":"paths and tree verified; no suite was run for this kind of work","evaluation":"structural","profile":"none","status":"accepted","submissionHash":"2e02b1acb37e79efde75a70b0d5f513b24ac6b9f4426a435286a92786f9e5412","verifiedTreeHash":"9dbf361697c355c82ffac26d727771bd2f5866fa","verifierVersion":"0.1.0+1b3bcb5e"}]}