{"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":"27391f0e-0419-4d15-a5d5-bb182f137bd9","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"f828db2395009952e3b9c3c71ed50fbe896105551018546952765fff815ae9a8","dependsOn":["build_contract_project","write_foundry_tests"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"6b037a7b6601e883cf8a906c1520c0624817d42d8310b65c2f43679204608af3","skillId":"adversarial-review","tools":[]},"key":"adversarial_review","kind":"code","role":"review","skillHash":"6b037a7b6601e883cf8a906c1520c0624817d42d8310b65c2f43679204608af3","skillId":"adversarial-review","state":"accepted"},{"acceptedSubmissionHash":"b8f2b0595ca2297b6690585c7dcbd343524e2f78746db062612440b81b7e5c9f","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"7c173f1c001bbb52b4997bf8737e1265cb9dadd9a2a7a87091082e899e62388b","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Build, test and adversarially review the chaintraits registry from the brief in this repository (README.md and the four documents it lists).","parentJobId":null,"planHash":"580d99b03dc367b2ff2f12272234b23f4b1298ce333c9edae099e013e296e1fd","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"27391f0e-0419-4d15-a5d5-bb182f137bd9","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":"51214","feedbackHash":"2a0a169ed8bbc4dcb0992c7b6225bd0275105ea5f028f70ce81ded5c7fc26d43","nodeKey":"adversarial_review","submissionHash":"f828db2395009952e3b9c3c71ed50fbe896105551018546952765fff815ae9a8","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51316","feedbackHash":"84c90ab1b9e073fc75a56bdd0205edc0cbceeb36fcfa2a1b44ed570fc35813b9","nodeKey":"build_contract_project","submissionHash":"b8f2b0595ca2297b6690585c7dcbd343524e2f78746db062612440b81b7e5c9f","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52159","feedbackHash":"4c25a2e8bf39c247ea4bf6d38ca82c598ae2e3ffd5a8221dc621c6d4c7b9c1c6","nodeKey":"write_foundry_tests","submissionHash":"7c173f1c001bbb52b4997bf8737e1265cb9dadd9a2a7a87091082e899e62388b","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"93c80c29c5435e7fd207a138c5ad2ac6b3bd8f2b5e7ee9ec249c4b92cbc32e21","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"875c2ccdd61a0c68b7d7330ce00380190190bc381f95067f8905acc0f81c0bf9","device":"6b37e4ab65246705","findings":[{"description":"INTEGRATION.md section 4 lists the signer check before the chainId check; _check tests a.chainId first. Only the diagnostic reason code differs (3 instead of 2) when both are wrong; no trait is ever marked. Either the document or the order could be aligned; the tests pin the implemented order.","line":566,"path":"src/Registry.sol","reproduction":"Attestation with a.chainId = 4663 and a signature from a key other than the attester, delivered to a pending request: expected (per INTEGRATION.md order) Missed(reason 2); actual Missed(reason 3). Nothing is stored in either case.","severity":"info","title":"Reason-code order: chainId is checked before the signer"},{"description":"nextSpecId is a uint16 starting at 10001; the checked increment reverts once it reaches 65535, after which registerSpec reverts for ever. At 1 IMD per registration this is an economic bound rather than a reachable path, and the registry is ownerless so no remedy exists short of a successor. Recorded so the limit is known.","line":642,"path":"src/Registry.sol","reproduction":"After 55,534 successful registerSpec calls, nextSpecId == 65535; the next call's `nextSpecId++` overflows and reverts (Panic 0x11). Expected per CATALOG.md section 5: ids from 10001 upward in registration order (no stated cap); actual: a permanent cap.","severity":"info","title":"registerSpec has a hard lifetime cap of 55,535 specs (uint16 id counter)"}],"hash":"7c173f1c001bbb52b4997bf8737e1265cb9dadd9a2a7a87091082e899e62388b","nodeId":"911fc4e6-14ca-4b60-958f-499754be4928","outcome":"completed","summary":"The suite is complete and green. Nothing further is needed from tools: the build passes, the hermetic run passes with the fork tests skipped, the fork tests pass against mainnet, the template check holds, and only allowed paths changed.\n\n## What I delivered\n\n**Four new files under `test/`**, building on the accepted suite without rewriting it:\n\n- `test/fork/Mainnet.fork.t.sol` fills the gap the README admitted. Eleven tests at pinned block 26,170,000, skipped unless `CHAINTRAITS_FORK_RPC` is set, read only via `vm.envOr`. They check the real Curator's views against the direct-read rules for the first, 1000th and last contributors, confirm a non-member reads `(0, false)`, confirm the real IDMD `balanceOf(0)` reverts while `hasTrait` still answers false, and confirm Intake v2's price, stipend and writer. The key one drives a real `requestWithFailure` through the mainnet Intake, then calls the real `complete` as the writer for a status-0 result and a status-2 failure, under the real stipend. All eleven passed on two public endpoints.\n- `test/Adversarial.t.sol` covers the failure paths the happy path never sends: a writer pairing one claimant's answer with another's request, every attestation field altered after signing (fuzzed), panel, window, expiry and answer boundaries (fuzzed), five non-recovering signature shapes including a high-s twin, maximal specs that must still compose and fit the body limit, the 64-address shared-fact envelope under a 180,000 stipend, a starved callback staying pending, re-entrancy through the token into every IMD-moving function, and `tokenURI` as a pure function of the claimant's facts.\n- `test/InvariantsExtended.t.sol` adds a fifteen-action random walk with ghost state: paid and pool-funded upgrades, true, false, tampered and failed completions, abandons, specs, shared facts and their application, donations and transfers. Its invariants state that a pair is marked exactly when the handler delivered a passing attestation, that the pool equals fees plus donations minus pool-funded requests, that specs never change, and that shared facts are bounded hashes.\n- `test/NOTES.md` maps each of the eleven invariants in CONCEPT.md to its tests and records the review observations.\n\n## Review outcome\n\nNo implementation defect needed a fix in `src/`. Two info-level observations are in `.imd-findings.json`: the chain-id check runs before the signer check, so the reason code differs from the document's order when both are wrong, and the spec id counter caps registrations at 55,535 for the contract's lifetime. Neither marks a trait or moves value.\n\n## Results\n\n| check | result |\n|---|---|\n| `forge build` | passes |\n| `forge test`, no network | 78 passed, 11 skipped, 0 failed |\n| fork suite with RPC | 11 passed |\n| `tools/gen_template.py --check` | passes |\n\nOne thing outside my write paths: the README still says fork tests are not delivered. That sentence is now stale, and the notes file says so.","treeHash":"79dcb050c9ec81032953c5881de0cd6185b9c2af","usage":{"cachedInputTokens":3211509,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":70941,"runtime":"claude","turns":40,"wallClockMs":1176890}},{"artifacts":[],"attempt":1,"bundleHash":"f28e3e4fc6f2df2c9f3ac6d8836a7430c5a9ecab3afcd99ed48b327916b5790a","device":"6b0a28df3d585600","findings":[],"hash":"b8f2b0595ca2297b6690585c7dcbd343524e2f78746db062612440b81b7e5c9f","nodeId":"47c21979-2b91-47c1-b69b-bbdeab8c7cd1","outcome":"completed","summary":"Everything is green and no protected file was touched. The work is complete.\n\n**Outcome.** The chaintraits registry is built, tested and documented. `forge build`, `forge test` (45 tests across 6 suites plus a stateful invariant run, no network, no ffi), `forge fmt --check`, `python3 tools/gen_template.py --check` and the generator's unit tests all pass with the committed `foundry.toml`.\n\n**What was delivered**\n- `src/Registry.sol`: ownerless ERC-721 + IERC4906, one card per wallet, live direct-read traits from the Curator and IDMD, oracle traits stored per (claimant, traitId) after every check of INTEGRATION.md section 4 in `onResult`, `onFailure`, `abandon`, `registerSpec`, shared facts, the sponsor pool, no immutables, no owner, no receive or fallback.\n- `src/Composer.sol`: the five templates, byte-exact bodies, the canonical question document and its keccak, the catalog as specs, spec guards, name table.\n- `src/Renderer.sol` + generated `src/TemplateData.sol`: compile-time template constant read by codecopy, splice loop, Base64 once, JSON/markup escaping.\n- `src/interfaces/{IIntake,IOracleConsumer,IIDMD}.sol`, `src/Types.sol`, `script/Deploy.s.sol`, adapted `tools/gen_template.py`, redrawn `template/card.svg`, goldens for three synthetic wallets, README section \"How to verify a card\".\n\n**Verified by tests.** All ten fixture bodies are byte-exact and all ten question hashes equal the plane's; the five served mainnet attestations recover the attester under their own domain only; the protocol's conformance vector digest matches; every miss reason code, the transition table, the stale-callback path, the pool rules, the tier monotonicity fuzz, the non-member rule, reentrancy, empty `immutableReferences`, identical runtime on two deployments, and the launch opcode scan. Worst-case `onResult` measured at 164,696 gas under the real 200,000 stipend.\n\n**Deviations, recorded in README.md with reasons**\n- The registry takes the renderer and the composer as a sixth and seventh constructor address instead of deploying them: embedding both creation codes pushed its init code past EIP-3860's limit. Three static deployments.\n- Composition, spec validation and the name table live in `Composer` because the registry alone exceeded EIP-170 by 17KB.\n- `verified()` returns the window from the trait's rule rather than storage, saving a cold slot in the callback.\n- Offsets are embedded as ASCII hex so no data byte reads as a forbidden opcode.\n- Fork tests were not delivered (the verifier has no network), and the THE LIST rasterizer script was removed.\n\n**Open items for the requester.** The product name, symbol and final trait names are still pending in the brief; the launch is three contracts, with the helper addresses filled by backward references in the manifest.","treeHash":"fc65e26496f1eb4f01939e6294cb26622a41d9a5","usage":{"cachedInputTokens":6799757,"inputTokens":1058,"model":"claude-fable-5-1","outputTokens":126324,"runtime":"claude","turns":66,"wallClockMs":1869046}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dd2ee4882a1be950","findings":[{"citation":"resolved","description":"cardOf() fills one slot per family with the highest true id, which is correct for the monotone tier families (2xx-5xx) but CATALOG.md section 3 states that family 11 is not a tier family: 1101-1104 are four distinct one-wallet ordinals and 1105 (First thousand, 1,000 wallets) is a window fact, not a tier above them. Every wallet that holds 1101 or 1102 also qualifies for 1105 (index 1 and 1000 are inside W_FIRST1000), so once both are verified the card's 'Ordinal' row in the SVG and the 'Ordinal' JSON attribute both print 1105 and the unique #1 / #1000 ordinal is no longer visible on the collectible. hasTrait and the JSON 'traits' list stay correct; the defect is display-only, which is why it is low. The renderer has no slot for a second ordinal value, so the fix is a scope decision (prefer the lowest id in family 11, or render family 11 as a list), not a one-liner.","line":221,"path":"src/Registry.sol","reproduction":"mint(alice); upgrade and deliver passing attestations for 1101 and 1105 for alice. Expected: the card surfaces Ordinal #1 (the rarer, unique trait). Actual: registry.cardOf(id).top[10] == 1105; tokenURI(id) decodes to attributes [...{\"trait_type\":\"Ordinal\",\"value\":\"1105\"}...] and the SVG Ordinal row reads 1105, while \"traits\":[1101,1105]. Reproduced in a scratch test (test_probe_ordinalCollapse): top[10] logged as 1105.","severity":"low","snippet":"            c.top[fam - 1] = id; // ids ascend, so the last of a family is its highest tier","title":"Card collapses the non-tier Ordinal family to its highest id, hiding Ordinal #1/#1000 behind First thousand"},{"citation":"resolved","description":"The composer hard-codes the question's chain as 1 in both the body ('\"chainId\": 1', Composer.sol:478) and the canonical document (Composer.sol:518), because every catalog question is about Ethereum mainnet. The attestation's chainId field is, per the protocol reference, 'the chain the question is about', so the plane signs chainId 1 regardless of where the consumer lives; the consumer's chain is bound separately through the EIP-712 domain, which the registry already computes from block.chainid. Comparing a.chainId with block.chainid therefore only passes on mainnet. On Sepolia (11155111), where CATALOG.md section 8 says the first real request from the registry is planned, every correctly signed answer is recorded as Missed(reason 3), the pending pair is cleared and 0.5 TestIMD is spent per attempt; nothing can ever be verified there. INTEGRATION.md check 2 does say 'a.chainId == block.chainid', so on mainnet this is exactly the requested behaviour; flagged low as a scope question for the rehearsal (comparing a.chainId with the question's chain, 1, would keep the mainnet behaviour and fix the rehearsal, but changes the brief's wording).","line":566,"path":"src/Registry.sol","reproduction":"vm.chainId(11155111); deploy Registry with the same arguments; alice upgrade([701]); build the attestation the plane would issue for that pending record (chainId 1, the pending questionHash, window B_H24..B_END, panel 5/3/3, answer uint256 1) and sign it with the attester key under the registry's own domain on 11155111; deliver via Intake.complete. Expected: trait verified. Actual: Missed(rid, 701, 3) emitted, hasTrait(alice, 701) == false, pendingOf cleared, price spent. Reproduced in a scratch test (test_probe_sepoliaChainIdMiss); the body sent carries \"chainId\": 1.","severity":"low","snippet":"        if (a.chainId != block.chainid) return 3;","title":"chainId check compares the question's chain with the consumer's chain, so the Sepolia rehearsal CATALOG section 8 plans can never verify a trait"},{"citation":"resolved","description":"validateSpec only forbids a stray fixedVal for kinds 3 to 5. For kinds 1 and 2 it allows fixedArg == \"\" together with fixedVal != 0. The composer builds the second-filter clause only when fixedArg is non-empty (Composer.sol:272-274), so the question sent to the plane has no filter, while the spec stored immutably and printed in every card's oracle metadata (Renderer._one: \"fixedArg\":\"\",\"fixedVal\":7) advertises a filter value. CATALOG.md section 5 defines fixedVal as the optional second indexed filter with 'empty string = none', and CONCEPT.md section 5 promises that the metadata carries the parameters a third party needs to rerun the recipe; a rerunner reading fixedVal 7 cannot tell which argument it applied to. No funds or verification logic are affected; the spec is simply inconsistent for ever. The guard should be symmetric: fixedArg empty implies fixedVal == 0.","line":182,"path":"src/Composer.sol","reproduction":"Spec s = t1Spec(0xCAFE, \"Odd\"); s.fixedArg = \"\"; s.fixedVal = 7; registry.registerSpec(s). Expected: revert BadSpec(\"fixedArg\"). Actual: returns id 10001; composeBody(10001, alice) has no 'and whose indexed ... argument equals' clause; specOf(10001).fixedVal == 7 and the card's oracle metadata prints \"fixedArg\":\"\",\"fixedVal\":7. Reproduced in a scratch test (test_probe_fixedValWithoutFixedArg).","severity":"low","snippet":"        if (s.kind > 2 && (fixedArg.length != 0 || s.fixedVal != 0)) revert BadSpec(\"fixedArg\");","title":"registerSpec accepts a T1/T2 spec with fixedVal set but fixedArg empty, so stored metadata advertises a filter value the question never applies"},{"citation":"resolved","description":"This implements CATALOG.md section 4 and INTEGRATION.md check 3 exactly, so it is not a defect against the requested design. It is recorded because the protocol reference delivered with this task (OracleAttestation.Attestation, field 'agreed') states that for chain evidence agreed can be below quorum 'when members who ran one recipe split and the deployer's own rerun settled which of their answers was whole', and that reference wins over the brief on protocol facts. Every such attestation is a reason-5 miss: the pair is cleared, the price is spent, and the claimant (or the pool, via poolUsed) pays again. The five vendored attestations all carry agreed >= quorum, so no live evidence shows this happening; it is a liveness exposure for the entrant to decide on, not something to change without a brief update.","line":571,"path":"src/Registry.sol","reproduction":"ask(alice, 701); a = attestationFor(rid, word(1)); a.panelSize = 5; a.quorum = 3; a.agreed = 2; deliver(rid, a). Actual and designed: Missed(rid, 701, 5), hasTrait false, pending cleared, 0.5 IMD spent. test_fuzz_panelAndQuorumBoundaries pins this behaviour.","severity":"info","snippet":"        if (a.agreed < a.quorum || a.quorum < quorum || a.panelSize < panelSize) return 5;","title":"agreed >= quorum is required for chain evidence, which the protocol reference says the plane may sign below quorum after the deployer's rerun"}],"hash":"f828db2395009952e3b9c3c71ed50fbe896105551018546952765fff815ae9a8","nodeId":"2da6dacd-2b89-40b2-8626-5ebcbac60231","outcome":"completed","summary":"The findings file is in place and valid JSON (it is excluded by the harness's own `.git/info/exclude`, which is expected), my scratch tests are removed, and the working tree is otherwise clean.\n\n**Summary of the review**\n\nThe registry holds up well against CONCEPT.md section 6, INTEGRATION.md section 4 and CATALOG.md. I found no high or medium defect. The findings file holds three low findings and one info observation, each with a reproduction, plus a coverage row for all 16 entry points and five invariants.\n\nFindings, ranked:\n\n1. **Low, `src/Registry.sol:221`.** The card collapses the Ordinal family to its highest id. A wallet verified for 1101 (Ordinal #1) and 1105 (First thousand) renders \"Ordinal\" as 1105 in both the SVG and the JSON attribute, hiding the unique trait. CATALOG says family 11 is not a tier family. Display only.\n2. **Low, `src/Registry.sol:566`.** The callback compares the attestation's chainId with `block.chainid`, while the body pins the question to chain 1. On the Sepolia rehearsal that CATALOG section 8 plans, every correct attestation is a reason-3 miss and the price is spent. Mainnet is unaffected, and the brief's wording asks for this check, so it is a scope question.\n3. **Low, `src/Composer.sol:182`.** A T1/T2 spec with empty `fixedArg` but nonzero `fixedVal` registers. The question applies no filter, but the immutable metadata prints a filter value, so a third party cannot rerun the recipe from the card.\n4. **Info, `src/Registry.sol:571`.** The `agreed >= quorum` rule follows the brief, but the protocol reference says chain-evidence attestations may carry `agreed < quorum` after the deployer's rerun. Such answers are a reason-5 miss with the price spent. A liveness decision for the entrant, not a code change.\n\nWhat I checked and found correct: attestation replay and consumer spoofing (five vendored mainnet signatures and the protocol vector), questionHash binding across claimants and traits, `onFailure`, pending-slot griefing, both pool paths and `poolUsed`, IMD reentrancy, tier monotonicity, claimant-vs-holder under transfer, spec guards and JSON/SVG escaping. Callback gas was measured cold through the mock's real stipend call: the heaviest path, a community T3 shared fact with 64 entries, needs 170,238 gas, under the 200,000 stipend.","treeHash":null,"usage":{"cachedInputTokens":3961005,"inputTokens":674,"model":"claude-fable-5-1","outputTokens":64577,"runtime":"claude","turns":36,"wallClockMs":972602}}],"verification":[{"checks":[{"durationMs":10512,"exitCode":0,"name":"build","output":"Compiling 71 files with Solc 0.8.24\nSolc 0.8.24 finished in 10.10s\nCompiler run successful!\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Renderer.sol:63:43\n   │\n63 │                 mcopy(add(add(out, 0x20), off), add(add(tpl, 0x20), start), len)\n   │                                           ━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Renderer.sol:171:21\n    │\n171 │                 out[o++] = \"\\\\\";\n    │                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Renderer.sol:162:42\n    │\n162 │             if (ch == '\"' || ch == \"\\\\\") extra += 1;\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/Registry.sol:58:38\n   │\n58 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:187:22\n    │\n187 │         deployedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n    ╭▸ src/Registry.sol:201:9\n    │\n201 │         _mint(msg.sender, tokenId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:200:34\n    │\n200 │         mintedAtBlock[tokenId] = uint64(block.number);\n    │                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:238:46\n    │\n238 │             if (c.traits[i] >= 701) c.oracle[k++] = _meta(claimant, c.traits[i]);\n    │                                              ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:233:37\n    │\n233 │             if (c.traits[i] >= 701) n++;\n    │                                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:398:16\n    │\n398 │         return composer.catalogSpec(traitId, address(curator));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:394:30\n    │\n394 │             if (s.kind == 0) revert NotAnOracleTrait(traitId);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:397:78\n    │\n397 │         if (!_isCatalogChain(traitId) && traitId != 1201 && traitId != 1301) revert NotAnOracleTrait(traitId);\n    │                                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:324:47\n    │\n324 │             if (hasTrait(wallet, all[i])) tmp[n++] = all[i];\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:271:43\n    │\n271 │             (uint256 hour, bool joined) = curator.firstHourOf(wallet);\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:277:25\n    │\n277 │             uint256 n = curator.txCountOf(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:281:25\n    │\n281 │             uint256 w = curator.contributedBy(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:285:25\n    │\n285 │             uint256 p = curator.pointsOf(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:288:36\n    │\n288 │         if (traitId == 601) return idmd.balanceOf(wallet) >= 1;\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:169:43\n    │\n169 │                 if (item[i] != prefix[i]) revert BadSpec(\"item\");\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:212:22\n    │\n212 │             if (!ok) revert BadSpec(\"name\");\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:250:61\n    │\n250 │             if (bytes(q.values[i]).length > MAX_DEFINITION) revert DefinitionTooLong(bytes(q.values[i]).length);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `pendingOf` is updated\n    ╭▸ src/Registry.sol:473:21\n    │\n473 │           requestId = intake.requestWithFailure(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n474 │ ┃             ACTION,\n475 │ ┃             body,\n476 │ ┃             IIntake.Callback(address(this), this.onResult.selector),\n    ‡ ┃\n479 │ ┃             price\n480 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Composer.sol:538:13\n    │\n538 │             n++;\n    │             ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:408:16\n    │\n408 │         return composer.compose(s, claimant, address(this), traitId == 1301, address(curator));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:473:21\n    │\n473 │           requestId = intake.requestWithFailure(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n474 │ ┃             ACTION,\n475 │ ┃             body,\n476 │ ┃             IIntake.Callback(address(this), this.onResult.selector),\n    ‡ ┃\n479 │ ┃             price\n480 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:484:9\n    │\n484 │         emit TraitRequested(claimant, traitId, requestId, qh);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:426:46\n    │\n426 │             if (_isDirect(id) || id == 1201) revert NotAnOracleTrait(id);\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:429:32\n    │\n429 │                 if (kind == 0) revert NotAnOracleTrait(id);\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:430:32\n    │\n430 │                 if (kind == 3) revert NotASharedFact(id);\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:432:17\n    │\n432 │                 revert NotAnOracleTrait(id);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:465:62\n    │\n465 │             if (_verified[claimant][traitId].requestId != 0) revert AlreadyVerified(claimant, traitId);\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:466:52\n    │\n466 │             if (pendingOf[claimant][traitId] != 0) revert AlreadyPending(claimant, traitId);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:468:50\n    │\n468 │             if (_shared[traitId].requestId != 0) revert FactAlreadyStored(traitId);\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:469:46\n    │\n469 │             if (sharedPending[traitId] != 0) revert AlreadyPending(claimant, traitId);\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:442:13\n    │\n442 │         if (block.timestamp < uint256(p.requestedAt) + ABANDON_AFTER) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:481:58\n    │\n481 │         _pending[requestId] = Pending(claimant, traitId, uint64(block.timestamp), qh);\n    │                                                          ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:513:13\n    │\n513 │             emit Missed(requestId, p.traitId, reason);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:519:13\n    │\n519 │             emit SharedFactStored(p.traitId, requestId, n);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:606:9\n    │\n606 │         emit Verified(claimant, traitId, requestId, oracleRequestId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:608:27\n    │\n608 │         if (tokenId != 0) emit MetadataUpdate(tokenId);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:573:13\n    │\n573 │         if (block.timestamp > a.expiresAt || a.issuedAt > block.timestamp + ISSUED_AT_TOLERANCE) return 7;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:573:46\n    │\n573 │         if (block.timestamp > a.expiresAt || a.issuedAt > block.timestamp + ISSUED_AT_TOLERANCE) return 7;\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:673:14\n    │\n673 │         if (!found) revert NotInList();\n    │              ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:734:9\n    │\n734 │         emit PoolSpent(msg.sender, traitId, requestId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:730:40\n    │\n730 │         if (!_isCatalogChain(traitId)) revert NotACatalogChainTrait(traitId);\n    │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:731:44\n    │\n731 │         if (poolUsed[msg.sender][traitId]) revert PoolAlreadyUsed(msg.sender, traitId);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:720:13\n    │\n720 │         if (block.timestamp < uint256(deployedAt) + POOL_OPENS_AFTER) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/Registry.sol:721:27\n    │\n721 │         (, bool joined) = curator.firstHourOf(msg.sender);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Adversarial.t.sol:446:17\n    │\n446 │         vm.warp(block.timestamp + 14 days);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Adversarial.t.sol:666:17\n    │\n666 │         vm.warp(block.timestamp + 1 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.chainid` may be reused across `vm.chainId`\n    ╭▸ test/Attestations.t.sol:133:17\n    │\n111 │             vm.chainId(4663);\n    │             ──────────────── `vm.chainId` changes this environment here\n    ‡\n133 │                 block.chainid,\n    │                 ━━━━━━━━━━━━━\n    │\n    ├ help: capture it with `vm.getChainId()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.chainid` may be reused across `vm.chainId`\n    ╭▸ test/Attestations.t.sol:133:17\n    │\n113 │             vm.chainId(1);\n    │             ───────────── `vm.chainId` changes this environment here\n    ‡\n133 │                 block.chainid,\n    │                 ━━━━━━━━━━━━━\n    │\n    ├ help: capture it with `vm.getChainId()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/Registry.t.sol:24:52\n   │\n24 │         assertEq(registry.mintedAtBlock(1), uint64(block.number));\n   │                                                    ━━━━━━━━━━━━\n   ‡\n31 │         vm.roll(block.number + 10);\n   │         ────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/Registry.t.sol:31:17\n   │\n31 │         vm.roll(block.number + 10);\n   │         ────────━━━━━━━━━━━━────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Registry.t.sol:395:17\n    │\n395 │         vm.warp(block.timestamp + 14 days - 1);\n    │         ────────━━━━━━━━━━━━━━━─────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Registry.t.sol:398:17\n    │\n398 │         vm.warp(block.timestamp + 1);\n    │         ────────━━━━━━━━━━━━━━━───── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":12827,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/fork/Mainnet.fork.t.sol:MainnetForkTest\n[SKIP] test_fork_attestationSignedForAnotherConsumerMissesOnTheRealIntake() (gas: 0)\n[SKIP] test_fork_curatorIsSettledWithTheBriefsConstants() (gas: 0)\n[SKIP] test_fork_firstContributorIsAnHourZeroEarlyBird() (gas: 0)\n[SKIP] test_fork_intakeV2SellsTheActionAsTheBriefRecords() (gas: 0)\n[SKIP] test_fork_lastContributorIsNoEarlyBird() (gas: 0)\n[SKIP] test_fork_memberMintsAndRendersAgainstTheRealCurator() (gas: 0)\n[SKIP] test_fork_nonMemberReadsZeroFalseAndHasNoCuratorTrait() (gas: 0)\n[SKIP] test_fork_operatorTraitReadsTheRealCollectionAndGuardsZero() (gas: 0)\n[SKIP] test_fork_pinnedBlockIsTheOneRecorded() (gas: 0)\n[SKIP] test_fork_thousandthContributorJoinedInsideTheFirstThousandWindow() (gas: 0)\n[SKIP] test_fork_upgradeThroughTheRealIntakeThenCompleteFromTheWriter() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 625.46µs (787.00µs CPU time)\n\nRan 3 tests for test/Attestations.t.sol:AttestationsTest\n[PASS] test_allFiveRecoverTheAttesterUnderTheirOwnDomainOnly() (gas: 2068691)\n[PASS] test_loaderRejectsUnknownAnswerTypeNames() (gas: 4845)\n[PASS] test_protocolVectorDigestAndSelector() (gas: 564871)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 6.83ms (7.36ms CPU time)\n\nRan 6 tests for test/Templates.t.sol:TemplatesTest\n[PASS] test_allTenBodiesAreByteExact() (gas: 1448401)\n[PASS] test_allTenQuestionHashesEqualThePlanes() (gas: 2176865)\n[PASS] test_bodyIsDeterministicInClaimantAndDiffersAcrossClaimants() (gas: 460653)\n[PASS] test_directAndUnknownIdsHaveNoBody() (gas: 60775)\n[PASS] test_hexMinAndCatalogWindows() (gas: 147209)\n[PASS] test_traitNamesAndClasses() (gas: 112609)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 19.42ms (16.68ms CPU time)\n\nRan 5 tests for test/Goldens.t.sol:GoldensTest\n[PASS] test_escapeJsonNeutralisesMarkup() (gas: 42667)\n[PASS] test_goldenSyntheticDirect() (gas: 2734613)\n[PASS] test_goldenSyntheticOracle() (gas: 7323662)\n[PASS] test_goldenSyntheticWidthThroughTheRenderer() (gas: 2739727)\n[PASS] test_templateArtifactsMatchTheCompiledConstants() (gas: 520257)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 88.46ms (23.31ms CPU time)\n\nRan 25 tests for test/Registry.t.sol:RegistryTest\n[PASS] test_abandonOnlyAfterFourteenDaysAndStaleCallbackLeavesSuccessor() (gas: 3262840)\n[PASS] test_anyoneReadsAnyWalletAndNothingUsesTxOrigin() (gas: 1145515)\n[PASS] test_attestationForAnotherConsumerOrChainIsNeverAccepted() (gas: 3187050)\n[PASS] test_callbacksRejectEveryoneButTheIntake() (gas: 1629427)\n[PASS] test_claimSponsoredRules() (gas: 5245444)\n[PASS] test_directTraitsAreLiveAndNeedNoCard() (gas: 478454)\n[PASS] test_fuzz_tiersAreMonotone(uint8,bool,uint32,uint128,uint32,uint8) (runs: 256, μ: 534765, ~: 529051)\n[PASS] test_malformedEnvelopeIsNotDeliveredAndStaysPending() (gas: 1538011)\n[PASS] test_mintOncePerWalletAndTransfersKeepClaimant() (gas: 956553)\n[PASS] test_mintWithoutFeeReverts() (gas: 47096)\n[PASS] test_missReasons() (gas: 29342783)\n[PASS] test_noReceiveOrFallback() (gas: 57797)\n[PASS] test_nonMemberIsNeverAnEarlyBird() (gas: 147936)\n[PASS] test_onFailureClearsAndAllowsRetry() (gas: 2982204)\n[PASS] test_onResultGasWorstCase() (gas: 2318564)\nLogs:\n  onResult worst-case gas: 164696\n\n[PASS] test_poolIsTheBalanceAndOnlyLeavesThroughSponsoredRequests() (gas: 5220214)\n[PASS] test_reentrantTokenCannotReenterMint() (gas: 1166283)\n[PASS] test_registerSpecAssignsSequentialIdsAndIsImmutable() (gas: 1211834)\n[PASS] test_sharedFactBadEnvelopeIsAMissAndCanBeRequestedAgain() (gas: 6891818)\n[PASS] test_sharedFactFlow() (gas: 2454932)\n[PASS] test_specGuards() (gas: 1333134)\n[PASS] test_supportsERC4906AndERC721() (gas: 25952)\n[PASS] test_upgradeGuards() (gas: 6031335)\n[PASS] test_upgradeHappyPathMarksTraitAndRefreshesCard() (gas: 2513234)\n[PASS] test_upgradeWithoutCardAttachesToClaimant() (gas: 1871748)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 184.67ms (237.07ms CPU time)\n\nRan 5 tests for test/Artifacts.t.sol:ArtifactsTest\n[PASS] test_constructorRejectsZeroAddressesAndStoresTheRest() (gas: 5746)\n[PASS] test_deployScriptUsesTheFiveStaticAddresses() (gas: 24671877)\n[PASS] test_noForbiddenOpcodesInRuntime() (gas: 37120714)\n[PASS] test_noImmutableReferencesInAnyArtifact() (gas: 63339763)\n[PASS] test_twoDeploymentsHaveIdenticalRuntimeCode() (gas: 549784)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 199.93ms (151.60ms CPU time)\n\nRan 32 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] test_abandonedPoolRequestKeepsPoolUsedAndLateCallbackIsIgnored() (gas: 1715875)\n[PASS] test_abandonedSharedFactCanBeRequestedAgainAndTheLateAnswerIsIgnored() (gas: 3031513)\n[PASS] test_attestationForAnotherClaimantIsAMissForThisRequest() (gas: 3214358)\n[PASS] test_attestationForAnotherTraitWithTheSameWindowIsAMiss() (gas: 3217337)\n[PASS] test_callbackStarvedOfGasIsNotDeliveredAndStaysPending() (gas: 1669769)\n[PASS] test_cardShowsAtMostThirtyTwoCommunityIdsAndCountsThemAll() (gas: 73826174)\n[PASS] test_claimSponsoredWhilePendingOrVerifiedReverts() (gas: 2041167)\n[PASS] test_communityT3SpecIsASharedFactWithItsOwnHead() (gas: 2394343)\n[PASS] test_everyTemplateVerifiesUnderTheStipendWithACard() (gas: 11632466)\n[PASS] test_expiryAtTheExactSecondStillPassesAndOneLaterDoesNot() (gas: 3211680)\n[PASS] test_fuzz_anyFieldAlteredAfterSigningIsASignatureMiss(uint8,uint256) (runs: 512, μ: 1629973, ~: 1631178)\nLogs:\n  Bound result 5\n\n[PASS] test_fuzz_applySharedFactOnlyWithinTheHead(uint8,uint8) (runs: 256, μ: 1752767, ~: 1737221)\nLogs:\n  Bound result 57\n  Bound result 28\n\n[PASS] test_fuzz_boolAnswerMustBeExactlyZeroOrOne(uint256) (runs: 512, μ: 2052618, ~: 2052318)\n[PASS] test_fuzz_countAnswerAgainstTheThreshold(uint256,bytes1,bool) (runs: 512, μ: 1636634, ~: 1615032)\n[PASS] test_fuzz_expiryAndClockSkewBoundaries(uint64,uint64) (runs: 512, μ: 1626822, ~: 1617978)\n[PASS] test_fuzz_hasTraitAndTraitsOfNeverRevert(address,uint16,uint8,bool,uint8) (runs: 512, μ: 262838, ~: 272730)\n[PASS] test_fuzz_maximalSpecRegistersComposesAndFitsTheBody(uint8,uint256,uint256) (runs: 64, μ: 2483911, ~: 2702778)\nLogs:\n  Bound result 2\n  Bound result 9\n\n[PASS] test_fuzz_panelAndQuorumBoundaries(uint16,uint16,uint16) (runs: 512, μ: 1630723, ~: 1617129)\n[PASS] test_fuzz_panelTraitNeedsElevenAndSeven(uint16,uint16,uint16) (runs: 512, μ: 2059096, ~: 2046111)\n[PASS] test_fuzz_specBodyIsDeterministicAndClaimantBound(address,address) (runs: 256, μ: 856325, ~: 856325)\n[PASS] test_fuzz_upgradeChargesExactlyKTimesPriceAndLeavesThePoolAlone(uint8,uint256) (runs: 256, μ: 5283249, ~: 4772829)\nLogs:\n  Bound result 3\n  Bound result 12780012061501423616\n\n[PASS] test_fuzz_upgradeRejectsEveryIdThatIsNotAnOracleTrait(uint16) (runs: 256, μ: 209691, ~: 209260)\n[PASS] test_fuzz_windowMustEqualTheCanonicalOne(uint64,uint64) (runs: 512, μ: 1617535, ~: 1617539)\n[PASS] test_onFailureRecordsWhatItIsToldAndStoresNothing() (gas: 3062351)\n[PASS] test_questionHashIsBoundToTheClaimantAndTheTrait() (gas: 684725)\n[PASS] test_reentrantTokenCannotReenterAnyIMDMovingFunction() (gas: 1988500)\n[PASS] test_sharedFactWorstCaseEnvelopeUnderTheStipend() (gas: 3939843)\n[PASS] test_signatureShapesThatDoNotRecover() (gas: 7707197)\n[PASS] test_tokenURIDependsOnlyOnTheClaimantsFacts() (gas: 8117626)\n[PASS] test_traitClassForEveryCatalogIdAndRevertsForUnknown() (gas: 703515)\n[PASS] test_upgradeSponsoredDrawsAllNineAndRefusesDuplicates() (gas: 12968649)\n[PASS] test_verifiedWindowIsTheCanonicalWindowForEveryOracleId() (gas: 16339333)\nSuite result: ok. 32 passed; 0 failed; 0 skipped; finished in 199.97ms (2.23s CPU time)\n\nRan 1 test for test/Invariants.t.sol:InvariantsTest\n[PASS]\nInvariantsTest invariants:\n[PASS] invariant_oneCardPerClaimantWithImmutableClaimant\n[PASS] invariant_poolOnlyLeavesThroughSponsoredRequests\n InvariantsTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭----------+-------------------+-------+---------+----------╮\n| Contract | Selector          | Calls | Reverts | Discards |\n+===========================================================+\n| Handler  | claimSponsored    | 3288  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | mintCard          | 3241  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | sponsor           | 3265  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | transfer          | 3320  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | upgradeAndDeliver | 3270  | 0       | 0        |\n╰----------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 903502693030451188\n  Bound result 1342378557739861183\n  Bound result 1727215418224039337\n  Bound result 457562073506117312\n  Bound result 185942811969039834\n  Bound result 1679408205130278012\n  Bound result 4723\n  Bound result 1943\n  Bound result 1385905244108341548\n  Bound result 1745468672485651682\n  Bound result 760879061971915136\n  Bound result 668968475689869459\n  Bound result 1371783871031994229\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.26s (5.26s CPU time)\n\nRan 1 test for test/InvariantsExtended.t.sol:InvariantsExtendedTest\n[PASS]\nInvariantsExtendedTest invariants:\n[PASS] invariant_markedExactlyWhenAPassingAttestationWasDelivered\n[PASS] invariant_oneCardPerClaimant\n[PASS] invariant_poolIsFeesPlusDonationsMinusSponsoredRequests\n[PASS] invariant_sharedFactsAreHashesStoredOnlyOnDelivery\n[PASS] invariant_specsAreImmutable\n InvariantsExtendedTest invariants (runs: 96, calls: 4608, reverts: 0)\n\n╭-------------+-------------------+-------+---------+----------╮\n| Contract    | Selector          | Calls | Reverts | Discards |\n+==============================================================+\n| FullHandler | abandonLate       | 344   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | applyShared       | 309   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | claimSponsored    | 333   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | deliverFalse      | 295   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | deliverTampered   | 321   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | deliverTrue       | 311   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | donate            | 281   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | failRequest       | 318   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | mintCard          | 316   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | registerSpec      | 288   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | requestSharedFact | 304   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | sponsor           | 294   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | transfer          | 292   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | upgradePaid       | 306   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| FullHandler | upgradeSponsored  | 296   | 0       | 0        |\n╰-------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 2680257944652377150\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 175519917692939684\n  Bound result 1300126943754487123\n  Bound result 1928028034\n  Bound result 2\n  Bound result 1129521836520189837\n  Bound result 1\n  Bound result 2\n  Bound result 113208181137293955\n  Bound result 40\n  Bound result 4\n  Bound result 4\n  Bound result 2\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 12.63s (12.63s CPU time)\n\nRan 9 test suites in 12.63s (18.59s CPU time): 78 tests passed, 0 failed, 11 skipped (89 total tests)\n","passed":true},{"durationMs":202,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Registry.abandon(bytes32)\",\"Registry.applySharedFact(uint16,address[])\",\"Registry.approve(address,uint256)\",\"Registry.claimSponsored(uint16)\",\"Registry.mintCard()\",\"Registry.onFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"Registry.onResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"Registry.registerSpec((uint8,address,string,string,string,uint256,string,uint8,uint256,uint64,uint64,string))\",\"Registry.requestSharedFact(uint16,uint256)\",\"Registry.safeTransferFrom(address,address,uint256)\",\"Registry.safeTransferFrom(address,address,uint256,bytes)\",\"Registry.setApprovalForAll(address,bool)\",\"Registry.sponsor(uint256)\",\"Registry.transferFrom(address,address,uint256)\",\"Registry.upgrade(uint16[],uint256)\",\"Registry.upgradeSponsored(uint256,uint16[])\"],\"files\":{\".gitignore\":8,\".gitmodules\":6,\"CATALOG.md\":240,\"CONCEPT.md\":188,\"DISCLOSURE.md\":12,\"INTEGRATION.md\":289,\"LICENSE\":21,\"README.md\":229,\"TEMPLATES.md\":154,\"foundry.toml\":44,\"reference/Intake.sol\":5175,\"reference/IntakeV2.sol\":5240,\"reference/PROVENANCE.md\":44,\"reference/abi/IMD.json\":1684,\"reference/abi/IdentityMD.json\":894,\"reference/abi/Intake.json\":955,\"reference/abi/IntakeV2.json\":1070,\"reference/abi/WhitelistCurator.json\":794,\"reference/anchors/headers.json\":61,\"reference/attestations/2026-10-10-link-pilot.json\":92,\"reference/attestations/2026-10-10-meatbag-consumer.json\":104,\"reference/attestations/2026-10-11-feed-consumer-v2.json\":105,\"reference/attestations/2026-10-11-nonce-false.json\":92,\"reference/attestations/2026-10-11-nonce-true.json\":92,\"reference/attestations/README.md\":29,\"reference/intake/completions.json\":147,\"reference/list-record/src/ListRecord.sol\":169,\"reference/list-record/src/ListRecordRenderer.sol\":126,\"reference/list-record/src/interfaces/IListRecordRenderer.sol\":29,\"reference/list-record/src/lib/SSTORE2.sol\":39,\"reference/list-record/src/lib/Str.sol\":54,\"reference/list-record/test/Renderer.t.sol\":165,\"reference/list-record/test/RendererMechanism.t.sol\":203,\"reference/list-record/test/Template.t.sol\":293,\"reference/list-record/test/fixtures/golden_synthetic_held_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_held_uri.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_transferred_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_transferred_uri.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_width_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_width_uri.txt\":1,\"reference/plane/checks/1001-hour-savior.json\":81,\"reference/plane/checks/1102-ordinal-1000.json\":81,\"reference/plane/checks/1105-first-thousand.json\":81,\"reference/plane/checks/1201-top-32.json\":82,\"reference/plane/checks/1301-not-born-yesterday.json\":86,\"reference/plane/checks/701-still-here.json\":81,\"reference/plane/checks/801-last-stand.json\":81,\"reference/plane/checks/T2-log-sum-composed.json\":81,\"reference/plane/checks/T4-call-compare-reference.json\":81,\"reference/plane/checks/T5-community-composed.json\":86,\"reference/plane/questionHashes.json\":92,\"reference/plane/quotes/1001-hour-savior.json\":20,\"reference/plane/quotes/1102-ordinal-1000.json\":20,\"reference/plane/quotes/1105-first-thousand.json\":20,\"reference/plane/quotes/1201-top-32.json\":20,\"reference/plane/quotes/1301-not-born-yesterday.json\":20,\"reference/plane/quotes/701-still-here.json\":20,\"reference/plane/quotes/801-last-stand.json\":20,\"reference/plane/quotes/T2-log-sum-composed.json\":20,\"reference/plane/quotes/T4-call-compare-reference.json\":20,\"reference/plane/quotes/T5-community-composed.json\":20,\"remappings.txt\":2,\"script/Deploy.s.sol\":35,\"src/Composer.sol\":550,\"src/Registry.sol\":736,\"src/Renderer.sol\":187,\"src/TemplateData.sol\":15,\"src/Types.sol\":41,\"src/interfaces/IIDMD.sol\":8,\"src/interfaces/IIntake.sol\":29,\"src/interfaces/IOracleConsumer.sol\":38,\"src/interfaces/IWhitelistCurator.sol\":53,\"template/blob.hex\":1,\"template/card.svg\":1,\"template/offsets.txt\":1,\"templates/fixtures/1001-hour-savior.json\":22,\"templates/fixtures/1102-ordinal-1000.json\":22,\"templates/fixtures/1105-first-thousand.json\":22,\"templates/fixtures/1201-top-32.json\":22,\"templates/fixtures/1301-not-born-yesterday.json\":24,\"templates/fixtures/701-still-here.json\":22,\"templates/fixtures/801-last-stand.json\":22,\"templates/fixtures/T2-log-sum-composed.json\":23,\"templates/fixtures/T4-call-compare-reference.json\":21,\"templates/fixtures/T5-community-composed.json\":24,\"test/.gitkeep\":0,\"test/Adversarial.t.sol\":746,\"test/Artifacts.t.sol\":95,\"test/Attestations.t.sol\":194,\"test/Base.t.sol\":157,\"test/Goldens.t.sol\":155,\"test/Invariants.t.sol\":124,\"test/InvariantsExtended.t.sol\":477,\"test/NOTES.md\":50,\"test/Registry.t.sol\":762,\"test/Templates.t.sol\":149,\"test/fixtures/golden_synthetic_direct_preimage.txt\":1,\"test/fixtures/golden_synthetic_direct_svg.txt\":1,\"test/fixtures/golden_synthetic_direct_uri.txt\":1,\"test/fixtures/golden_synthetic_oracle_preimage.txt\":1,\"test/fixtures/golden_synthetic_oracle_svg.txt\":1,\"test/fixtures/golden_synthetic_oracle_uri.txt\":1,\"test/fixtures/golden_synthetic_width_preimage.txt\":1,\"test/fixtures/golden_synthetic_width_svg.txt\":1,\"test/fixtures/golden_synthetic_width_uri.txt\":1,\"test/fork/Mainnet.fork.t.sol\":330,\"test/mocks/Mocks.sol\":225,\"tools/gen_template.py\":460,\"tools/test_gen_template.py\":94},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"7c173f1c001bbb52b4997bf8737e1265cb9dadd9a2a7a87091082e899e62388b","verifiedTreeHash":"79dcb050c9ec81032953c5881de0cd6185b9c2af","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":7984,"exitCode":0,"name":"build","output":"Compiling 68 files with Solc 0.8.24\nSolc 0.8.24 finished in 7.59s\nCompiler run successful!\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Renderer.sol:63:43\n   │\n63 │                 mcopy(add(add(out, 0x20), off), add(add(tpl, 0x20), start), len)\n   │                                           ━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Renderer.sol:171:21\n    │\n171 │                 out[o++] = \"\\\\\";\n    │                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Renderer.sol:162:42\n    │\n162 │             if (ch == '\"' || ch == \"\\\\\") extra += 1;\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/Registry.sol:58:38\n   │\n58 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:187:22\n    │\n187 │         deployedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:169:43\n    │\n169 │                 if (item[i] != prefix[i]) revert BadSpec(\"item\");\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:212:22\n    │\n212 │             if (!ok) revert BadSpec(\"name\");\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n    ╭▸ src/Registry.sol:201:9\n    │\n201 │         _mint(msg.sender, tokenId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Composer.sol:250:61\n    │\n250 │             if (bytes(q.values[i]).length > MAX_DEFINITION) revert DefinitionTooLong(bytes(q.values[i]).length);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:200:34\n    │\n200 │         mintedAtBlock[tokenId] = uint64(block.number);\n    │                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:238:46\n    │\n238 │             if (c.traits[i] >= 701) c.oracle[k++] = _meta(claimant, c.traits[i]);\n    │                                              ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:233:37\n    │\n233 │             if (c.traits[i] >= 701) n++;\n    │                                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:398:16\n    │\n398 │         return composer.catalogSpec(traitId, address(curator));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:394:30\n    │\n394 │             if (s.kind == 0) revert NotAnOracleTrait(traitId);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:397:78\n    │\n397 │         if (!_isCatalogChain(traitId) && traitId != 1201 && traitId != 1301) revert NotAnOracleTrait(traitId);\n    │                                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Composer.sol:538:13\n    │\n538 │             n++;\n    │             ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:324:47\n    │\n324 │             if (hasTrait(wallet, all[i])) tmp[n++] = all[i];\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:271:43\n    │\n271 │             (uint256 hour, bool joined) = curator.firstHourOf(wallet);\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:277:25\n    │\n277 │             uint256 n = curator.txCountOf(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:281:25\n    │\n281 │             uint256 w = curator.contributedBy(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:285:25\n    │\n285 │             uint256 p = curator.pointsOf(wallet);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:288:36\n    │\n288 │         if (traitId == 601) return idmd.balanceOf(wallet) >= 1;\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `pendingOf` is updated\n    ╭▸ src/Registry.sol:473:21\n    │\n473 │           requestId = intake.requestWithFailure(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n474 │ ┃             ACTION,\n475 │ ┃             body,\n476 │ ┃             IIntake.Callback(address(this), this.onResult.selector),\n    ‡ ┃\n479 │ ┃             price\n480 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:408:16\n    │\n408 │         return composer.compose(s, claimant, address(this), traitId == 1301, address(curator));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/Registry.sol:473:21\n    │\n473 │           requestId = intake.requestWithFailure(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n474 │ ┃             ACTION,\n475 │ ┃             body,\n476 │ ┃             IIntake.Callback(address(this), this.onResult.selector),\n    ‡ ┃\n479 │ ┃             price\n480 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:484:9\n    │\n484 │         emit TraitRequested(claimant, traitId, requestId, qh);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:426:46\n    │\n426 │             if (_isDirect(id) || id == 1201) revert NotAnOracleTrait(id);\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:429:32\n    │\n429 │                 if (kind == 0) revert NotAnOracleTrait(id);\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:430:32\n    │\n430 │                 if (kind == 3) revert NotASharedFact(id);\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:432:17\n    │\n432 │                 revert NotAnOracleTrait(id);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:465:62\n    │\n465 │             if (_verified[claimant][traitId].requestId != 0) revert AlreadyVerified(claimant, traitId);\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:466:52\n    │\n466 │             if (pendingOf[claimant][traitId] != 0) revert AlreadyPending(claimant, traitId);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:468:50\n    │\n468 │             if (_shared[traitId].requestId != 0) revert FactAlreadyStored(traitId);\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:469:46\n    │\n469 │             if (sharedPending[traitId] != 0) revert AlreadyPending(claimant, traitId);\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:442:13\n    │\n442 │         if (block.timestamp < uint256(p.requestedAt) + ABANDON_AFTER) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Registry.sol:481:58\n    │\n481 │         _pending[requestId] = Pending(claimant, traitId, uint64(block.timestamp), qh);\n    │                                                          ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:513:13\n    │\n513 │             emit Missed(requestId, p.traitId, reason);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:519:13\n    │\n519 │             emit SharedFactStored(p.traitId, requestId, n);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:606:9\n    │\n606 │         emit Verified(claimant, traitId, requestId, oracleRequestId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:608:27\n    │\n608 │         if (tokenId != 0) emit MetadataUpdate(tokenId);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:573:13\n    │\n573 │         if (block.timestamp > a.expiresAt || a.issuedAt > block.timestamp + ISSUED_AT_TOLERANCE) return 7;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:573:46\n    │\n573 │         if (block.timestamp > a.expiresAt || a.issuedAt > block.timestamp + ISSUED_AT_TOLERANCE) return 7;\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Registry.sol:673:14\n    │\n673 │         if (!found) revert NotInList();\n    │              ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Registry.sol:734:9\n    │\n734 │         emit PoolSpent(msg.sender, traitId, requestId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:730:40\n    │\n730 │         if (!_isCatalogChain(traitId)) revert NotACatalogChainTrait(traitId);\n    │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Registry.sol:731:44\n    │\n731 │         if (poolUsed[msg.sender][traitId]) revert PoolAlreadyUsed(msg.sender, traitId);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Registry.sol:720:13\n    │\n720 │         if (block.timestamp < uint256(deployedAt) + POOL_OPENS_AFTER) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/Registry.sol:721:27\n    │\n721 │         (, bool joined) = curator.firstHourOf(msg.sender);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[environment-read-across-mutation]: `block.chainid` may be reused across `vm.chainId`\n    ╭▸ test/Attestations.t.sol:133:17\n    │\n111 │             vm.chainId(4663);\n    │             ──────────────── `vm.chainId` changes this environment here\n    ‡\n133 │                 block.chainid,\n    │                 ━━━━━━━━━━━━━\n    │\n    ├ help: capture it with `vm.getChainId()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.chainid` may be reused across `vm.chainId`\n    ╭▸ test/Attestations.t.sol:133:17\n    │\n113 │             vm.chainId(1);\n    │             ───────────── `vm.chainId` changes this environment here\n    ‡\n133 │                 block.chainid,\n    │                 ━━━━━━━━━━━━━\n    │\n    ├ help: capture it with `vm.getChainId()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/Registry.t.sol:24:52\n   │\n24 │         assertEq(registry.mintedAtBlock(1), uint64(block.number));\n   │                                                    ━━━━━━━━━━━━\n   ‡\n31 │         vm.roll(block.number + 10);\n   │         ────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/Registry.t.sol:31:17\n   │\n31 │         vm.roll(block.number + 10);\n   │         ────────━━━━━━━━━━━━────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Registry.t.sol:395:17\n    │\n395 │         vm.warp(block.timestamp + 14 days - 1);\n    │         ────────━━━━━━━━━━━━━━━─────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Registry.t.sol:398:17\n    │\n398 │         vm.warp(block.timestamp + 1);\n    │         ────────━━━━━━━━━━━━━━━───── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":5083,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/Templates.t.sol:TemplatesTest\n[PASS] test_allTenBodiesAreByteExact() (gas: 1448401)\n[PASS] test_allTenQuestionHashesEqualThePlanes() (gas: 2176865)\n[PASS] test_bodyIsDeterministicInClaimantAndDiffersAcrossClaimants() (gas: 460653)\n[PASS] test_directAndUnknownIdsHaveNoBody() (gas: 60775)\n[PASS] test_hexMinAndCatalogWindows() (gas: 147209)\n[PASS] test_traitNamesAndClasses() (gas: 112609)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 6.68ms (9.89ms CPU time)\n\nRan 3 tests for test/Attestations.t.sol:AttestationsTest\n[PASS] test_allFiveRecoverTheAttesterUnderTheirOwnDomainOnly() (gas: 2068691)\n[PASS] test_loaderRejectsUnknownAnswerTypeNames() (gas: 4845)\n[PASS] test_protocolVectorDigestAndSelector() (gas: 564871)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 8.29ms (8.77ms CPU time)\n\nRan 5 tests for test/Goldens.t.sol:GoldensTest\n[PASS] test_escapeJsonNeutralisesMarkup() (gas: 42667)\n[PASS] test_goldenSyntheticDirect() (gas: 2734613)\n[PASS] test_goldenSyntheticOracle() (gas: 7323662)\n[PASS] test_goldenSyntheticWidthThroughTheRenderer() (gas: 2739727)\n[PASS] test_templateArtifactsMatchTheCompiledConstants() (gas: 520257)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 10.44ms (26.31ms CPU time)\n\nRan 25 tests for test/Registry.t.sol:RegistryTest\n[PASS] test_abandonOnlyAfterFourteenDaysAndStaleCallbackLeavesSuccessor() (gas: 3262840)\n[PASS] test_anyoneReadsAnyWalletAndNothingUsesTxOrigin() (gas: 1145515)\n[PASS] test_attestationForAnotherConsumerOrChainIsNeverAccepted() (gas: 3187050)\n[PASS] test_callbacksRejectEveryoneButTheIntake() (gas: 1629427)\n[PASS] test_claimSponsoredRules() (gas: 5245444)\n[PASS] test_directTraitsAreLiveAndNeedNoCard() (gas: 478454)\n[PASS] test_fuzz_tiersAreMonotone(uint8,bool,uint32,uint128,uint32,uint8) (runs: 256, μ: 536476, ~: 529093)\n[PASS] test_malformedEnvelopeIsNotDeliveredAndStaysPending() (gas: 1538011)\n[PASS] test_mintOncePerWalletAndTransfersKeepClaimant() (gas: 956553)\n[PASS] test_mintWithoutFeeReverts() (gas: 47096)\n[PASS] test_missReasons() (gas: 29342783)\n[PASS] test_noReceiveOrFallback() (gas: 57797)\n[PASS] test_nonMemberIsNeverAnEarlyBird() (gas: 147936)\n[PASS] test_onFailureClearsAndAllowsRetry() (gas: 2982204)\n[PASS] test_onResultGasWorstCase() (gas: 2318564)\nLogs:\n  onResult worst-case gas: 164696\n\n[PASS] test_poolIsTheBalanceAndOnlyLeavesThroughSponsoredRequests() (gas: 5220214)\n[PASS] test_reentrantTokenCannotReenterMint() (gas: 1166283)\n[PASS] test_registerSpecAssignsSequentialIdsAndIsImmutable() (gas: 1211834)\n[PASS] test_sharedFactBadEnvelopeIsAMissAndCanBeRequestedAgain() (gas: 6891818)\n[PASS] test_sharedFactFlow() (gas: 2454932)\n[PASS] test_specGuards() (gas: 1333134)\n[PASS] test_supportsERC4906AndERC721() (gas: 25952)\n[PASS] test_upgradeGuards() (gas: 6031335)\n[PASS] test_upgradeHappyPathMarksTraitAndRefreshesCard() (gas: 2513234)\n[PASS] test_upgradeWithoutCardAttachesToClaimant() (gas: 1871748)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 26.51ms (77.52ms CPU time)\n\nRan 5 tests for test/Artifacts.t.sol:ArtifactsTest\n[PASS] test_constructorRejectsZeroAddressesAndStoresTheRest() (gas: 5746)\n[PASS] test_deployScriptUsesTheFiveStaticAddresses() (gas: 24671877)\n[PASS] test_noForbiddenOpcodesInRuntime() (gas: 37120714)\n[PASS] test_noImmutableReferencesInAnyArtifact() (gas: 63339763)\n[PASS] test_twoDeploymentsHaveIdenticalRuntimeCode() (gas: 549784)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 53.62ms (89.36ms CPU time)\n\nRan 1 test for test/Invariants.t.sol:InvariantsTest\n[PASS]\nInvariantsTest invariants:\n[PASS] invariant_oneCardPerClaimantWithImmutableClaimant\n[PASS] invariant_poolOnlyLeavesThroughSponsoredRequests\n InvariantsTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭----------+-------------------+-------+---------+----------╮\n| Contract | Selector          | Calls | Reverts | Discards |\n+===========================================================+\n| Handler  | claimSponsored    | 3133  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | mintCard          | 3363  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | sponsor           | 3204  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | transfer          | 3393  | 0       | 0        |\n|----------+-------------------+-------+---------+----------|\n| Handler  | upgradeAndDeliver | 3291  | 0       | 0        |\n╰----------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 200000000000026892\n  Bound result 4628\n  Bound result 9262258\n  Bound result 112009637295419073\n  Bound result 9785\n  Bound result 1852977662072014932\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.88s (4.88s CPU time)\n\nRan 6 test suites in 4.88s (4.99s CPU time): 45 tests passed, 0 failed, 0 skipped (45 total tests)\n","passed":true},{"durationMs":151,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Registry.abandon(bytes32)\",\"Registry.applySharedFact(uint16,address[])\",\"Registry.approve(address,uint256)\",\"Registry.claimSponsored(uint16)\",\"Registry.mintCard()\",\"Registry.onFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"Registry.onResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"Registry.registerSpec((uint8,address,string,string,string,uint256,string,uint8,uint256,uint64,uint64,string))\",\"Registry.requestSharedFact(uint16,uint256)\",\"Registry.safeTransferFrom(address,address,uint256)\",\"Registry.safeTransferFrom(address,address,uint256,bytes)\",\"Registry.setApprovalForAll(address,bool)\",\"Registry.sponsor(uint256)\",\"Registry.transferFrom(address,address,uint256)\",\"Registry.upgrade(uint16[],uint256)\",\"Registry.upgradeSponsored(uint256,uint16[])\"],\"files\":{\".gitignore\":8,\".gitmodules\":6,\"CATALOG.md\":240,\"CONCEPT.md\":188,\"DISCLOSURE.md\":12,\"INTEGRATION.md\":289,\"LICENSE\":21,\"README.md\":229,\"TEMPLATES.md\":154,\"foundry.toml\":44,\"reference/Intake.sol\":5175,\"reference/IntakeV2.sol\":5240,\"reference/PROVENANCE.md\":44,\"reference/abi/IMD.json\":1684,\"reference/abi/IdentityMD.json\":894,\"reference/abi/Intake.json\":955,\"reference/abi/IntakeV2.json\":1070,\"reference/abi/WhitelistCurator.json\":794,\"reference/anchors/headers.json\":61,\"reference/attestations/2026-10-10-link-pilot.json\":92,\"reference/attestations/2026-10-10-meatbag-consumer.json\":104,\"reference/attestations/2026-10-11-feed-consumer-v2.json\":105,\"reference/attestations/2026-10-11-nonce-false.json\":92,\"reference/attestations/2026-10-11-nonce-true.json\":92,\"reference/attestations/README.md\":29,\"reference/intake/completions.json\":147,\"reference/list-record/src/ListRecord.sol\":169,\"reference/list-record/src/ListRecordRenderer.sol\":126,\"reference/list-record/src/interfaces/IListRecordRenderer.sol\":29,\"reference/list-record/src/lib/SSTORE2.sol\":39,\"reference/list-record/src/lib/Str.sol\":54,\"reference/list-record/test/Renderer.t.sol\":165,\"reference/list-record/test/RendererMechanism.t.sol\":203,\"reference/list-record/test/Template.t.sol\":293,\"reference/list-record/test/fixtures/golden_synthetic_held_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_held_uri.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_transferred_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_transferred_uri.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_width_svg.txt\":1,\"reference/list-record/test/fixtures/golden_synthetic_width_uri.txt\":1,\"reference/plane/checks/1001-hour-savior.json\":81,\"reference/plane/checks/1102-ordinal-1000.json\":81,\"reference/plane/checks/1105-first-thousand.json\":81,\"reference/plane/checks/1201-top-32.json\":82,\"reference/plane/checks/1301-not-born-yesterday.json\":86,\"reference/plane/checks/701-still-here.json\":81,\"reference/plane/checks/801-last-stand.json\":81,\"reference/plane/checks/T2-log-sum-composed.json\":81,\"reference/plane/checks/T4-call-compare-reference.json\":81,\"reference/plane/checks/T5-community-composed.json\":86,\"reference/plane/questionHashes.json\":92,\"reference/plane/quotes/1001-hour-savior.json\":20,\"reference/plane/quotes/1102-ordinal-1000.json\":20,\"reference/plane/quotes/1105-first-thousand.json\":20,\"reference/plane/quotes/1201-top-32.json\":20,\"reference/plane/quotes/1301-not-born-yesterday.json\":20,\"reference/plane/quotes/701-still-here.json\":20,\"reference/plane/quotes/801-last-stand.json\":20,\"reference/plane/quotes/T2-log-sum-composed.json\":20,\"reference/plane/quotes/T4-call-compare-reference.json\":20,\"reference/plane/quotes/T5-community-composed.json\":20,\"remappings.txt\":2,\"script/Deploy.s.sol\":35,\"src/Composer.sol\":550,\"src/Registry.sol\":736,\"src/Renderer.sol\":187,\"src/TemplateData.sol\":15,\"src/Types.sol\":41,\"src/interfaces/IIDMD.sol\":8,\"src/interfaces/IIntake.sol\":29,\"src/interfaces/IOracleConsumer.sol\":38,\"src/interfaces/IWhitelistCurator.sol\":53,\"template/blob.hex\":1,\"template/card.svg\":1,\"template/offsets.txt\":1,\"templates/fixtures/1001-hour-savior.json\":22,\"templates/fixtures/1102-ordinal-1000.json\":22,\"templates/fixtures/1105-first-thousand.json\":22,\"templates/fixtures/1201-top-32.json\":22,\"templates/fixtures/1301-not-born-yesterday.json\":24,\"templates/fixtures/701-still-here.json\":22,\"templates/fixtures/801-last-stand.json\":22,\"templates/fixtures/T2-log-sum-composed.json\":23,\"templates/fixtures/T4-call-compare-reference.json\":21,\"templates/fixtures/T5-community-composed.json\":24,\"test/.gitkeep\":0,\"test/Artifacts.t.sol\":95,\"test/Attestations.t.sol\":194,\"test/Base.t.sol\":157,\"test/Goldens.t.sol\":155,\"test/Invariants.t.sol\":124,\"test/Registry.t.sol\":762,\"test/Templates.t.sol\":149,\"test/fixtures/golden_synthetic_direct_preimage.txt\":1,\"test/fixtures/golden_synthetic_direct_svg.txt\":1,\"test/fixtures/golden_synthetic_direct_uri.txt\":1,\"test/fixtures/golden_synthetic_oracle_preimage.txt\":1,\"test/fixtures/golden_synthetic_oracle_svg.txt\":1,\"test/fixtures/golden_synthetic_oracle_uri.txt\":1,\"test/fixtures/golden_synthetic_width_preimage.txt\":1,\"test/fixtures/golden_synthetic_width_svg.txt\":1,\"test/fixtures/golden_synthetic_width_uri.txt\":1,\"test/mocks/Mocks.sol\":225,\"tools/gen_template.py\":460,\"tools/test_gen_template.py\":94},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":4096,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/Registry.sol:541: Registry._rule(uint16) (src/Registry.sol#541-555) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:526: Registry.onFailure(bytes32,uint8,bytes32,uint16,uint16,bytes) (src/Registry.sol#526-538) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:501: Registry.onResult(bytes32,OracleAttestation,bytes) (src/Registry.sol#501-523) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:541: Registry._rule(uint16) (src/Registry.sol#541-555) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:541: Registry._rule(uint16) (src/Registry.sol#541-555) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:541: Registry._rule(uint16) (src/Registry.sol#541-555) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Registry.sol:439: Registry.abandon(bytes32) (src/Registry.sol#439-445) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/Registry.sol:463: Reentrancy in Registry._request(address,uint16,uint256) (src/Registry.sol#463-485):\n[medium/medium] uninitialized-local at src/Composer.sol:466: Composer.encodeBody(Composer.Question,address).defs (src/Composer.sol#466) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Registry.sol:236: Registry.cardOf(uint256).k (src/Registry.sol#236) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Renderer.sol:167: Renderer.escapeJson(bytes).o (src/Renderer.sol#167) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Registry.sol:666: Registry.applySharedFact(uint16,address[]).found (src/Registry.sol#666) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Composer.sol:536: Composer.hexMin(uint256).n (src/Composer.sol#536) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Registry.sol:231: Registry.cardOf(uint256).n (src/Registry.sol#231) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Registry.sol:322: Registry.traitsOf(address).n (src/Registry.sol#322) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Composer.sol:509: Composer.canonical(Composer.Question).defs (src/Composer.sol#509) is a local variable never initialized\n[medium/medium] uninitialized-local at src/Renderer.sol:159: Renderer.escapeJson(bytes).extra (src/Renderer.sol#159) is a local variable never initialized\n[medium/medium] unused-return at src/Registry.sol:719: Registry.claimSponsored(uint16) (src/Registry.sol#719-727) ignores return value by (None,joined) = curator.firstHourOf(msg.sender) (src/Registry.sol#721)\n[medium/medium] unused-return at src/Registry.sol:558: Registry._check(Registry.Pending,OracleAttestation,bytes,uint8,uint64,uint64) (src/Registry.sol#558-576) ignores return value by (signer,err,None) = ECDSA.tryRecover(attestationDigest(a),signature) (src/Registry.sol#567)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: w = curator.contributedBy(wallet) (src/Registry.sol#281)\n[low/medium] calls-loop at src/Registry.sol:463: Registry._request(address,uint16,uint256) (src/Registry.sol#463-485) has external calls inside a loop: requestId = intake.requestWithFailure(ACTION,body,IIntake.Callback(address(this),this.onResult.selector),this.onFailure.selector,address(imd),price) (src/Registry.sol#473-480)\n[low/medium] calls-loop at src/Registry.sol:402: Registry.composeBody(uint16,address) (src/Registry.sol#402-409) has external calls inside a loop: composer.compose(s,claimant,address(this),traitId == 1301,address(curator)) (src/Registry.sol#408)\n[low/medium] calls-loop at src/Registry.sol:391: Registry.specOf(uint16) (src/Registry.sol#391-399) has external calls inside a loop: composer.catalogSpec(traitId,address(curator)) (src/Registry.sol#398)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: (hour,joined) = curator.firstHourOf(wallet) (src/Registry.sol#271)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: (hour,joined) = curator.firstHourOf(wallet) (src/Registry.sol#271)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: n = curator.txCountOf(wallet) (src/Registry.sol#277)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: p = curator.pointsOf(wallet) (src/Registry.sol#285)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: n = curator.txCountOf(wallet) (src/Registry.sol#277)\n[low/medium] calls-loop at src/Registry.sol:402: Registry.composeBody(uint16,address) (src/Registry.sol#402-409) has external calls inside a loop: composer.compose(s,claimant,address(this),traitId == 1301,address(curator)) (src/Registry.sol#408)\n[low/medium] calls-loop at src/Registry.sol:391: Registry.specOf(uint16) (src/Registry.sol#391-399) has external calls inside a loop: composer.catalogSpec(traitId,address(curator)) (src/Registry.sol#398)\n[low/medium] calls-loop at src/Registry.sol:463: Registry._request(address,uint16,uint256) (src/Registry.sol#463-485) has external calls inside a loop: requestId = intake.requestWithFailure(ACTION,body,IIntake.Callback(address(this),this.onResult.selector),this.onFailure.selector,address(imd),price) (src/Registry.sol#473-480)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: w = curator.contributedBy(wallet) (src/Registry.sol#281)\n[low/medium] calls-loop at src/Registry.sol:391: Registry.specOf(uint16) (src/Registry.sol#391-399) has external calls inside a loop: composer.catalogSpec(traitId,address(curator)) (src/Registry.sol#398)\n[low/medium] calls-loop at src/Registry.sol:391: Registry.specOf(uint16) (src/Registry.sol#391-399) has external calls inside a loop: composer.catalogSpec(traitId,address(curator)) (src/Registry.sol#398)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: p = curator.pointsOf(wallet) (src/Registry.sol#285)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: n = curator.txCountOf(wallet) (src/Registry.sol#277)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: idmd.balanceOf(wallet) >= 1 (src/Registry.sol#288)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: idmd.balanceOf(wallet) >= 1 (src/Registry.sol#288)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: p = curator.pointsOf(wallet) (src/Registry.sol#285)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: (hour,joined) = curator.firstHourOf(wallet) (src/Registry.sol#271)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: w = curator.contributedBy(wallet) (src/Registry.sol#281)\n[low/medium] calls-loop at src/Registry.sol:268: Registry.hasTrait(address,uint16) (src/Registry.sol#268-290) has external calls inside a loop: idmd.balanceOf(wallet) >= 1 (src/Registry.sol#288)\n[low/medium] reentrancy-benign at src/Registry.sol:463: Reentrancy in Registry._request(address,uint16,uint256) (src/Registry.sol#463-485):\n[low/medium] timestamp at src/Registry.sol:719: Registry.claimSponsored(uint16) (src/Registry.sol#719-727) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:439: Registry.abandon(bytes32) (src/Registry.sol#439-445) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:488: Registry._clear(bytes32,Registry.Pending) (src/Registry.sol#488-495) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:558: Registry._check(Registry.Pending,OracleAttestation,bytes,uint8,uint64,uint64) (src/Registry.sol#558-576) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:603: Registry._mark(address,uint16,bytes32,bytes32) (src/Registry.sol#603-609) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:526: Registry.onFailure(bytes32,uint8,bytes32,uint16,uint16,bytes) (src/Registry.sol#526-538) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:541: Registry._rule(uint16) (src/Registry.sol#541-555) uses timestamp for comparisons\n[low/medium] timestamp at src/Registry.sol:501: Registry.onResult(bytes32,OracleAttestation,bytes) (src/Registry.sol#501-523) uses timestamp for comparisons","passed":true},{"durationMs":873,"exitCode":0,"name":"aderyn","output":"[high] abi-encode-packed-hash-collision at src/Renderer.sol:45: `abi.encodePacked()` Hash Collision\n[high] reentrancy-state-change at src/Registry.sol:640: Reentrancy: State change after external call (2 places)\n[low] costly-loop at src/Registry.sol:424: Costly operations inside loop (2 places)\n[low] internal-function-used-once at src/Composer.sol:258: Internal Function Used Only Once (4 places)\n[low] large-numeric-literal at src/Composer.sol:93: Large Numeric Literal (2 places)\n[low] literal-instead-of-constant at src/Composer.sol:70: Literal Instead of Constant (204 places)\n[low] require-revert-in-loop at src/Composer.sol:168: Loop Contains `require`/`revert` (8 places)\n[low] state-variable-could-be-immutable at src/Registry.sol:87: State Variable Could Be Immutable (8 places)\n[low] unchecked-return at src/Registry.sol:434: Unchecked Return (2 places)\n[low] uninitialized-local-variable at src/Composer.sol:536: Uninitialized Local Variable (2 places)\n[low] unsafe-oz-erc721-mint at src/Registry.sol:201: Unsafe `ERC721::_mint()`\n[low] unused-public-function at src/Composer.sol:230: Public Function Not Used Internally (3 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"b8f2b0595ca2297b6690585c7dcbd343524e2f78746db062612440b81b7e5c9f","verifiedTreeHash":"fc65e26496f1eb4f01939e6294cb26622a41d9a5","verifierVersion":"0.1.0+fb8278c5"}]}