{"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":"90b38805-0b70-4d48-9d21-bc90f7447a10","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"0ca9faa21d5012e873f2cfd4315507d415411ed89b32d0490abfd3b702913132","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":"3ee4dcc680873bdb5f69e7ca16bbde0ba60e09c916f5f5bf10b5917e043d0fce","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":"931427e83b54fb86a379931dfdf6fdf894a4e80d65d7ddb6543f15d1a740b1f2","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":"41145d14bd21c9df792a22121e986aa955c4e48e60cd30bcf158cd8333bf2252","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":"fad310bf3083b585243ca60a1d6858bffac809cc6196a7a5a4a4641f3cfd1d68","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":"46b77e6e3c84f03e0c3af23322f42b937cdfa716f523a15c2fa9c6cecf99b22d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"d59561da3b378461b7c749f6bd5084477d44993aa94972ddea90f542535751df","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"d59561da3b378461b7c749f6bd5084477d44993aa94972ddea90f542535751df","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"be126f0e7bfdc7ad2b43214d3e6bd855b3b4d2efb46fc37cd5053b5d0c7e545d","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"300497cd40d1c87e22bf522e2399417cc1a137fd01c6c12e71ff8d7520aecd19","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","state":"accepted"}],"objective":"A custom token: Mutually Assured Destruction (MAD).\nToken name: Mutually Assured Destruction\nToken symbol: MAD\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"6702b3ba2f0e7a449e5438f6a39f21406a85ccc483664eb9773310de91266d0e","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"90b38805-0b70-4d48-9d21-bc90f7447a10","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2427-mutually-assured-destruction"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52170","feedbackHash":"35554d2cab5217ab2b4c47aef92d6a18ad57b834704e3a62156a306a43ce9338","nodeKey":"audit_economics","submissionHash":"0ca9faa21d5012e873f2cfd4315507d415411ed89b32d0490abfd3b702913132","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53929","feedbackHash":"171b87881c45854965d5298f0d270159196283aed25068dafa8560c3197ad99d","nodeKey":"audit_flow","submissionHash":"3ee4dcc680873bdb5f69e7ca16bbde0ba60e09c916f5f5bf10b5917e043d0fce","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52596","feedbackHash":"d770f715bb02e12f437930263f7836068f01e1058e244f47ef2264f65056ee05","nodeKey":"audit_judge","submissionHash":"931427e83b54fb86a379931dfdf6fdf894a4e80d65d7ddb6543f15d1a740b1f2","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51374","feedbackHash":"c9294abbee3a29897190b76f0a4fea6129b8ba5a7bd1d5377323f40887ed0749","nodeKey":"audit_math","submissionHash":"41145d14bd21c9df792a22121e986aa955c4e48e60cd30bcf158cd8333bf2252","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52205","feedbackHash":"7110a07b47122b99eaf0c931054ed017962dca002154cf72c613a09b655d846d","nodeKey":"audit_permissions","submissionHash":"fad310bf3083b585243ca60a1d6858bffac809cc6196a7a5a4a4641f3cfd1d68","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52199","feedbackHash":"7c978ee41056e6513906ae9a20559a998ff2c09a0dc74156b07b8b7ee5588431","nodeKey":"build_contract_project","submissionHash":"46b77e6e3c84f03e0c3af23322f42b937cdfa716f523a15c2fa9c6cecf99b22d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51493","feedbackHash":"0087721d38b45d27235d34a04e48dd7fdf9292d73159f294cc1dfe2737658e9a","nodeKey":"manifest","submissionHash":"be126f0e7bfdc7ad2b43214d3e6bd855b3b4d2efb46fc37cd5053b5d0c7e545d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51144","feedbackHash":"d196f7e32a6383cb2522322ad332bc254a1e376d16d4166886cd3e02a065f034","nodeKey":"write_foundry_tests","submissionHash":"300497cd40d1c87e22bf522e2399417cc1a137fd01c6c12e71ff8d7520aecd19","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"0cc35a624f2fad2acb6159d03fc0388e7f5adc6468da15589f82c9316de11cdd","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"fa99051b60a858d6","findings":[],"hash":"0ca9faa21d5012e873f2cfd4315507d415411ed89b32d0490abfd3b702913132","nodeId":"7ab45038-9f88-4499-8548-4462c8bd80ce","outcome":"completed","summary":"Review complete. The findings file holds an empty findings list and nine coverage rows. The working tree is clean apart from the untracked `.imd-findings.json`, which git status does not list because `.gitignore` covers it.\n\n**Result: no defects found in the economics area.** MAD is a plain fixed-supply ERC-20 with nothing that the Economic Security, Invariant or Flow Gap guides can break.\n\nWhat I checked, with concrete evidence:\n\n- **Supply conservation.** The total supply is a constant equal to the one-time constructor mint to the deployer. The compiled ABI has only three nonpayable functions and no fallback or receive, so no path grows or shrinks supply. The repo's stateful invariant suite and my scratch probes confirmed the balance sum stays at the full supply across every call sequence.\n- **Launch flows.** A scratch probe deployed the token through a CREATE2 factory, moved ten percent to a distributor and on to a claimant, settled sixty percent into a Uniswap v4 style sync/settle/take model, and sent the remainder to the requester's address. Every leg paid exactly what was sent, and buy and sell legs through the manager model were exact. No exemptions are needed because nothing is taxed.\n- **Privileged powers.** There is no owner, role, initializer or admin selector. The protected floor's pause, freeze, seize, mint and burnFrom selectors all hit the missing-fallback revert. The runtime opcode scan from the protected test finds no reachable DELEGATECALL, CALLCODE or SELFDESTRUCT.\n- **Entry point boundaries.** Unlimited allowance stays sticky, finite allowance decrements and rolls back atomically on a reverted transfer, zero-address sender, receiver and spender all revert, and self transfers preserve balance.\n\nTwo items are noted in the coverage record rather than as findings. The ordinary ERC-20 approve race is standard behaviour the README already documents. The manifest row is marked unreached because no launch.json exists in the tree yet. The aderyn large-literal note is cosmetic and the literal evaluates to the correct supply.","treeHash":null,"usage":{"cachedInputTokens":778062,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":13813,"runtime":"claude","turns":19,"wallClockMs":189781}},{"artifacts":[],"attempt":1,"bundleHash":"27a0b5bfc8965708033f8e2168c5c585b9b5a291bef3f206bf67f87abce795d4","device":"91067b3439961e55","findings":[],"hash":"300497cd40d1c87e22bf522e2399417cc1a137fd01c6c12e71ff8d7520aecd19","nodeId":"31c3ed02-faee-4a65-8c66-01000d58150c","outcome":"completed","summary":"I added two test files and found no defects in `MADToken`, so I didn't write `.imd-findings.json`. All 59 tests pass with the verifier's fuzz seed: the 34 that were already there and 25 new ones. `forge build` is clean. The only new files are the two below, and I didn't change the existing tests, `src/` or any configuration.\n\n**`test/MADToken.stateful.t.sol`**: invariant tests over random call sequences, set to 256 runs × 64 calls in the file itself.\n- A handler drives `transfer`, `approve` and `transferFrom` with both valid and invalid inputs:\n  - amounts above the balance or the allowance, up to the maximum value;\n  - the zero address as sender, receiver, approver or spender;\n  - allowances of `max - 1` and of more than the supply;\n  - the token contract and a contract that rejects calls as holders;\n  - owner, spender and recipient being the same address in every combination.\n- Every call that should fail must fail with the exact error the ERC-20 rules predict. Every call that should succeed must return exactly one `true` word.\n- The invariants check that:\n  - all balances add up to the fixed supply and match a separate record of who should hold what;\n  - every allowance matches that record, and the zero address has none;\n  - nobody spends more through finite allowances than owners granted.\n- A final check fails any run where no failure path or edge input was actually reached, so the suite can't pass without testing anything.\n- To check the invariants can fail, I ran them against a deliberately broken copy of the token (allowance not fully reduced after spending). All three caught it.\n\n**`test/MADToken.edge.t.sol`**: 24 unit and fuzz tests for gaps in the existing suite:\n- the order of errors (allowance is checked before sender, receiver and balance);\n- raw return data;\n- that `transferFrom` emits only `Transfer`, `approve` only `Approval`, and failed calls emit nothing;\n- boundary amounts: the maximum value, one unit over the balance, `max - 1` allowances, allowances above the supply;\n- tokens sent to the token contract stay stuck there;\n- deploying the token and distributing from it in a single transaction;\n- fuzzed approvals, unlimited allowances that never decrease, lossless round trips, and an over-balance `transferFrom` that leaves the allowance unchanged.\n\nTwo behaviours are intended and documented rather than defects:\n- **Owner needs an allowance:** the owner needs an allowance to call `transferFrom` on their own tokens.\n- **Stuck tokens:** tokens sent to the contract's own address can't be recovered.\n\nBoth are within ERC-20.","treeHash":"1486d0de790ec64ee1c2f7979c5026c82efe5f3a","usage":{"cachedInputTokens":524138,"inputTokens":22,"model":"claude-opus-5-5","outputTokens":16277,"runtime":"claude","turns":15,"wallClockMs":176826}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"23617eab0c5242d6","findings":[],"hash":"3ee4dcc680873bdb5f69e7ca16bbde0ba60e09c916f5f5bf10b5917e043d0fce","nodeId":"d92e8826-d6e9-4108-b299-cc35b403902b","outcome":"completed","summary":"I found no defects in the MAD token. `.imd-findings.json` holds an empty findings list plus a coverage record that answers all three entry points.\n\n**What I covered:** I traced every path through `src/MADToken.sol` against the Execution Trace, Periphery and First Principles guides. That includes the constructor and each function's checks, state changes, failure paths and revert rollback. I also checked the launch flows: the factory sending the swarm's share to the distributor, claims, and the pool manager taking tokens in and paying them out on swaps. The existing tests (34 unit, fuzz and invariant tests) all pass.\n\n**Coverage rows:**\n- **`approve`** – holds. It rejects a zero spender, replaces the allowance and emits Approval, with no external call. The known approve race is part of how ERC-20 works, and the README already warns holders about it.\n- **`transfer`** – holds. It debits the sender, then credits the recipient, with overflow checks, so sending to yourself keeps your balance. Transfers from or to the zero address revert. There is no fee, burn or exemption, so the factory, distributor and pool manager move exactly the amounts they state.\n- **`transferFrom`** – holds. It checks the allowance first, lowers a finite allowance by the amount and leaves an unlimited one unchanged. If the transfer then fails, the allowance change is undone too. The zero address can never hold an allowance, and the transfer would reject it anyway.\n- **Two extra invariant rows** – both hold:\n  - The supply is fixed at 10^27 and minted once to the deployer, with no mint, burn, owner, DELEGATECALL or SELFDESTRUCT path.\n  - Balances always add up to the total supply.\n\n**Static analysis leads:**\n- Slither reported nothing.\n- Aderyn's single low result flags the large number at `src/MADToken.sol:14`. It is the intended supply constant (`1_000_000_000 * 10 ** 18`), so it is not a defect.\n\n**Not covered:**\n- I could not run the protected launch tests here, because they depend on launch-system contracts that are not in this repository. They remain the verifier's job.\n- There is no `launch.json` yet, so there was no manifest to review.\n\nI changed no repository files apart from writing `.imd-findings.json`.","treeHash":null,"usage":{"cachedInputTokens":145860,"inputTokens":8,"model":"claude-opus-5-5","outputTokens":2062,"runtime":"claude","turns":4,"wallClockMs":32811}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"13603a08ada71730","findings":[],"hash":"41145d14bd21c9df792a22121e986aa955c4e48e60cd30bcf158cd8333bf2252","nodeId":"9c0dbe26-3b7a-4f4a-9857-b5c3aff409ed","outcome":"completed","summary":"I found no defects in the math, boundary or precision areas of `src/MADToken.sol`. `.imd-findings.json` holds an empty findings list and a coverage row for each entry point, all marked `holds`. The project's existing 34 tests pass, including the invariant test, which makes about 8,200 calls with no reverts.\n\n- **Supply:** `INITIAL_SUPPLY = 1_000_000_000 * 10 ** 18` comes to 1e27, which matches the stated supply and is far below the uint256 limit. Aderyn's \"large numeric literal\" warning points at this correct constant, so it is not a defect. No function can mint or burn, and transfers keep the total exact, with no fee or rounding.\n- **`transfer`:** the balance is checked before it is reduced, so the subtraction can't underflow. The addition can't overflow because no balance can exceed the fixed supply. Sending to yourself leaves your balance unchanged, because the receiver's balance is read after the sender's is reduced. Zero-value transfers succeed, and sending from or to the zero address reverts.\n- **`transferFrom`:** spending exactly the allowance leaves it at 0, and spending more reverts. An unlimited (`type(uint256).max`) allowance is never reduced. A failed call reverts as a whole, so no partial allowance change remains. Pulling from the zero address is impossible because it can never approve anyone.\n- **`approve`:** it stores the value exactly as given and does no arithmetic. Approving the zero address as spender reverts.\n\nThe rest of the review standard also held: the token has no owner and no privileged functions, it never calls another contract, and it has no fee or burn that could make a launch transfer arrive short. I wrote no proof tests, since there was nothing to prove, and changed no project files.","treeHash":null,"usage":{"cachedInputTokens":156886,"inputTokens":8,"model":"claude-opus-5-5","outputTokens":2111,"runtime":"claude","turns":4,"wallClockMs":34843}},{"artifacts":[],"attempt":1,"bundleHash":"c1f3eaff0f0a33eb60799f2deb4b5fffd7b58d2a14b785fb44722e484e39c4de","device":"410d15d57eeec440","findings":[],"hash":"46b77e6e3c84f03e0c3af23322f42b937cdfa716f523a15c2fa9c6cecf99b22d","nodeId":"0390b5e2-603e-4017-9f4c-0a33ed845e8c","outcome":"completed","summary":"Implemented MAD with 1,000,000,000 tokens, 18 decimals, minted once to the deployer. Includes deployment documentation and no external dependencies.\n\nVerified with Solidity 0.8.26:\n\n- `forge build` passed.\n- `forge test` passed: 34 tests using the specified seed.\n- `forge fmt --check` passed.\n\nTests cover success, failure, fuzzing, and 8,192 stateful invariant actions. Protected launch integration checks remain for the independent verifier.","treeHash":"1b5ac41d27b0510a43096694097f26aeffdcd873","usage":{"cachedInputTokens":640896,"inputTokens":58309,"model":"gpt-6-astra","outputTokens":18605,"runtime":"codex","turns":6,"wallClockMs":462409}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"629987aaf6c7aa88","findings":[{"citation":"resolved","description":"Merged from audit_permissions (its only finding; audit_flow, audit_economics, audit_math and the test writer reported nothing). `approve` (src/MADToken.sol:42-48) unconditionally replaces the stored allowance and `transferFrom` (src/MADToken.sol:53-61) debits whatever is stored at execution time, so there is no atomic 'change from X to Y' primitive and no increaseAllowance/decreaseAllowance/permit helper. A spender who sees an owner's replacement approve pending can order a pull of the old amount first and then pull the new amount. This is exactly the behaviour ERC-20 specifies and OpenZeppelin v5 ships; README lines 27 and 77 already document the revoke-then-approve mitigation. It is a property of the standard, not an implementation defect, and does not affect any launch flow (the factory, distributor and PoolManager legs all use `transfer` or a single-shot `transferFrom` of an exact amount). Kept at info so the examined asymmetry is on record; no revision is needed unless the requester wants allowance-adjustment helpers added to the design.","line":45,"path":"src/MADToken.sol","reproduction":"State: deploy MADToken from the test contract (it receives 1e27), transfer 1000e18 to alice; bob holds 0. Steps: (1) vm.prank(alice); token.approve(bob, 100e18). (2) vm.prank(bob); token.transferFrom(alice, bob, 100e18) -> allowance[alice][bob] = 0, bob = 100e18. (3) vm.prank(alice); token.approve(bob, 50e18) (alice's intended 'lower to 50e18'). (4) vm.prank(bob); token.transferFrom(alice, bob, 50e18) succeeds. Actual: balanceOf(bob) = 150e18, balanceOf(alice) = 850e18, allowance = 0. Expected by the owner: at most 100e18 moved. Verified by test/scratch/ApproveRace.t.sol::test_spenderCanSpendOldPlusNewAllowance, which passes on the current code (the sequence executes as described).","severity":"info","snippet":"        allowance[msg.sender][spender] = value;","title":"approve overwrites a non-zero allowance, so a spender who front-runs a replacement approval can spend old plus new (standard ERC-20 ordering race; documented in README, no code change required)"}],"hash":"931427e83b54fb86a379931dfdf6fdf894a4e80d65d7ddb6543f15d1a740b1f2","nodeId":"880224da-6668-4e79-ace2-3188263ef272","outcome":"completed","summary":"The review is complete and written to `.imd-findings.json`. The working tree is otherwise untouched (the findings file and `test/scratch/` are gitignored).\n\n**Outcome:** no defects that would reopen the author's work. The MAD token is a minimal fixed-supply ERC-20 and it behaves as specified.\n\n**What I verified against the code**\n\n- All 59 project tests pass with the pinned fuzz seed, and `forge fmt --check` is clean.\n- The constructor takes no arguments and mints exactly 10^27 units to msg.sender, matching the manifest's empty constructorArgs and totalSupply. Under the factory's CREATE2 deployment the factory receives the whole supply.\n- Creation code is 1,595 bytes and runtime 1,487 bytes, far below the size limits.\n- A reachable-opcode scan of the runtime finds no CALL, STATICCALL, DELEGATECALL, CALLCODE or SELFDESTRUCT. There is no owner, mint, burn, pause, blacklist, proxy, receive or fallback.\n- Transfers move exactly the requested amount, so the distributor, seed and swap legs the protected floor checks cannot arrive short.\n- The aderyn large-numeric-literal lead is a readable constant equal to the manifest supply. Dropped as a style note.\n\n**Specialist findings**\n\nFour specialists and the test writer reported one finding in total, from the permissions area. I reproduced it with a scratch test and kept it at its original info severity. It is the standard ERC-20 approve overwrite race: a spender who front-runs a replacement approval can pull the old amount plus the new one. This is the behaviour the standard specifies and the README already documents the revoke-then-approve mitigation. No launch flow depends on replacing a non-zero allowance. No revision is required unless the requester wants allowance-adjustment helpers added to the design.\n\n**Coverage record**\n\nAll three ABI entry points are answered: `approve` carries the info finding, `transfer` and `transferFrom` hold. I added rows for the constructor and deployment model, the constant-supply and no-privileged-control invariant, and the static-analysis lead.","treeHash":null,"usage":{"cachedInputTokens":422692,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":7780,"runtime":"claude","turns":15,"wallClockMs":121519}},{"artifacts":[],"attempt":1,"bundleHash":"f309292d1b98426e0630a91546e12d44cc13a68e44b0d37ad17355cd4191a65a","device":"74979c69cdd583ad","findings":[],"hash":"be126f0e7bfdc7ad2b43214d3e6bd855b3b4d2efb46fc37cd5053b5d0c7e545d","nodeId":"19ed6312-aac6-4043-9e4d-db1506650c9c","outcome":"completed","summary":"I wrote `launch.json` for the MAD launch. It parses as valid JSON, and `forge build` and `forge test` (run with the verifier's fuzz seed) pass: 34 of 34 tests. Nothing checks it against the manifest schema itself, so I checked the fields by reading them. No other file was changed.\n\nWhat the manifest says, based on `src/MADToken.sol`:\n- **Token:** contract `MADToken`, named \"Mutually Assured Destruction\", symbol MAD, 18 decimals.\n- **Constructor arguments:** none (`[]`), because the constructor takes no parameters.\n- **Supply:** `\"1000000000000000000000000000\"` in minor units (1,000,000,000 × 10^18). This is the amount the constructor mints once to `msg.sender`.\n- **Application contracts:** none. The accepted code contains only the token and its ERC-20 interface.\n- **Pool:** the FWA pair token at `0xa0df17b5ac76ababa36e1450e2cbcd18a620c845`, fee 12500, tick spacing 60, initial price `79228162514264337593543950336` (one to one).\n- **Economics:** copied exactly from the job.\n- **Notes:** a short description of the token. It has a fixed supply, no admin powers, and no mint, burn, fee or pause path.","treeHash":"1a62a2d7dc0685ac78f63ac97b73cfa7a6f1ebdc","usage":{"cachedInputTokens":82323,"inputTokens":6,"model":"claude-opus-5-5","outputTokens":1079,"runtime":"claude","turns":3,"wallClockMs":24084}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"fa5c50e7abe46571","findings":[{"citation":"resolved","description":"Area: Asymmetry (approve <-> pull pair). `approve` overwrites the allowance unconditionally (src/MADToken.sol:45) while `transferFrom` (src/MADToken.sol:54-58) decrements whatever value is stored at execution time. The two sides of the pair do not share any notion of the allowance the owner believed was outstanding, so a spender who orders a pull between an owner's two approvals spends the sum of both. This is the behaviour the ERC-20 standard itself specifies and OpenZeppelin v5 ships the same; the README (lines 27 and 77) already documents the revoke-then-approve mitigation and the contract offers no increaseAllowance/decreaseAllowance or permit. Reported for completeness so the judge can see the asymmetry was examined; it is not a bug in this implementation and no fix is required unless the requester wants atomic allowance adjustment helpers. Every access-control and trust-gap check in the assigned area otherwise holds: there is no owner, role, modifier, initializer, proxy, external call, DELEGATECALL/CALLCODE/SELFDESTRUCT or CALL in the runtime (opcode scan of out/MADToken.sol/MADToken.json), `balanceOf` is written only by `_transfer` reached from `transfer` (msg.sender as source) and `transferFrom` (allowance[from][msg.sender] as guard), and `allowance` is written only by `approve` (msg.sender as owner) and by `transferFrom` (only its own allowance[from][msg.sender], only downward). The deployer/factory holds nothing but its ordinary balance after the constructor.","line":45,"path":"src/MADToken.sol","reproduction":"State: alice holds 1000e18 MAD, bob holds 0. Sequence: (1) vm.prank(alice); token.approve(bob, 100e18). (2) alice broadcasts approve(bob, 50e18) intending to lower the allowance; bob sees it pending and gets transferFrom(alice, bob, 100e18) ordered first: allowance 100e18 -> 0, bob +100e18. (3) alice's approve(bob, 50e18) executes: allowance = 50e18. (4) vm.prank(bob); token.transferFrom(alice, bob, 50e18) succeeds. Actual: bob holds 150e18, alice holds 850e18, allowance 0. Expected by the owner: at most 100e18 moved (the larger of the two grants). Verified with test/scratch/ApproveRace.t.sol::test_spenderCanSpendOldPlusNewAllowance (passes on current code, i.e. the sequence executes as described).","severity":"info","snippet":"        allowance[msg.sender][spender] = value;","title":"approve/transferFrom pair: replacing a non-zero allowance lets the spender take old plus new amounts (standard ERC-20 ordering race, documented in README)"}],"hash":"fad310bf3083b585243ca60a1d6858bffac809cc6196a7a5a4a4641f3cfd1d68","nodeId":"78914a5e-f08e-4b7c-9b92-fd045080af85","outcome":"completed","summary":"The review is complete and the findings file is written and validated.\n\n**Outcome:** the assigned area is clean. `.imd-findings.json` holds one informational finding and eight coverage rows, with every listed entry point answered.\n\n**What I checked, against the Access Control, Trust Gap and Asymmetry guides**\n\n- **Permission model.** The token has no owner, role, modifier, initializer, proxy or external call. The only writers of `balanceOf` are `transfer` and `transferFrom` through the shared private `_transfer`, and the only writers of `allowance` are `approve` on the caller's own row and `transferFrom` decrementing its own row. No guard is weaker than its mirror.\n- **Deployment and trust.** The constructor takes no arguments and mints the whole supply once to the immediate deployer, which is the factory at launch. Nothing is left for a first outside caller to claim, and the factory holds no power beyond an ordinary balance. A scratch test confirmed the deployer cannot move a holder's funds without an allowance.\n- **Launch flows.** There is no fee, exemption list or hook, so the distributor, pool seed and swap legs move exactly the stated amounts. An opcode scan of the compiled runtime found no DELEGATECALL, CALLCODE, SELFDESTRUCT or CALL.\n- **Asymmetry.** `transfer` and `transferFrom` share identical zero-address and balance checks. The existing unit, fuzz and invariant suites all pass.\n\n**The one finding, severity info:** `approve` overwrites an allowance unconditionally while `transferFrom` pulls whatever is stored at execution time, so a spender who orders a pull between an owner's two approvals spends the sum. I reproduced it in `test/scratch/ApproveRace.t.sol` with concrete balances. This is the ERC-20 standard's own behaviour, matches OpenZeppelin v5, and the README already documents the revoke-then-approve mitigation. I recorded it so the judge can see the approve/pull pair was examined, not as something the author must change.\n\n**Not done:** no proof file was attached because nothing reached high or critical severity, and forge-std is not vendored in this tree in any case. The aderyn \"large numeric literal\" lead is a style note on the supply constant and not a defect. The scratch test is in the ignored `test/scratch/` directory and nothing else in the tree was modified.","treeHash":null,"usage":{"cachedInputTokens":784524,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":12085,"runtime":"claude","turns":28,"wallClockMs":184952}}],"verification":[{"checks":[{"durationMs":674,"exitCode":0,"name":"build","output":"Compiling 7 files with Solc 0.8.26\nSolc 0.8.26 finished in 625.66ms\nCompiler run successful!\n","passed":true},{"durationMs":6743,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 33 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_excessiveAllowanceSpendReverts(uint256) (runs: 256, μ: 106490, ~: 107117)\n[PASS] testFuzz_excessiveTransferRevertsWithoutChanges(uint256) (runs: 256, μ: 54486, ~: 54452)\n[PASS] testFuzz_selfTransferConservesBalance(uint256) (runs: 256, μ: 40882, ~: 40885)\n[PASS] testFuzz_spendingFiniteApproval(uint256,uint256) (runs: 256, μ: 137062, ~: 138186)\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 75954, ~: 76288)\n[PASS] test_approvalDoesNotRequireBalanceOrMoveTokens() (gas: 87224)\n[PASS] test_approvalEmitsAndCanBeOverwrittenAndRevoked() (gas: 183997)\n[PASS] test_approvalRejectsZeroApprover() (gas: 32969)\n[PASS] test_approvalRejectsZeroSpender() (gas: 54172)\n[PASS] test_approvalsAreIsolatedByOwnerAndSpender() (gas: 192143)\n[PASS] test_constructorEmitsSingleSupplyMint() (gas: 8450)\n[PASS] test_entireSupplyCanRoundTrip() (gas: 127166)\n[PASS] test_factoryDeploymentMintsOnlyToImmediateDeployer() (gas: 206608)\n[PASS] test_launchAndTradingTokenLegsTransferExactAmounts() (gas: 536736)\n[PASS] test_metadataAndInitialSupply() (gas: 70289)\n[PASS] test_noMintBurnFreezeSeizeOrUpgradeEntryPoints() (gas: 1433525)\n[PASS] test_rejectsNativeCurrencyAndUnknownCalls() (gas: 58533)\n[PASS] test_selfTransferPreservesBalance() (gas: 40363)\n[PASS] test_selfTransferStillRequiresBalance() (gas: 35753)\n[PASS] test_transferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 229827)\n[PASS] test_transferFromInsufficientBalanceRollsBackAllowance() (gas: 169438)\n[PASS] test_transferFromPreservesUnlimitedAllowanceAcrossTransfers() (gas: 202094)\n[PASS] test_transferFromRejectsUnapprovedSpender() (gas: 99086)\n[PASS] test_transferFromRejectsZeroSource() (gas: 38104)\n[PASS] test_transferFromRequiresAllowanceEvenWhenCallerIsOwner() (gas: 140087)\n[PASS] test_transferFromToSelfConsumesAllowanceWithoutChangingBalance() (gas: 98959)\n[PASS] test_transferFromZeroRecipientRollsBackAllowance() (gas: 97740)\n[PASS] test_transferFromZeroValueNeedsNoAllowance() (gas: 52910)\n[PASS] test_transferRejectsZeroRecipientEvenForZeroValue() (gas: 63860)\n[PASS] test_transferRejectsZeroSender() (gas: 32986)\n[PASS] test_transferReturnsTrueAndEmitsExactAmount() (gas: 82331)\n[PASS] test_transferToContractDoesNotCallRecipient() (gas: 165950)\n[PASS] test_zeroTransferFromEmptyBalanceEmitsEvent() (gas: 56977)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 28.65ms (124.35ms CPU time)\n\nRan 24 tests for test/MADToken.edge.t.sol:MADTokenEdgeTest\n[PASS] testFuzz_approveStoresAnyValue(address,address,uint256) (runs: 1000, μ: 63836, ~: 64257)\n[PASS] testFuzz_roundTripIsLossless(address,uint256) (runs: 1000, μ: 101255, ~: 101882)\n[PASS] testFuzz_transferFromAboveBalanceRevertsAndKeepsAllowance(uint256,uint256) (runs: 1000, μ: 170709, ~: 171009)\n[PASS] testFuzz_unlimitedAllowanceNeverDecreases(uint256,uint256) (runs: 1000, μ: 210187, ~: 210860)\n[PASS] test_allowanceAboveSupplyIsStoredVerbatim() (gas: 135625)\n[PASS] test_allowanceOfReceiverUnaffectedByIncomingTransfer() (gas: 124504)\n[PASS] test_allowanceOneBelowMaxIsFiniteAndDecreases() (gas: 120822)\n[PASS] test_approveAndTransferFromReturnExactlyOneTrueWord() (gas: 112663)\n[PASS] test_approveEmitsOnlyApproval() (gas: 59640)\n[PASS] test_deployAndDistributeInOneTransaction() (gas: 282941)\n[PASS] test_eachDeploymentMintsIndependently() (gas: 81115)\n[PASS] test_failedCallsEmitNothing() (gas: 84217)\n[PASS] test_selfApprovalByContractHolderSpendsLikeAnyOther() (gas: 117299)\n[PASS] test_supplyIsExactlyTenToTheTwentySeventh() (gas: 16414)\n[PASS] test_tokensSentToTokenContractAreStuck() (gas: 94925)\n[PASS] test_transferFromAllowanceErrorPrecedesBalanceError() (gas: 87655)\n[PASS] test_transferFromEmitsOnlyTransferNoApproval() (gas: 120663)\n[PASS] test_transferFromZeroRecipientZeroValueFailsOnReceiver() (gas: 35937)\n[PASS] test_transferFromZeroSourceWithValueFailsOnAllowance() (gas: 37910)\n[PASS] test_transferMaxUintReverts() (gas: 35427)\n[PASS] test_transferOneUnitOverBalanceReverts() (gas: 94204)\n[PASS] test_transferReturnsExactlyOneTrueWord() (gas: 59348)\n[PASS] test_unlimitedAllowanceStillBoundByBalance() (gas: 95111)\n[PASS] test_zeroSenderTransferRejectedBeforeBalance() (gas: 31101)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 31.18ms (117.74ms CPU time)\n\nRan 1 test for test/MADToken.invariant.t.sol:MADTokenInvariantTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchModel() (runs: 128, calls: 8192, reverts: 0)\n\n╭-----------------+--------------+-------+---------+----------╮\n| Contract        | Selector     | Calls | Reverts | Discards |\n+=============================================================+\n| MADTokenHandler | approve      | 2648  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transfer     | 2794  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transferFrom | 2750  | 0       | 0        |\n╰-----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.54s (2.54s CPU time)\n\nRan 1 test for test/MADToken.stateful.t.sol:MADStatefulInvariantTest\n[PASS]\nMADStatefulInvariantTest invariants:\n[PASS] invariant_allowancesMatchModelAndZeroAddressHasNone\n[PASS] invariant_finiteSpendingNeverExceedsGrants\n[PASS] invariant_holdersAccountForTheWholeFixedSupply\n MADStatefulInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+--------------+-------+---------+----------╮\n| Contract           | Selector     | Calls | Reverts | Discards |\n+================================================================+\n| MADStatefulHandler | approve      | 5415  | 0       | 0        |\n|--------------------+--------------+-------+---------+----------|\n| MADStatefulHandler | transfer     | 5402  | 0       | 0        |\n|--------------------+--------------+-------+---------+----------|\n| MADStatefulHandler | transferFrom | 5567  | 0       | 0        |\n╰--------------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.69s (6.69s CPU time)\n\nRan 4 test suites in 6.69s (9.28s CPU time): 59 tests passed, 0 failed, 0 skipped (59 total tests)\n","passed":true},{"durationMs":27,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"LICENSE\":21,\"README.md\":79,\"foundry.toml\":21,\"src/MADToken.sol\":74,\"src/interfaces/IERC20.sol\":18,\"test/MADToken.edge.t.sol\":281,\"test/MADToken.invariant.t.sol\":113,\"test/MADToken.stateful.t.sol\":252,\"test/MADToken.t.sol\":403,\"test/utils/TestBase.sol\":42},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"300497cd40d1c87e22bf522e2399417cc1a137fd01c6c12e71ff8d7520aecd19","verifiedTreeHash":"1486d0de790ec64ee1c2f7979c5026c82efe5f3a","verifierVersion":"0.1.0+560ab6a2"},{"checks":[{"durationMs":398,"exitCode":0,"name":"build","output":"Compiling 5 files with Solc 0.8.26\nSolc 0.8.26 finished in 346.58ms\nCompiler run successful!\n","passed":true},{"durationMs":2652,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 33 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_excessiveAllowanceSpendReverts(uint256) (runs: 256, μ: 106333, ~: 107123)\n[PASS] testFuzz_excessiveTransferRevertsWithoutChanges(uint256) (runs: 256, μ: 54487, ~: 54452)\n[PASS] testFuzz_selfTransferConservesBalance(uint256) (runs: 256, μ: 40882, ~: 40885)\n[PASS] testFuzz_spendingFiniteApproval(uint256,uint256) (runs: 256, μ: 136803, ~: 138186)\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 76130, ~: 76288)\n[PASS] test_approvalDoesNotRequireBalanceOrMoveTokens() (gas: 87224)\n[PASS] test_approvalEmitsAndCanBeOverwrittenAndRevoked() (gas: 183997)\n[PASS] test_approvalRejectsZeroApprover() (gas: 32969)\n[PASS] test_approvalRejectsZeroSpender() (gas: 54172)\n[PASS] test_approvalsAreIsolatedByOwnerAndSpender() (gas: 192143)\n[PASS] test_constructorEmitsSingleSupplyMint() (gas: 8450)\n[PASS] test_entireSupplyCanRoundTrip() (gas: 127166)\n[PASS] test_factoryDeploymentMintsOnlyToImmediateDeployer() (gas: 206608)\n[PASS] test_launchAndTradingTokenLegsTransferExactAmounts() (gas: 536736)\n[PASS] test_metadataAndInitialSupply() (gas: 70289)\n[PASS] test_noMintBurnFreezeSeizeOrUpgradeEntryPoints() (gas: 1433525)\n[PASS] test_rejectsNativeCurrencyAndUnknownCalls() (gas: 58533)\n[PASS] test_selfTransferPreservesBalance() (gas: 40363)\n[PASS] test_selfTransferStillRequiresBalance() (gas: 35753)\n[PASS] test_transferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 229827)\n[PASS] test_transferFromInsufficientBalanceRollsBackAllowance() (gas: 169438)\n[PASS] test_transferFromPreservesUnlimitedAllowanceAcrossTransfers() (gas: 202094)\n[PASS] test_transferFromRejectsUnapprovedSpender() (gas: 99086)\n[PASS] test_transferFromRejectsZeroSource() (gas: 38104)\n[PASS] test_transferFromRequiresAllowanceEvenWhenCallerIsOwner() (gas: 140087)\n[PASS] test_transferFromToSelfConsumesAllowanceWithoutChangingBalance() (gas: 98959)\n[PASS] test_transferFromZeroRecipientRollsBackAllowance() (gas: 97740)\n[PASS] test_transferFromZeroValueNeedsNoAllowance() (gas: 52910)\n[PASS] test_transferRejectsZeroRecipientEvenForZeroValue() (gas: 63860)\n[PASS] test_transferRejectsZeroSender() (gas: 32986)\n[PASS] test_transferReturnsTrueAndEmitsExactAmount() (gas: 82331)\n[PASS] test_transferToContractDoesNotCallRecipient() (gas: 165950)\n[PASS] test_zeroTransferFromEmptyBalanceEmitsEvent() (gas: 56977)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 8.60ms (37.93ms CPU time)\n\nRan 1 test for test/MADToken.invariant.t.sol:MADTokenInvariantTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchModel() (runs: 128, calls: 8192, reverts: 0)\n\n╭-----------------+--------------+-------+---------+----------╮\n| Contract        | Selector     | Calls | Reverts | Discards |\n+=============================================================+\n| MADTokenHandler | approve      | 2648  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transfer     | 2794  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transferFrom | 2750  | 0       | 0        |\n╰-----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.60s (2.60s CPU time)\n\nRan 2 test suites in 2.60s (2.61s CPU time): 34 tests passed, 0 failed, 0 skipped (34 total tests)\n","passed":true},{"durationMs":22,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"LICENSE\":21,\"README.md\":79,\"foundry.toml\":21,\"src/MADToken.sol\":74,\"src/interfaces/IERC20.sol\":18,\"test/MADToken.invariant.t.sol\":113,\"test/MADToken.t.sol\":403,\"test/utils/TestBase.sol\":42},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":469,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":323,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/MADToken.sol:14: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"46b77e6e3c84f03e0c3af23322f42b937cdfa716f523a15c2fa9c6cecf99b22d","verifiedTreeHash":"1b5ac41d27b0510a43096694097f26aeffdcd873","verifierVersion":"0.1.0+560ab6a2"},{"checks":[{"durationMs":357,"exitCode":0,"name":"build","output":"Compiling 5 files with Solc 0.8.26\nSolc 0.8.26 finished in 316.47ms\nCompiler run successful!\n","passed":true},{"durationMs":2527,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 33 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_excessiveAllowanceSpendReverts(uint256) (runs: 256, μ: 106333, ~: 107123)\n[PASS] testFuzz_excessiveTransferRevertsWithoutChanges(uint256) (runs: 256, μ: 54487, ~: 54452)\n[PASS] testFuzz_selfTransferConservesBalance(uint256) (runs: 256, μ: 40882, ~: 40885)\n[PASS] testFuzz_spendingFiniteApproval(uint256,uint256) (runs: 256, μ: 136803, ~: 138186)\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 76130, ~: 76288)\n[PASS] test_approvalDoesNotRequireBalanceOrMoveTokens() (gas: 87224)\n[PASS] test_approvalEmitsAndCanBeOverwrittenAndRevoked() (gas: 183997)\n[PASS] test_approvalRejectsZeroApprover() (gas: 32969)\n[PASS] test_approvalRejectsZeroSpender() (gas: 54172)\n[PASS] test_approvalsAreIsolatedByOwnerAndSpender() (gas: 192143)\n[PASS] test_constructorEmitsSingleSupplyMint() (gas: 8450)\n[PASS] test_entireSupplyCanRoundTrip() (gas: 127166)\n[PASS] test_factoryDeploymentMintsOnlyToImmediateDeployer() (gas: 206608)\n[PASS] test_launchAndTradingTokenLegsTransferExactAmounts() (gas: 536736)\n[PASS] test_metadataAndInitialSupply() (gas: 70289)\n[PASS] test_noMintBurnFreezeSeizeOrUpgradeEntryPoints() (gas: 1433525)\n[PASS] test_rejectsNativeCurrencyAndUnknownCalls() (gas: 58533)\n[PASS] test_selfTransferPreservesBalance() (gas: 40363)\n[PASS] test_selfTransferStillRequiresBalance() (gas: 35753)\n[PASS] test_transferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 229827)\n[PASS] test_transferFromInsufficientBalanceRollsBackAllowance() (gas: 169438)\n[PASS] test_transferFromPreservesUnlimitedAllowanceAcrossTransfers() (gas: 202094)\n[PASS] test_transferFromRejectsUnapprovedSpender() (gas: 99086)\n[PASS] test_transferFromRejectsZeroSource() (gas: 38104)\n[PASS] test_transferFromRequiresAllowanceEvenWhenCallerIsOwner() (gas: 140087)\n[PASS] test_transferFromToSelfConsumesAllowanceWithoutChangingBalance() (gas: 98959)\n[PASS] test_transferFromZeroRecipientRollsBackAllowance() (gas: 97740)\n[PASS] test_transferFromZeroValueNeedsNoAllowance() (gas: 52910)\n[PASS] test_transferRejectsZeroRecipientEvenForZeroValue() (gas: 63860)\n[PASS] test_transferRejectsZeroSender() (gas: 32986)\n[PASS] test_transferReturnsTrueAndEmitsExactAmount() (gas: 82331)\n[PASS] test_transferToContractDoesNotCallRecipient() (gas: 165950)\n[PASS] test_zeroTransferFromEmptyBalanceEmitsEvent() (gas: 56977)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 8.16ms (38.23ms CPU time)\n\nRan 1 test for test/MADToken.invariant.t.sol:MADTokenInvariantTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchModel() (runs: 128, calls: 8192, reverts: 0)\n\n╭-----------------+--------------+-------+---------+----------╮\n| Contract        | Selector     | Calls | Reverts | Discards |\n+=============================================================+\n| MADTokenHandler | approve      | 2648  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transfer     | 2794  | 0       | 0        |\n|-----------------+--------------+-------+---------+----------|\n| MADTokenHandler | transferFrom | 2750  | 0       | 0        |\n╰-----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.49s (2.49s CPU time)\n\nRan 2 test suites in 2.49s (2.49s CPU time): 34 tests passed, 0 failed, 0 skipped (34 total tests)\n","passed":true},{"durationMs":21,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"LICENSE\":21,\"README.md\":79,\"foundry.toml\":21,\"launch.json\":20,\"src/MADToken.sol\":74,\"src/interfaces/IERC20.sol\":18,\"test/MADToken.invariant.t.sol\":113,\"test/MADToken.t.sol\":403,\"test/utils/TestBase.sol\":42},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"be126f0e7bfdc7ad2b43214d3e6bd855b3b4d2efb46fc37cd5053b5d0c7e545d","verifiedTreeHash":"1a62a2d7dc0685ac78f63ac97b73cfa7a6f1ebdc","verifierVersion":"0.1.0+560ab6a2"}]}