{"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":"60c3f4c6-f8d3-4ad0-8495-525b6be52c44","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"80c806f4f29b98638989150afc063ea7adf3eadc443027725a13d75c74697993","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"65298344585d61c77eeeb717859e24df8a49154003b5ce0ac3e38068fcd60946","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"14de52ad7933a39b53ad8bf9b84de16958c639f0ad6fbc0126444147f7332db7","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"5ea6e867675f576925c510358ce4d259476c9d522d7383f4f78b0958cddffd10","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"bd1a672b5dd64ebbace3ad49ad19d81aa001c2894e52180cca388084597023b0","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"47ec79a80a2a1e0c4032fe0bf4a32209291acd84ec5e8b5964e184cf2bd6b965","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":"23fb0580d294c27cddab5606fc0e370b9991e837ea5714ee86dc484d9608c154","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"cde9c4818fb4febd781c5f2fac26d47252a7d8a7a2d578927c804106d5149fc8","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":"A custom token: Offsets (OFFSETS).\nToken name: Offsets\nToken symbol: OFFSETS\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"b7e7bcd96237a75272b9e9f98e9a6e3d37dbaf8451990ca794dc902084deb5f1","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"60c3f4c6-f8d3-4ad0-8495-525b6be52c44","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1407-offsets"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52480","feedbackHash":"9d2be364f06c929eadf83f50b5c8d3b6f581e782b423fcd9281822bcaf637328","nodeKey":"audit_economics","submissionHash":"80c806f4f29b98638989150afc063ea7adf3eadc443027725a13d75c74697993","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52268","feedbackHash":"d0028acc2b2f21d6c06f250d659afd33ee0a8ce76a73680f5cf3dba10a7772e1","nodeKey":"audit_flow","submissionHash":"65298344585d61c77eeeb717859e24df8a49154003b5ce0ac3e38068fcd60946","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51538","feedbackHash":"53f9ed726d18235796e5ecc7e29cdc8f282172753ed12d3ac9bdb26e9614c4ae","nodeKey":"audit_judge","submissionHash":"14de52ad7933a39b53ad8bf9b84de16958c639f0ad6fbc0126444147f7332db7","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51043","feedbackHash":"e1dac3b744d2a72d5919d2284f2b5c25020bd128a5c7d91d997464c183aff50c","nodeKey":"audit_math","submissionHash":"5ea6e867675f576925c510358ce4d259476c9d522d7383f4f78b0958cddffd10","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51154","feedbackHash":"259d3e9eb8b4221075fefca13c07ccc3b6fc450a23454f80f1f0d57fb0860405","nodeKey":"audit_permissions","submissionHash":"bd1a672b5dd64ebbace3ad49ad19d81aa001c2894e52180cca388084597023b0","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52149","feedbackHash":"00ba6b492e5fd7866c9349b25f0ffad9647c825eca2664bd0a2c5fc6383c8453","nodeKey":"build_contract_project","submissionHash":"47ec79a80a2a1e0c4032fe0bf4a32209291acd84ec5e8b5964e184cf2bd6b965","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52014","feedbackHash":"7d69f14ac92de1f36e123f35d79787ef3805e34c2de8031e345116502ab8dc7b","nodeKey":"manifest","submissionHash":"23fb0580d294c27cddab5606fc0e370b9991e837ea5714ee86dc484d9608c154","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51444","feedbackHash":"eb17b885a0183eaa8fb35e074a68d638ca476f3690243ebe534c64b3ddcc3556","nodeKey":"write_foundry_tests","submissionHash":"cde9c4818fb4febd781c5f2fac26d47252a7d8a7a2d578927c804106d5149fc8","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"60c68e45cbbc58316fd6fa0b9909e379aaa9831d9aa4addabf93b7628de3fa3f","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"b57ae3a96321a0e1","findings":[{"citation":"resolved","description":"Merged from audit_math, audit_economics and audit_flow (same root cause, reported three times). _transfer refuses the zero address only as the recipient; nothing refuses it as the sender. _spendAllowance (line 134: `if (current < amount) revert`) passes for amount 0 against the zero allowance, and _transfer (line 115: `if (fromBalance < amount) revert`) passes for amount 0 against the zero balance. So any unprivileged caller can run transferFrom(address(0), anyone, 0): it returns true and emits Approval(address(0), caller, 0) followed by Transfer(address(0), anyone, 0), the exact event shape of the constructor's mint on line 61. Balances, allowances and totalSupply are unchanged; a non-zero amount reverts with InsufficientAllowance, and address(0) can never hold a balance, so there is no loss of funds and no path to supply growth. The only effect is on off-chain consumers that treat a Transfer from address(0) as a mint. The NatSpec on lines 10-11 claims parity with the widely used library conventions; OpenZeppelin v5 reverts ERC20InvalidSender(address(0)) here. Not a launch-floor failure. Minimal fix, if the author wants exact parity: add `if (from == address(0)) revert TransferFromZeroAddress();` at the top of _transfer, which changes no intended behaviour.","line":113,"path":"src/OffsetsToken.sol","reproduction":"Reproduced with a Foundry test under test/scratch against the tree as it is. State: fresh OffsetsToken deployed by the test contract; alice (0xA11CE) and bob (0xB0B) hold no balance and no allowance. Call: vm.prank(alice); token.transferFrom(address(0), bob, 0). Expected (library convention the NatSpec cites): revert with an invalid-sender error. Actual: returns true; vm.expectEmit confirmed Approval(address(0), alice, 0) then Transfer(address(0), bob, 0); totalSupply() == 1000000000000000000000000000 and balanceOf(bob) == 0 afterwards. Control: vm.prank(alice); token.transferFrom(address(0), bob, 1) reverts with InsufficientAllowance(alice, 0, 1), so the path is reachable only for a zero amount.","severity":"info","snippet":"        if (to == address(0)) revert TransferToZeroAddress();","title":"transferFrom accepts address(0) as `from` for a zero amount and emits a mint-shaped Transfer(0, to, 0)"}],"hash":"14de52ad7933a39b53ad8bf9b84de16958c639f0ad6fbc0126444147f7332db7","nodeId":"dea23e83-af6f-4401-8d6f-359addb2fb99","outcome":"completed","summary":"The review is complete and the findings file is written. The tree is otherwise unchanged.\n\n**Outcome.** The Offsets token is a plain fixed-supply ERC-20 with no privileged path, and it holds on all three entry points. One specialist finding survived, at info severity.\n\n**What I kept.** Three specialists reported the same root cause, so they are merged into one finding. Any caller can run transferFrom from the zero address with a zero amount, and the call succeeds while emitting a mint-shaped Transfer event. I reproduced it with a Foundry test under test/scratch, including the control that a non-zero amount reverts with InsufficientAllowance. Nothing moves, supply cannot grow, and the launch floor is unaffected, so it stays at info with no proof attached.\n\n**What I verified myself.**\n- The full project suite passes, including the invariant suite with 256 runs and no reverts.\n- Runtime bytecode disassembly shows no DELEGATECALL, CALLCODE or SELFDESTRUCT. Creation and runtime sizes are far under the protocol limits.\n- The manifest matches the code: argument-free constructor, 18 decimals, and the exact minted supply.\n- Max allowance is not decremented, self-transfer of a full balance is safe, and the unchecked arithmetic is bounded by the fixed supply.\n\n**Coverage.** All three entry points are answered, plus two invariant rows for fixed supply and factory deployability. The scratch test was removed after it ran.","treeHash":null,"usage":{"cachedInputTokens":442621,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":6141,"runtime":"claude","turns":10,"wallClockMs":100147}},{"artifacts":[],"attempt":1,"bundleHash":"26843986b937ef4e9629f024ce22f9b9b1d99c267a6c0d359faf56dbf68d558a","device":"b5d96cb4e4dd8f0e","findings":[],"hash":"23fb0580d294c27cddab5606fc0e370b9991e837ea5714ee86dc484d9608c154","nodeId":"b093e5dc-8f35-474a-9d79-4ebc542fbca2","outcome":"completed","summary":"Created [launch.json](/home/imd1/.identitymd/work/60c3f4c6-f8d3-4ad0-8495-525b6be52c44/b093e5dc-8f35-474a-9d79-4ebc542fbca2/launch.json) matching `OffsetsToken`, its exact supply, empty constructor arguments, and required pool/economics.\n\nOnly `launch.json` changed.\n\nValidation: manifest and compiled ABI checks passed; `forge build` succeeded; all 30 tests passed.","treeHash":"377f848815851f1a876bc365bc72e94e993fbfb6","usage":{"cachedInputTokens":125696,"inputTokens":31753,"model":"gpt-6-astra","outputTokens":1872,"runtime":"codex","turns":3,"wallClockMs":69033}},{"artifacts":[],"attempt":1,"bundleHash":"ae49eb8c1ef36f04dca19c90154fba23a9a116a194aa74222ab2d8ec41584646","device":"af1843f371022d4a","findings":[],"hash":"47ec79a80a2a1e0c4032fe0bf4a32209291acd84ec5e8b5964e184cf2bd6b965","nodeId":"611072be-33d2-49ea-b1d2-622943bb3f90","outcome":"completed","summary":"The Offsets token project is complete, verified and committed.\n\n**What was delivered**\n\n- `src/OffsetsToken.sol`: a hand-written, fixed-supply ERC-20 named Offsets with symbol OFFSETS and 18 decimals. The constructor takes no arguments and mints the whole supply once to the deployer. There is no owner, mint, burn, pause, blacklist, fee or upgrade path, so nothing can grow the supply or freeze a holder after launch.\n- `test/OffsetsToken.t.sol`: 30 tests covering metadata, the one-time mint to any deployer, every transfer and allowance success and failure path with exact error data and events, fuzzed supply conservation, the absence of mint and admin selectors, refusal of plain ETH, and an opcode scan mirroring the launch floor's check.\n- `script/DeployOffsets.s.sol`: a deploy script whose deploy function is tested directly and reads no environment variables.\n- `README.md`: assumptions, deployment parameters, launch values, after-launch settings (none) and operational responsibilities.\n- `foundry.toml` pins solc 0.8.26, sets `bytecode_hash = \"none\"`, and enables no ffi or filesystem access. forge-std v1.9.7 is vendored under `lib/` as ordinary files with no nested git metadata.\n\n**Verification results**\n\n| Check | Result |\n| --- | --- |\n| forge build | passes with solc 0.8.26 |\n| forge test | 30 passed, 0 failed |\n| forge fmt --check | passes |\n| runtime size | 1,444 bytes |\n\nThe commit on main contains all files, including the vendored library. No launch.json was written, as the brief directs. Tests passing is not a security audit, so the launch's independent review should still read the contract before release.","treeHash":"8da6a26d666f73396a15ace6dd2fb33c2537d5cc","usage":{"cachedInputTokens":551307,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":19447,"runtime":"claude","turns":24,"wallClockMs":243145}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2565f234b0a569e9","findings":[{"citation":"resolved","description":"_transfer refuses the zero address only as the recipient, not as the sender, and _spendAllowance passes a zero amount against a zero allowance (0 < 0 is false). Any caller can therefore run transferFrom(address(0), anyone, 0) with no allowance and the call returns true, emitting Approval(address(0), caller, 0) and Transfer(address(0), anyone, 0). The Transfer event has the shape of a mint. No balance, allowance or supply changes (a non-zero amount reverts with InsufficientAllowance, and address(0) can never hold a balance), so there is no loss of funds; the only effect is that off-chain indexers or explorers which treat Transfer-from-zero as a mint can be fed spurious zero-value mint events by anyone. This diverges from the library convention the NatSpec cites (OpenZeppelin v5 reverts ERC20InvalidSender for from == address(0)). The guarantee 'nothing mints after construction' still holds numerically. Minimal fix, if wanted: add `if (from == address(0)) revert TransferFromZeroAddress();` in _transfer; it does not alter any intended behaviour.","line":113,"path":"src/OffsetsToken.sol","reproduction":"State: fresh OffsetsToken deployed by D. Call, as any address A: token.transferFrom(address(0), B, 0). Expected (library convention): revert. Actual: returns true; events emitted: Approval(0x0, A, 0) then Transfer(0x0, B, 0); totalSupply() still 1e27; balanceOf(B) still 0. Reproduced in Foundry with vm.expectEmit for both events and the call succeeding. Control: transferFrom(address(0), B, 1) reverts InsufficientAllowance(A, 0, 1).","severity":"info","snippet":"        if (to == address(0)) revert TransferToZeroAddress();","title":"transferFrom(address(0), to, 0) succeeds and emits a mint-shaped Transfer from the zero address"}],"hash":"5ea6e867675f576925c510358ce4d259476c9d522d7383f4f78b0958cddffd10","nodeId":"82046ac7-e663-4c49-9700-a8e7a0f84492","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds the result. The scratch tests were removed, so the tree is unchanged apart from the findings file.\n\n**Outcome: no math defect found.** The Offsets token is a hand-written fixed-supply ERC-20 with no division, scaling, casts or external calls, so most of the Math Precision, Boundary and Numerical Gap checklists have nothing to attach to. I traced the two `unchecked` blocks, the three sentinel branches and every zero or max boundary, and confirmed them with Foundry tests before deleting them:\n\n- **Supply constant** is exactly 1e27 and splits into the launch's 10/80/10 shares with no dust. The aderyn large-literal lead is stylistic only.\n- **Unchecked subtraction** in both `_transfer` and `_spendAllowance` sits behind an explicit `<` guard. The unchecked addition cannot overflow because an invariant fuzz over seven actors confirmed every balance stays at or below the supply and the sum stays conserved.\n- **Boundaries** at amount zero, whole balance, supply plus one, max uint, allowance max minus one, allowance exactly max, and self-transfer all behave as intended.\n\n**One info-level finding** is recorded. Anyone can call `transferFrom(address(0), to, 0)` with no allowance and it returns true, emitting a zero-value Approval and a Transfer from the zero address. The event has the shape of a mint, which can mislead indexers, but no balance, allowance or supply changes, and a non-zero amount reverts. OpenZeppelin rejects a zero sender, so this diverges from the convention the NatSpec cites. The suggested fix is a one-line sender check that changes no intended behaviour.\n\n**Coverage** has seven rows: the three ABI entry points plus the supply invariant, the constant, the constructor and the views. `approve` and `transfer` hold. `transferFrom` points to the info finding. Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":698118,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":13878,"runtime":"claude","turns":19,"wallClockMs":220513}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ff35db055462d2ad","findings":[{"citation":"resolved","description":"_transfer refuses the zero address only as `to`. Nothing refuses it as `from`. Because address(0) has balance 0 and allowance 0, the only way through is amount == 0, which both guards accept (0 < 0 is false in _spendAllowance line 134 and in _transfer line 115). Any unprivileged caller can therefore emit `Approval(address(0), caller, 0)` followed by `Transfer(address(0), anyone, 0)`, the exact shape the constructor's mint event has (line 61). Balances, allowances and totalSupply are unchanged, so there is no loss; the effect is limited to off-chain consumers that treat a Transfer from address(0) as a mint (indexers that count mint events, or explorers that display a 'mint' row). OpenZeppelin's ERC20 (v4 and v5) reverts on a zero sender in _transfer, so this is a small divergence from the library conventions the NatSpec on line 10 otherwise follows. Execution Trace guide item checked: sentinel bypass (address(0) taking a path the normal path refuses). Not a loss of funds and not a launch-floor failure; reported so the author can decide whether to add `if (from == address(0)) revert` for exact parity.","line":113,"path":"src/OffsetsToken.sol","reproduction":"State: fresh OffsetsToken deployed by `deployer`; alice and bob are any addresses with no balance and no allowance. Call: vm.prank(alice); token.transferFrom(address(0), bob, 0). Expected (library convention): revert with an invalid-sender error. Actual: returns true and emits Approval(address(0), alice, 0) then Transfer(address(0), bob, 0); totalSupply() still 1000000000000000000000000000, balanceOf(bob) == 0. With amount 1 instead of 0 the call reverts with InsufficientAllowance(alice, 0, 1), so the path is reachable only for zero value. Verified with a Foundry test under test/scratch (expectEmit on both events, then the assertions above) against the tree as it is.","severity":"info","snippet":"        if (to == address(0)) revert TransferToZeroAddress();\n        uint256 fromBalance = _balances[from];\n        if (fromBalance < amount) revert InsufficientBalance(from, fromBalance, amount);","title":"transferFrom accepts from == address(0) for zero amounts and emits a mint-shaped Transfer event"}],"hash":"65298344585d61c77eeeb717859e24df8a49154003b5ce0ac3e38068fcd60946","nodeId":"0c6d132a-fef1-42b9-be13-864696cc82e0","outcome":"completed","summary":"The review is complete. The findings file is in place at the repository root, the scratch tests are removed, and no tracked file was changed.\n\n**Outcome:** the Offsets token holds up under the Execution Trace, Periphery and First Principles checks. I found no loss-of-funds, supply-growth, privileged-path or launch-flow defect. The one substantiated item is informational.\n\n**What I checked, in depth, in my area**\n\n- **Execution Trace.** Traced `approve`, `transfer` and `transferFrom` from entry to final state. Sentinel paths: zero `to` refused, max allowance is exact (max minus one still decrements) and does not bypass the balance check, self-transfer re-reads storage so the cached balance is not stale. Fuzzed supply conservation over random sixteen-step sequences across four actors, plus self-transfers through both paths.\n- **Periphery.** The token imports nothing and uses no assembly. The only peripheral code is the deploy script, which wraps the constructor in a broadcast and is not part of the launch.\n- **First Principles.** The constructor's assumptions hold: no arguments, no external call, supply written once to the deployer. The unchecked addition relies on the sum of balances equalling the fixed supply, which is enforced because only one conserving function writes balances after construction.\n- **Static-analysis lead.** The aderyn large-literal line is the correct 1e27 supply constant, not a defect.\n\n**The one finding (info).** A zero-amount `transferFrom` with the zero address as sender succeeds and emits `Transfer(address(0), to, 0)`, the same shape as the constructor's mint event. Reproduction is any caller sending `transferFrom(address(0), bob, 0)` on a fresh deployment. Balances, allowances and total supply are untouched, so it affects only off-chain indexers that count mint-shaped events. OpenZeppelin reverts on a zero sender, so the author may want parity.\n\n**Coverage record.** All three listed entry points have rows, plus rows for the constructor mint, the supply invariant, the launch-flow invariant, the opcode scan, and the two periphery surfaces. Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":474003,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":11838,"runtime":"claude","turns":20,"wallClockMs":174217}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"b0b4e7bbc84f9d80","findings":[{"citation":"resolved","description":"_transfer refuses the zero address only as the recipient; there is no check that `from` is non-zero. Because _spendAllowance passes when `current (0) >= amount (0)`, and _transfer passes when `fromBalance (0) >= amount (0)`, any caller can execute transferFrom(address(0), anyone, 0). The call returns true and emits Approval(address(0), caller, 0) followed by Transfer(address(0), anyone, 0): the exact event shape of a mint. OpenZeppelin v5 reverts here with ERC20InvalidSender(address(0)), which the contract's NatSpec (lines 10-11) cites as the convention it matches. Nothing moves: balances, allowances and totalSupply are unchanged, and a non-zero amount reverts with InsufficientAllowance, so there is no economic impact and no path to supply growth. Off-chain indexers that count Transfer-from-zero events as mints will see spurious zero-value mint events that any address can emit at will. Minimal fix, if wanted: `if (from == address(0)) revert TransferFromZeroAddress();` at the top of _transfer (or reject owner == address(0) in _spendAllowance).","line":113,"path":"src/OffsetsToken.sol","reproduction":"State: fresh OffsetsToken, any caller `spender` with no allowance and no balance. Call: vm.prank(spender); token.transferFrom(address(0), alice, 0). Expected (library convention the NatSpec claims): revert. Actual: returns true, emits Approval(address(0), spender, 0) and Transfer(address(0), alice, 0); totalSupply still 1000000000000000000000000000 and balanceOf(alice) still 0. Verified with a Foundry test using vm.expectEmit on both events. Control: token.transferFrom(address(0), alice, 1) reverts with InsufficientAllowance(spender, 0, 1).","severity":"info","snippet":"        if (to == address(0)) revert TransferToZeroAddress();","title":"transferFrom accepts address(0) as `from` for a zero amount and emits a mint-shaped Transfer(0, to, 0)"}],"hash":"80c806f4f29b98638989150afc063ea7adf3eadc443027725a13d75c74697993","nodeId":"ee2d50ab-0047-41fe-ad11-8bb5505500b8","outcome":"completed","summary":"Review complete. The findings file is written and validated, and the scratch tests are removed so the tree holds only `.imd-findings.json`.\n\n**Outcome:** no economic, invariant or flow-gap defect in `src/OffsetsToken.sol`. One info-level note recorded.\n\n**What I checked, against the Economic Security, Invariant and Flow Gap guides:**\n- **Conservation invariant.** A handler-based Foundry invariant run over random transfer, approve and transferFrom calls across five actors never broke sum of balances equals the constant 1e27 supply. The unchecked arithmetic is safe under that law, and self-transfers re-read storage so balances are preserved.\n- **Supply growth.** The compiled ABI exposes only approve, transfer and transferFrom as state changers, no receive or fallback, and the runtime has no delegatecall, callcode or selfdestruct. Supply cannot grow or be minted after construction.\n- **Launch flows.** No fee, burn, exemption, pause or blacklist exists, and transfer returns true. A launch-shaped sequence of factory to distributor to claimant, factory to pool, and pool to trader and back moved exact amounts in a scratch test. The protected harness checks should pass. I could not run that harness itself because its Uniswap v4 and LaunchLiquidity dependencies are not in this tree.\n- **External dependencies and economics.** The token calls no other contract and has no price, fee or cap logic. The only trust assumption is the launch design itself: whoever deploys receives everything, which is the factory.\n- **Static analysis lead.** The large-numeric-literal line is the constant-folded supply, computed as exactly the manifest value and below 2^256.\n\n**Info finding recorded:** `transferFrom(address(0), to, 0)` succeeds from any caller and emits a mint-shaped zero-value Transfer plus an Approval for owner address zero. OpenZeppelin reverts there. Nothing moves and a non-zero amount reverts, so there is no fund or supply impact. The reproduction and a one-line fix are in the file.\n\n**Coverage record:** all three listed entry points have rows, two holding and transferFrom pointing at the info finding, plus five rows for the invariants and flows checked.","treeHash":null,"usage":{"cachedInputTokens":427081,"inputTokens":194,"model":"claude-fable-5-1","outputTokens":12430,"runtime":"claude","turns":18,"wallClockMs":202502}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"27168b1ff68f84d2","findings":[],"hash":"bd1a672b5dd64ebbace3ad49ad19d81aa001c2894e52180cca388084597023b0","nodeId":"fa57bf41-93f6-4b7a-8df8-37c6bcfe9a1a","outcome":"completed","summary":"The findings file is in place at the repository root, excluded from git by the harness's own `.git/info/exclude` rule as intended, the scratch directory is removed, and no tracked file changed.\n\n**Result: no defects found in the assigned area.** The review covered Access Control, Trust Gap and Asymmetry against `src/OffsetsToken.sol`, and the file `.imd-findings.json` holds an empty findings list with eight coverage rows.\n\n**What was checked**\n\n- **Access control.** The ABI exposes exactly three state-changing functions. Each writes only state keyed by the caller's own identity: approve writes the caller's allowance, transfer moves the caller's balance, and transferFrom spends the caller's allowance from the named owner before moving funds. There is no owner, modifier, initializer, mint, burn, pause, blacklist, receive or fallback, and the constructor takes no arguments and only mints to the deployer.\n- **Asymmetry.** Both balance writers route through one internal transfer function. The allowance setter and the allowance decrement are the only allowance writers and each is guarded by the caller's identity. Self-transfer under the unchecked block, transferFrom with sender equal to recipient, a zero-address owner, and sticky unlimited allowance were all fuzzed or tested in a scratch suite and behaved correctly.\n- **Trust gap.** With no privileged actor and no economic formula beyond exact transfers, none of the four seams in the guide has an actor to exploit them.\n- **Launch floor.** Supply is a constant of one billion tokens at 18 decimals, minted once to msg.sender, and transfers move exactly the stated amount, so the factory, distributor and PoolManager flows arrive whole. Existing tests confirming no DELEGATECALL, CALLCODE or SELFDESTRUCT and refusal of plain ETH pass on this build.\n\n**Static analysis leads.** Slither reported nothing. Aderyn's large-numeric-literal note on line 23 is a style remark about the supply constant and not a defect, so it was left out.\n\n**Trust assumptions, not findings.** The ERC-20 approve race is inherent to the standard and is documented in the source and README. The Approval event emitted on each allowance decrement is permitted by the standard. Whoever deploys receives the full supply, which in the launch is the factory.\n\nThe deploy script was outside my area but is covered with a holds row since it only wraps the constructor. All 30 existing tests pass and formatting checks are clean.","treeHash":null,"usage":{"cachedInputTokens":465768,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":10137,"runtime":"claude","turns":19,"wallClockMs":178683}},{"artifacts":[],"attempt":1,"bundleHash":"ff08f48d04d6518c6b5942aed8c4ba8a3bf208942148177b7a95275527e43e0a","device":"b41d844dba698308","findings":[],"hash":"cde9c4818fb4febd781c5f2fac26d47252a7d8a7a2d578927c804106d5149fc8","nodeId":"a5c4fd36-166c-4ab3-b3c2-05911f57c9ab","outcome":"completed","summary":"Added 21 edge-case and fuzz tests plus three stateful invariants covering supply conservation, balances, allowances, and failure rollback.\n\nOffline `forge build` and `forge test` pass: **52 tests, zero failures**, including 24,576 randomized handler calls. Mutation checks caught all three seeded faults.\n\nNo confirmed implementation defects found. Only `test/` files were added.","treeHash":"a7d6ac0ce2c1490248dc5157dcbd5e11cc9cfa01","usage":{"cachedInputTokens":806784,"inputTokens":82445,"model":"gpt-6-astra","outputTokens":18004,"runtime":"codex","turns":7,"wallClockMs":544785}}],"verification":[{"checks":[{"durationMs":824,"exitCode":0,"name":"build","output":"Compiling 23 files with Solc 0.8.26\nSolc 0.8.26 finished in 723.91ms\nCompiler run successful!\n","passed":true},{"durationMs":79,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 30 tests for test/OffsetsToken.t.sol:OffsetsTokenTest\n[PASS] testFuzz_transferFromConservesSupply(uint256,uint256) (runs: 256, μ: 156424, ~: 159397)\nLogs:\n  Bound result 18\n  Bound result 9\n\n[PASS] testFuzz_transfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 221765, ~: 227599)\nLogs:\n  Bound result 636818812696957631389233174\n  Bound result 3948293327846055544241020\n  Bound result 0\n\n[PASS] test_approveOverwritesPreviousAllowance() (gas: 95331)\n[PASS] test_approveRevertsForZeroSpender() (gas: 32505)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68059)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8150)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 33666)\n[PASS] test_deployScriptMintsToItsCaller() (gas: 929069)\n[PASS] test_metadata() (gas: 26524)\n[PASS] test_mintGoesToWhoeverDeploys(address) (runs: 256, μ: 16058, ~: 16058)\n[PASS] test_noMintOrAdminFunctionExists() (gas: 513743)\n[PASS] test_noPrivilegedFunctionFreezesOrMovesAHolder() (gas: 448855)\n[PASS] test_plainEtherIsRefused() (gas: 39495)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1826848)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 24715)\n[PASS] test_transferFromBySelfStillNeedsAllowance() (gas: 38426)\n[PASS] test_transferFromRevertsBeyondAllowance() (gas: 95166)\n[PASS] test_transferFromRevertsOnInsufficientBalanceEvenWithAllowance() (gas: 95089)\n[PASS] test_transferFromRevertsToZeroAddress() (gas: 89924)\n[PASS] test_transferFromRevertsWithoutAllowance() (gas: 47341)\n[PASS] test_transferFromSpendsAllowance() (gas: 168381)\n[PASS] test_transferFromWithUnlimitedAllowanceKeepsIt() (gas: 135885)\n[PASS] test_transferMovesBalanceAndEmits() (gas: 93614)\n[PASS] test_transferRevertsFromEmptyAccount() (gas: 37674)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 111849)\n[PASS] test_transferRevertsToZeroAddress() (gas: 39510)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43625)\n[PASS] test_transferWholeBalance() (gas: 78165)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47500)\n[PASS] test_unknownSelectorReverts() (gas: 29490)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 7.88ms (28.06ms CPU time)\n\nRan 1 test suite in 8.57ms (7.88ms CPU time): 30 tests passed, 0 failed, 0 skipped (30 total tests)\n","passed":true},{"durationMs":43,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OffsetsToken.approve(address,uint256)\",\"OffsetsToken.transfer(address,uint256)\",\"OffsetsToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":8,\"README.md\":109,\"foundry.toml\":23,\"launch.json\":24,\"remappings.txt\":1,\"script/DeployOffsets.s.sol\":26,\"src/OffsetsToken.sol\":141,\"test/OffsetsToken.t.sol\":348},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"23fb0580d294c27cddab5606fc0e370b9991e837ea5714ee86dc484d9608c154","verifiedTreeHash":"377f848815851f1a876bc365bc72e94e993fbfb6","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":823,"exitCode":0,"name":"build","output":"Compiling 23 files with Solc 0.8.26\nSolc 0.8.26 finished in 726.28ms\nCompiler run successful!\n","passed":true},{"durationMs":86,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 30 tests for test/OffsetsToken.t.sol:OffsetsTokenTest\n[PASS] testFuzz_transferFromConservesSupply(uint256,uint256) (runs: 256, μ: 156704, ~: 159307)\nLogs:\n  Bound result 213234531218075577718119519\n  Bound result 5276\n\n[PASS] testFuzz_transfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 221403, ~: 227599)\nLogs:\n  Bound result 485273654999623864987838821\n  Bound result 8716945480160\n  Bound result 1400124451772\n\n[PASS] test_approveOverwritesPreviousAllowance() (gas: 95331)\n[PASS] test_approveRevertsForZeroSpender() (gas: 32505)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68059)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8150)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 33666)\n[PASS] test_deployScriptMintsToItsCaller() (gas: 929069)\n[PASS] test_metadata() (gas: 26524)\n[PASS] test_mintGoesToWhoeverDeploys(address) (runs: 256, μ: 16058, ~: 16058)\n[PASS] test_noMintOrAdminFunctionExists() (gas: 513743)\n[PASS] test_noPrivilegedFunctionFreezesOrMovesAHolder() (gas: 448855)\n[PASS] test_plainEtherIsRefused() (gas: 39495)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1826848)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 24715)\n[PASS] test_transferFromBySelfStillNeedsAllowance() (gas: 38426)\n[PASS] test_transferFromRevertsBeyondAllowance() (gas: 95166)\n[PASS] test_transferFromRevertsOnInsufficientBalanceEvenWithAllowance() (gas: 95089)\n[PASS] test_transferFromRevertsToZeroAddress() (gas: 89924)\n[PASS] test_transferFromRevertsWithoutAllowance() (gas: 47341)\n[PASS] test_transferFromSpendsAllowance() (gas: 168381)\n[PASS] test_transferFromWithUnlimitedAllowanceKeepsIt() (gas: 135885)\n[PASS] test_transferMovesBalanceAndEmits() (gas: 93614)\n[PASS] test_transferRevertsFromEmptyAccount() (gas: 37674)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 111849)\n[PASS] test_transferRevertsToZeroAddress() (gas: 39510)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43625)\n[PASS] test_transferWholeBalance() (gas: 78165)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47500)\n[PASS] test_unknownSelectorReverts() (gas: 29490)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 8.25ms (26.58ms CPU time)\n\nRan 1 test suite in 9.11ms (8.25ms CPU time): 30 tests passed, 0 failed, 0 skipped (30 total tests)\n","passed":true},{"durationMs":33,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OffsetsToken.approve(address,uint256)\",\"OffsetsToken.transfer(address,uint256)\",\"OffsetsToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":8,\"README.md\":109,\"foundry.toml\":23,\"remappings.txt\":1,\"script/DeployOffsets.s.sol\":26,\"src/OffsetsToken.sol\":141,\"test/OffsetsToken.t.sol\":348},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":326,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":212,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/OffsetsToken.sol:23: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"47ec79a80a2a1e0c4032fe0bf4a32209291acd84ec5e8b5964e184cf2bd6b965","verifiedTreeHash":"8da6a26d666f73396a15ace6dd2fb33c2537d5cc","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":1463,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.36s\nCompiler run successful!\n","passed":true},{"durationMs":7038,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 30 tests for test/OffsetsToken.t.sol:OffsetsTokenTest\n[PASS] testFuzz_transferFromConservesSupply(uint256,uint256) (runs: 256, μ: 157108, ~: 159327)\nLogs:\n  Bound result 14100919316156052962422\n  Bound result 49968050213\n\n[PASS] testFuzz_transfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 221841, ~: 227599)\nLogs:\n  Bound result 314308850589736995232070408\n  Bound result 3161207535213414589\n  Bound result 14489485\n\n[PASS] test_approveOverwritesPreviousAllowance() (gas: 95331)\n[PASS] test_approveRevertsForZeroSpender() (gas: 32505)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68059)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8150)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 33666)\n[PASS] test_deployScriptMintsToItsCaller() (gas: 929069)\n[PASS] test_metadata() (gas: 26524)\n[PASS] test_mintGoesToWhoeverDeploys(address) (runs: 256, μ: 16058, ~: 16058)\n[PASS] test_noMintOrAdminFunctionExists() (gas: 513743)\n[PASS] test_noPrivilegedFunctionFreezesOrMovesAHolder() (gas: 448855)\n[PASS] test_plainEtherIsRefused() (gas: 39495)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1826848)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 24715)\n[PASS] test_transferFromBySelfStillNeedsAllowance() (gas: 38426)\n[PASS] test_transferFromRevertsBeyondAllowance() (gas: 95166)\n[PASS] test_transferFromRevertsOnInsufficientBalanceEvenWithAllowance() (gas: 95089)\n[PASS] test_transferFromRevertsToZeroAddress() (gas: 89924)\n[PASS] test_transferFromRevertsWithoutAllowance() (gas: 47341)\n[PASS] test_transferFromSpendsAllowance() (gas: 168381)\n[PASS] test_transferFromWithUnlimitedAllowanceKeepsIt() (gas: 135885)\n[PASS] test_transferMovesBalanceAndEmits() (gas: 93614)\n[PASS] test_transferRevertsFromEmptyAccount() (gas: 37674)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 111849)\n[PASS] test_transferRevertsToZeroAddress() (gas: 39510)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43625)\n[PASS] test_transferWholeBalance() (gas: 78165)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47500)\n[PASS] test_unknownSelectorReverts() (gas: 29490)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 412.90ms (851.75ms CPU time)\n\nRan 21 tests for test/OffsetsToken.EdgeCases.t.sol:OffsetsTokenEdgeCasesTest\n[PASS] testFuzz_approvalReplacementAndRepetitionDoNotAccumulate(uint256,uint256) (runs: 1000, μ: 889242, ~: 889345)\n[PASS] testFuzz_contractCREATE2DeployerReceivesAndCanForwardWholeSupply(bytes32) (runs: 1000, μ: 353227, ~: 353327)\n[PASS] testFuzz_delegatedOverdraftRollsBackFiniteOrUnlimitedApproval(uint256,uint256,bool) (runs: 1000, μ: 867682, ~: 866989)\nLogs:\n  Bound result 999999999999999999999999998\n  Bound result 442690180989931116928646244975038028604333334555769651181494\n\n[PASS] testFuzz_insufficientAllowanceCannotBeSpent(uint256,uint256) (runs: 1000, μ: 809126, ~: 810422)\nLogs:\n  Bound result 182897586385271441695701641\n  Bound result 82144115754927113912428610\n\n[PASS] testFuzz_splitDirectTransfersEqualOneDelegatedTransfer(uint256,uint256) (runs: 1000, μ: 296014, ~: 296870)\nLogs:\n  Bound result 904162930\n  Bound result 3620307123742810199068\n\n[PASS] testFuzz_transferOverdraftIsAtomic(uint256,uint256) (runs: 1000, μ: 862159, ~: 862937)\nLogs:\n  Bound result 39659262838212976302667375\n  Bound result 210301085480287654297973898996671182897586385271441695701641\n\n[PASS] testFuzz_transferRoundTripRestoresBalancesAndLeavesApprovals(uint256) (runs: 1000, μ: 937854, ~: 937512)\nLogs:\n  Bound result 3000000000000000000\n\n[PASS] testFuzz_transferToAnyNonzeroAddressConservesSupply(address,uint256) (runs: 1000, μ: 106163, ~: 106332)\nLogs:\n  Bound result 1\n  Bound result 1000000000000000000\n\n[PASS] testFuzz_zeroRecipientRollsBackFiniteOrUnlimitedApproval(uint256,bool) (runs: 1000, μ: 808339, ~: 806639)\nLogs:\n  Bound result 32754232417042187018\n\n[PASS] test_delegatedSelfTransferConsumesOnlyItsFiniteAllowance() (gas: 240542)\n[PASS] test_entireSupplyCanBeDelegatedButSpentAllowanceCannotBeReused() (gas: 951097)\n[PASS] test_failedSpendCanBeRetriedAfterHolderIsFunded() (gas: 960316)\n[PASS] test_maximumFiniteAllowanceIsNotTreatedAsUnlimited() (gas: 240192)\n[PASS] test_maximumTransferAmountsRejectWithoutArithmeticPanic() (gas: 1196656)\n[PASS] test_oneMinorUnitCanMoveAndReturn() (gas: 210166)\n[PASS] test_ownerCanExplicitlyApproveItselfAndBeAllThreeTransferFromRoles() (gas: 115336)\n[PASS] test_permissionsAreIsolatedByBothOwnerAndSpender() (gas: 1100983)\n[PASS] test_selfTransferBoundariesDoNotCreateTokensOrBypassBalanceChecks() (gas: 1926039)\n[PASS] test_unlimitedAllowanceCanBeReducedRevokedAndRegranted() (gas: 1159228)\n[PASS] test_zeroAmountsStillRejectZeroRecipientAndSpender() (gas: 803865)\n[PASS] test_zeroTransfersFromEmptyHoldersEmitAndPreserveState() (gas: 1158150)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 416.53ms (3.58s CPU time)\n\nRan 1 test for test/OffsetsToken.Invariant.t.sol:OffsetsTokenInvariantTest\n[PASS]\nOffsetsTokenInvariantTest invariants:\n[PASS] invariant_allowancesMatchOwnerAuthorization\n[PASS] invariant_eachHolderHasExactlyItsEntitlement\n[PASS] invariant_fixedSupplyEqualsAllBalances\n OffsetsTokenInvariantTest invariants (runs: 256, calls: 24576, reverts: 0)\n\n╭---------------------+-------------------------+-------+---------+----------╮\n| Contract            | Selector                | Calls | Reverts | Discards |\n+============================================================================+\n| OffsetsTokenHandler | approve                 | 2680  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | approveAndTransferFrom  | 2774  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | rejectAllowanceOverrun  | 2722  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | rejectDelegatedOverdraw | 2706  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | rejectOverdraw          | 2754  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | rejectZeroRecipient     | 2744  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | rejectZeroSpender       | 2827  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | transfer                | 2680  | 0       | 0        |\n|---------------------+-------------------------+-------+---------+----------|\n| OffsetsTokenHandler | transferFrom            | 2689  | 0       | 0        |\n╰---------------------+-------------------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.95s (6.94s CPU time)\n\nRan 3 test suites in 6.95s (7.77s CPU time): 52 tests passed, 0 failed, 0 skipped (52 total tests)\n","passed":true},{"durationMs":31,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OffsetsToken.approve(address,uint256)\",\"OffsetsToken.transfer(address,uint256)\",\"OffsetsToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":8,\"README.md\":109,\"foundry.toml\":23,\"remappings.txt\":1,\"script/DeployOffsets.s.sol\":26,\"src/OffsetsToken.sol\":141,\"test/OffsetsToken.EdgeCases.t.sol\":412,\"test/OffsetsToken.Invariant.t.sol\":278,\"test/OffsetsToken.t.sol\":348,\"test/README.md\":31},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"cde9c4818fb4febd781c5f2fac26d47252a7d8a7a2d578927c804106d5149fc8","verifiedTreeHash":"a7d6ac0ce2c1490248dc5157dcbd5e11cc9cfa01","verifierVersion":"0.1.0+fb8278c5"}]}