{"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":"6072fbc0-bc06-482a-8cec-68d703d51e17","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"09316c0d355932508a9ccb8901d920c216b8724598a34c146c1d1fba03eff46a","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":"341cec3be213b011efb83e34b5494e9fffe979c99e8299b5fd3e7b8ae784613c","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":"1ecb45edfad0bd8416ab984f9e9dd7f9b6e5d3d640f2d31e955ad183f0f7f046","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":"c5cffc4efd564259ccb92e69f636f8123d18a5fccfc9265adb1f85a13e201f02","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":"f7b4d87670620970f2012506acacdd96575b7c55276f6efa38d7f99e4588449a","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":"611fe4d872bcd4d08150cb2f904cab314a481c479ff016b544d0c7e0b38381d1","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"816fe39c7efd64504a19175b0f4dd9186d61069f37a22684c90358a18c60bddc","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"816fe39c7efd64504a19175b0f4dd9186d61069f37a22684c90358a18c60bddc","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"8ac5c76cb505ffaac4f6dfb7cf0503a15cd1cbed850f6c1ba814563aec44889f","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"b4c59a073f981484e0ba3460b08df14a3fd472f396f14448b6416bc425fe2321","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"ab3f8f2aa4e7f3b3ada558c0dcf522ba733ca3df3b1da92c707a0fe305816d5f","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"ab3f8f2aa4e7f3b3ada558c0dcf522ba733ca3df3b1da92c707a0fe305816d5f","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":"c89dd3c29ec7f011731bc384c2b6830e7859f0d515aeedd436cb290c549b3d44","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"6072fbc0-bc06-482a-8cec-68d703d51e17","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2516-mutually-assured-destruction"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52128","feedbackHash":"182df7a7da16677a23809fe7df32c6097ff0798e11a1a54081af5ba362f99231","nodeKey":"audit_economics","submissionHash":"09316c0d355932508a9ccb8901d920c216b8724598a34c146c1d1fba03eff46a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52264","feedbackHash":"b71644430db4877914af838bf65680d35da00462b73a75b3e65903067074774f","nodeKey":"audit_flow","submissionHash":"341cec3be213b011efb83e34b5494e9fffe979c99e8299b5fd3e7b8ae784613c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51195","feedbackHash":"7c0d2bf6f74054b21b540dfe7249b65709f5fd026bae80b3425db708d6f39e23","nodeKey":"audit_judge","submissionHash":"1ecb45edfad0bd8416ab984f9e9dd7f9b6e5d3d640f2d31e955ad183f0f7f046","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52614","feedbackHash":"bb880d86e10b3f82f4aec00accff7cc0c202fe15d91a3fa2d616c4029bc1d1ae","nodeKey":"audit_math","submissionHash":"c5cffc4efd564259ccb92e69f636f8123d18a5fccfc9265adb1f85a13e201f02","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52268","feedbackHash":"aa53d92afc8e306c07423b76116338ca5d1021982b3da784dedf3c2a89af2fa5","nodeKey":"audit_permissions","submissionHash":"f7b4d87670620970f2012506acacdd96575b7c55276f6efa38d7f99e4588449a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52675","feedbackHash":"055cd87fe38c5d8129d0762bae7ff4dc501cf120f22b8e957822cd463778f0ed","nodeKey":"build_contract_project","submissionHash":"611fe4d872bcd4d08150cb2f904cab314a481c479ff016b544d0c7e0b38381d1","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51318","feedbackHash":"710465987f98d21c323a90514cda93b7f26aaf8dea0a54ab32e6052042d93417","nodeKey":"manifest","submissionHash":"8ac5c76cb505ffaac4f6dfb7cf0503a15cd1cbed850f6c1ba814563aec44889f","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52167","feedbackHash":"aa5455ce101ff6a4608ca90c0a6223f3dfb48ebf8fa58d690fa80ae414d261c2","nodeKey":"write_foundry_tests","submissionHash":"b4c59a073f981484e0ba3460b08df14a3fd472f396f14448b6416bc425fe2321","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"5573ad212d114e9b01b7ad6ce3b23074fc4eae6998979f9b656630e58ea84ca4","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"9c6767b941fcfedc","findings":[],"hash":"09316c0d355932508a9ccb8901d920c216b8724598a34c146c1d1fba03eff46a","nodeId":"fc9cc085-e80d-4501-b721-3833617cfd1b","outcome":"completed","summary":"The review is complete. The findings file is valid JSON, the working tree is clean apart from the untracked `.imd-findings.json`, and the scratch test has been removed.\n\n**Result: no defects found.** The MAD token in `src/MADToken.sol` is a minimal fixed-supply ERC-20 with no owner, mint, fee, pause, blacklist, callbacks, payable paths or external dependencies. Every failure mode in the Economic Security, Invariant and Flow Gap guides that could apply to a bare token was checked and none is reachable. The findings file reports an empty list with eight coverage rows.\n\n**What I verified**\n\n- **Conservation.** Sum of balances equals totalSupply equals 1e27 at all times. Only the constructor writes totalSupply, and only `_transfer` writes balances. A stateful fuzz over six actors, including the token's own address, ran 128,000 calls without breaking it.\n- **Unchecked arithmetic.** The sender's subtraction is guarded by the preceding balance check. The recipient's addition cannot overflow because all balances sum to 1e27. Self-transfers of the whole supply leave the balance unchanged.\n- **Allowances.** Decrement happens only after the check, infinite allowance is never reduced, and no caller without an allowance can move a holder's balance. The factory and deployer have no special path.\n- **Launch flows.** Transfers are fee-free and return true, so the swarm share, the Uniswap v4 seed and swaps, and the remainder forward move exactly what they say. The compiled ABI has exactly the three listed entry points and nothing else state-changing.\n- **Supply floor.** No mint, owner, initializer or upgrade function exists. There is no DELEGATECALL, CALLCODE or SELFDESTRUCT in the source.\n\n**Leads dismissed.** Both aderyn lines are gas and style only. The standard ERC-20 approve race and tokens sent to the contract's own address are inherent ERC-20 properties shared with OpenZeppelin v5 and harm only the caller, so they are recorded as notes in the coverage record rather than findings.\n\n**Not reached.** I could not run the protected test file itself because it depends on Uniswap v4 sources that are not in this tree. I reproduced its token-level checks against a mock pool manager instead. No `launch.json` exists yet, which is expected before the manifest step runs.","treeHash":null,"usage":{"cachedInputTokens":601222,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":12092,"runtime":"claude","turns":23,"wallClockMs":290205}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e02ee782fe2a91c3","findings":[{"citation":"resolved","description":"Merged from audit_math (info), audit_permissions (low) and audit_flow (low): one root cause. `_transfer` (src/MADToken.sol:55-64) validates only the receiver and never rejects `from == address(0)`. `transfer` cannot reach that state because `from` is `msg.sender`, but `transferFrom` (src/MADToken.sol:43-53) takes `from` from calldata. With value == 0 both guards pass: allowance[address(0)][caller] is 0 so `allowed < value` is `0 < 0` (false), and balanceOf[address(0)] is 0 so `bal < value` is `0 < 0` (false). The call returns true and emits `Transfer(address(0), to, 0)`, the event shape EIP-20 reserves for token creation and which OpenZeppelin ERC20 rejects with ERC20InvalidSender. No balance or totalSupply changes and no funds are at risk, so this is low: the harm is to off-chain consumers (indexers, explorers, monitors) that count Transfer-from-zero as mints and will record unbounded attacker-triggered post-launch mints of a token documented as minted exactly once. Any non-zero value still reverts with InsufficientAllowance. The launch flows and protected floor tests are unaffected. Minimal fix preserving the intended design: add `error InvalidSender(address sender);` and `if (from == address(0)) revert InvalidSender(from);` at the top of `_transfer`, mirroring the receiver check. address(0) can never hold a balance, so no legitimate transfer changes.","line":56,"path":"src/MADToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MADToken} from \"src/MADToken.sol\";\n\n/// @notice transferFrom accepts `from == address(0)`: an unprivileged caller with no allowance can\n/// make the token emit `Transfer(address(0), anyone, 0)`, the event shape EIP-20 reserves for a mint.\n/// Fails on the current code (the call succeeds); passes once `_transfer` or `transferFrom` rejects a\n/// zero `from`.\ncontract ZeroSenderTransferFromTest is Test {\n    MADToken token;\n    address factory = address(0xFAC7);\n    address attacker = address(0xBAD);\n\n    function setUp() public {\n        vm.prank(factory);\n        token = new MADToken();\n    }\n\n    function test_transferFromZeroSenderReverts() public {\n        vm.prank(attacker);\n        vm.expectRevert();\n        token.transferFrom(address(0), attacker, 0);\n    }\n}","reproduction":"State: fresh MADToken deployed by factory 0xFAC7 (holds the full 1_000_000_000e18 supply). Attacker 0xBAD holds 0 MAD and has no allowance from anyone. Call: vm.prank(0xBAD); token.transferFrom(address(0), 0xBAD, 0). Expected: revert with an invalid-sender error, as transfer(address(0), 0) reverts with InvalidReceiver. Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=0xBAD, value=0); totalSupply stays 1000000000000000000000000000 and balanceOf(0xBAD) stays 0. Reproduced by me with vm.expectEmit(true,true,false,true) on Transfer(address(0), 0xBAD, 0) (passes on current code) and by running both specialist proofs from test/scratch: Proof_bfbc18f66f44.t.sol fails 'transferFrom with from == address(0) should revert' and Proof_a0a0ff2f4ebc.t.sol fails 'next call did not revert as expected'. Control: transferFrom(address(0), 0xBAD, 1) reverts with InsufficientAllowance(0xBAD, 0, 1).","severity":"low","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"transferFrom accepts from == address(0): any caller can emit a mint-shaped Transfer(0x0, to, 0) event after launch"}],"hash":"1ecb45edfad0bd8416ab984f9e9dd7f9b6e5d3d640f2d31e955ad183f0f7f046","nodeId":"340afda8-19b5-4171-a3d8-78c43f9548cc","outcome":"completed","summary":"Nothing remains to request. The findings file parses, its snippet matches the source line, the scratch directory is gone, and the working tree holds only the untracked `.imd-findings.json`.\n\n**Outcome.** The review of the MAD token is complete and written to `.imd-findings.json`. One low-severity finding was kept, and every entry point has a coverage row.\n\n**What the specialists reported.** Three of the four areas reported the same defect at different severities. `transferFrom` accepts a zero `from` address, and with value zero every guard passes, so an unprivileged caller can make the token emit a mint-shaped Transfer event from the zero address. I merged the three reports into one finding at low severity, since no balance or supply changes and the harm is to indexers and explorers that treat such events as mints. I attached the audit_flow specialist's proof, which fails on the current code for the stated reason.\n\n**How I reproduced it.** Both specialist proof files fail when run from the scratch directory, and my own test with an exact event expectation confirms the emitted event is `Transfer(0x0, attacker, 0)`. A non-zero value correctly reverts with an insufficient-allowance error, so only the zero-value case is reachable.\n\n**My own pass.** Approve and transfer behave as intended, including self-transfers and the zero-receiver rejection. The constructor mints the manifest supply once to the deployer, there is no owner, mint, burn, pause or external call, and the project's 53 tests including the invariant suite pass. The manifest agrees with the code on contract name, empty constructor arguments, supply and decimals. The two aderyn notes are style only and were not reported.\n\n**Coverage.** All three listed entry points are answered: approve holds, transfer holds, transferFrom references finding 1. Two invariant rows cover the fixed supply and the manifest.","treeHash":null,"usage":{"cachedInputTokens":425631,"inputTokens":44,"model":"claude-fable-5-1","outputTokens":8827,"runtime":"claude","turns":19,"wallClockMs":132502}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c97fd6a73e3737dc","findings":[{"citation":"resolved","description":"Execution Trace / First Principles pass. `_transfer` (src/MADToken.sol:55-64) validates only the receiver; it never rejects `from == address(0)`. `transfer` cannot reach that state because `from` is `msg.sender`, but `transferFrom` (src/MADToken.sol:43-53) passes a caller-chosen `from`. With `value == 0` the allowance check `allowed < value` (0 < 0) is false and the balance check `bal < value` (0 < 0) is false, so the call succeeds and emits `Transfer(address(0), to, 0)`, which EIP-20 reserves for token creation and which OpenZeppelin's ERC20 rejects with `ERC20InvalidSender(address(0))`. No balance or supply changes, so there is no fund loss; the impact is on off-chain consumers (indexers, explorers, accounting that treats from == 0x0 as a mint) which can be fed an unbounded number of attacker-triggered mint events for this token, against the documented guarantee that the supply is minted exactly once in the constructor. A non-zero `value` still reverts (InsufficientAllowance), so this is informational-to-low. Fix: add `error InvalidSender(address sender);` and `if (from == address(0)) revert InvalidSender(from);` at the top of `_transfer` (or in `transferFrom`), matching the receiver check. This preserves all intended behaviour and the launch flows.","line":56,"path":"src/MADToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MADToken} from \"src/MADToken.sol\";\n\n/// @notice transferFrom accepts `from == address(0)`: an unprivileged caller with no allowance can\n/// make the token emit `Transfer(address(0), anyone, 0)`, the event shape EIP-20 reserves for a mint.\n/// Fails on the current code (the call succeeds); passes once `_transfer` or `transferFrom` rejects a\n/// zero `from`.\ncontract ZeroSenderTransferFromTest is Test {\n    MADToken token;\n    address factory = address(0xFAC7);\n    address attacker = address(0xBAD);\n\n    function setUp() public {\n        vm.prank(factory);\n        token = new MADToken();\n    }\n\n    function test_transferFromZeroSenderReverts() public {\n        vm.prank(attacker);\n        vm.expectRevert();\n        token.transferFrom(address(0), attacker, 0);\n    }\n}","reproduction":"State: fresh MADToken deployed by factory 0xFAC7; attacker 0xBAD holds nothing and has no allowance from anyone. Call: vm.prank(0xBAD); token.transferFrom(address(0), 0xBAD, 0). Expected (EIP-20 / OpenZeppelin semantics and README 'minted once'): revert with an invalid-sender error. Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=0xBAD, value=0); totalSupply unchanged at 1000000000000000000000000000. Confirmed with test/scratch/ZeroSenderTransferFrom.t.sol (fails on current code: 'next call did not revert as expected') and the event-matching check in test/scratch/Sanity.t.sol::test_zeroSenderEmitsMintShapedEvent (passes, i.e. the mint-shaped event is emitted). transferFrom(address(0), 0xBAD, 1) correctly reverts with InsufficientAllowance(0xBAD, 0, 1).","severity":"low","snippet":"        if (to == address(0)) revert InvalidReceiver(to);\n        uint256 bal = balanceOf[from];\n        if (bal < value) revert InsufficientBalance(from, bal, value);","title":"transferFrom accepts from == address(0): anyone can emit a mint-shaped Transfer(0x0, to, 0) event without allowance"}],"hash":"341cec3be213b011efb83e34b5494e9fffe979c99e8299b5fd3e7b8ae784613c","nodeId":"8b6ef742-bc7b-4138-8995-e17ec06f13b1","outcome":"completed","summary":"The review is complete. The findings file is written and the proof is verified in both directions: it fails on the current code and passes on a patched copy.\n\n**Outcome:** MAD is a minimal, dependency-free ERC-20 and the control flow holds in every material respect. One low-severity deviation from standard semantics is reported.\n\n**Finding (low):** `transferFrom` never rejects a zero `from` address. The receiver is validated in `_transfer` but the sender is not, and `transferFrom` lets the caller choose it. With value zero both the allowance and balance checks pass, so any unprivileged address can make the token emit a mint-shaped Transfer event from the zero address, which EIP-20 reserves for token creation and which OpenZeppelin rejects. No balance or supply changes, so the impact is limited to off-chain indexers and accounting. The proposed fix is a one-line sender check mirroring the receiver check, and the proof test passes with it applied.\n\n**What was verified as holding:**\n- Supply is written once in the constructor to the factory, with no mint, burn, admin, fallback or receive path. ETH sent to the contract reverts.\n- Transfer arithmetic conserves balances under a fuzz over transfer, approve and transferFrom sequences. Self-transfer nets zero. The unchecked blocks are safe because the sum of balances is fixed at the supply.\n- Infinite allowance is honoured, finite allowance decrements correctly, and a balance failure reverts the whole call so there is no partial allowance consumption.\n- Launch flows to the factory, distributor and PoolManager move exact amounts, with return values the v4 PoolManager accepts.\n- No libraries, inheritance, external calls or assembly exist, so the Periphery guide has no surface here. Build and format checks pass.\n\n**Not reported:** the EIP-20 approve-overwrite race, which is inherent to the standard rather than this implementation, and the two aderyn style leads, which are gas-only.\n\nCoverage rows answer all three listed entry points plus five invariants. Nothing was left unreached. Scratch tests live under test/scratch only, and no repository file was modified.","treeHash":null,"usage":{"cachedInputTokens":486946,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":13507,"runtime":"claude","turns":22,"wallClockMs":238985}},{"artifacts":[],"attempt":1,"bundleHash":"7708e62124efc36dad93619df9e0be47a321daa4f4966e1aa4ec2e434efcd018","device":"382ebcfad965e0cd","findings":[],"hash":"611fe4d872bcd4d08150cb2f904cab314a481c479ff016b544d0c7e0b38381d1","nodeId":"80c8016f-6012-414e-bb69-eaa577ead5c4","outcome":"completed","summary":"I built the MAD token as a plain fixed-supply ERC-20 and tested it, but **it is not committed**. The commit failed because git has no author name or email set on this machine. The files are staged in the working tree; I didn't set an author because that's stored in `.git`, which I'm not allowed to touch.\n\nOn the compiler pinned in `foundry.toml` (0.8.26), `forge build` and `forge test` pass: 11 of 11 tests, including the fuzz test run with the verifier's seed. `forge fmt --check` is clean. I couldn't run the launch's own protected test files, because they need launch-side files and settings that aren't in this repository.\n\n- **Contract:** `src/MADToken.sol`, Solidity name `MADToken`. `name()` returns \"Mutually Assured Destruction\", the symbol is \"MAD\", and it has 18 decimals. The constructor takes no arguments and mints all 1,000,000,000 × 10^18 tokens once to the deployer, which is the launch factory.\n- **What it doesn't have:** no owner, no further minting, no fee, burn, pause or blacklist. So every transfer to or from the factory, the distributor and the pool moves exactly the amount sent, and the supply can never grow. `type(uint256).max` counts as an unlimited allowance.\n- **Tests:** `test/MADToken.t.sol` checks the token details and supply, the mint event, transfers, `approve` and `transferFrom`, the unlimited allowance, and that the failure cases revert with the right error (not enough balance or allowance, zero address). It also checks there is no mint function and runs a fuzz test that the total supply never changes.\n- **Setup:** `foundry.toml` sets compiler 0.8.26, `bytecode_hash = \"none\"` and the optimizer at 200 runs. The test library (forge-std v1.9.4) is copied into `lib/forge-std` as ordinary files, so the verifier needs no network.\n- **Docs:** `README.md` covers the deployment parameters and assumptions. It records that there are no privileged roles and nothing for the owner to set after launch.\n\nI didn't write `launch.json`, since that's for the later manifest step.\n\nThe repository root also has some files that aren't mine, such as `.bashrc`, `.gitmodules` and `.mcp.json`. They appear to be placeholders the sandbox puts there, so I left them out.","treeHash":"c8e7b7259845ae954f1c24bc84430043713349aa","usage":{"cachedInputTokens":284911,"inputTokens":14,"model":"claude-opus-5-5","outputTokens":5136,"runtime":"claude","turns":7,"wallClockMs":49946}},{"artifacts":[],"attempt":1,"bundleHash":"e140231cf92dbca0d901a39943b508c48f2a40fdcf737c9581e16fec03827953","device":"c7b1db4d25939bd5","findings":[],"hash":"8ac5c76cb505ffaac4f6dfb7cf0503a15cd1cbed850f6c1ba814563aec44889f","nodeId":"f43c8964-1d6d-4975-b8ec-3b996648cb4a","outcome":"completed","summary":"Created [launch.json](/home/worker/.identitymd/work/6072fbc0-bc06-482a-8cec-68d703d51e17/f43c8964-1d6d-4975-b8ec-3b996648cb4a/launch.json) matching `MADToken`, its fixed supply, empty constructor arguments, and the exact pool and economics values.\n\n`forge build` succeeded. All 11 tests passed, including 256 fuzz runs with the supplied seed. Only `launch.json` is changed for submission.","treeHash":"4b76b97508efb116fe13bcaf195a97bcea6821d0","usage":{"cachedInputTokens":136064,"inputTokens":17905,"model":"gpt-6-astra","outputTokens":2097,"runtime":"codex","turns":3,"wallClockMs":59511}},{"artifacts":[],"attempt":1,"bundleHash":"ad3e89de6e1049e27ba2f354003ca53fcd1930e7f9ac8428025a6687b56b5380","device":"1ca477e8d9b58040","findings":[],"hash":"b4c59a073f981484e0ba3460b08df14a3fd472f396f14448b6416bc425fe2321","nodeId":"727ff13e-b035-47f0-a248-5d4a59fe3f34","outcome":"completed","summary":"I didn't commit because this machine has no git identity set, and changing git config is outside what I'm allowed to touch. The two new files are staged and waiting for the pipeline. Nothing outside `test/` was changed.\n\nThe tests are written and pass: `forge build` succeeds, and `forge test` with the verifier's fuzz seed runs 53 tests with 0 failures. I found no defects in `src/MADToken.sol`, so I didn't write a `.imd-findings.json`. It's a plain fixed-supply ERC-20 with no owner, mint, burn, pause, blacklist or fee, and no input I tried broke it.\n\nI kept the earlier contributor's `test/MADToken.t.sol` as it was and added two files.\n\n**`test/MADToken.edges.t.sol`** (41 tests, of which 6 are fuzz tests at 1000 runs each)\n- **Edge cases:** amounts of 0, 1 wei, the full supply, supply + 1 and the maximum uint256; transfers to yourself; tokens sent to the token contract stay there for good.\n- **Every revert checks its exact error and arguments:** insufficient balance, insufficient allowance, sending to the zero address (including with amount 0), and approving the zero address.\n- **Allowances:**\n  - A failed `transferFrom` leaves the allowance unchanged.\n  - A maximum allowance is never reduced, but one just below the maximum is.\n  - A spender can only use their own allowance.\n  - The owner needs an allowance to call `transferFrom` on themselves.\n  - Changing an approval while the spender is active lets them spend at most the old amount plus the new one.\n- **No admin functions:** 14 common admin, mint and burn calls all fail and the supply is unchanged. The contract also rejects ETH and unknown calls.\n- **Fuzz tests:** transfers move exact amounts, overspending reverts, `transferFrom` reduces the allowance by exactly what it moves, and a stranger can't move another holder's tokens.\n\n**`test/MADToken.invariant.t.sol`** (256 runs, 100 calls deep)\n- A handler makes random valid and invalid calls (transfer, approve, transferFrom, sending to zero, approving zero) across five accounts. It keeps its own record of what every balance and allowance should be.\n- After every sequence, these must hold:\n  - the total supply is still 1,000,000,000e18;\n  - balances add up to the total supply;\n  - every balance and allowance matches the handler's record;\n  - every call succeeded or reverted exactly as it should.\n- The run made 25,600 calls with no failures.","treeHash":"0d1802019773a1d9cbb6632062c945614346e20d","usage":{"cachedInputTokens":241222,"inputTokens":12,"model":"claude-opus-5-5","outputTokens":13134,"runtime":"claude","turns":7,"wallClockMs":116756}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"9506ecec995bdbf9","findings":[{"citation":"resolved","description":"Boundary x invariant seam on the sentinel address. _transfer rejects address(0) as receiver but never rejects it as sender. balanceOf[address(0)] is always 0 (nothing can be sent to it), so any value > 0 reverts with InsufficientBalance. But value == 0 passes every guard: allowance[address(0)][caller] is 0, the check `allowed < value` is 0 < 0 and fails, and `bal < value` is 0 < 0 and fails. The call then emits Transfer(address(0), to, 0). That event is indistinguishable from a mint, which breaks the stated invariant 'minted once in the constructor' for any indexer or explorer that treats Transfer events from address(0) as mints. No balance or totalSupply changes, so no funds are at risk. OpenZeppelin's ERC20 rejects this case with ERC20InvalidSender.","line":56,"path":"src/MADToken.sol","reproduction":"Deploy MADToken. From any account (e.g. 0xBEEF) call transferFrom(address(0), 0x000000000000000000000000000000000000CAFE, 0). Expected: revert (an invalid sender, as in OZ ERC20). Actual: returns true and emits Transfer(from=0x0, to=0xCAFE, value=0). totalSupply stays 1e27. I checked this with a scratch Foundry test using vm.recordLogs: one log, topics[1] == bytes32(0). Minimal fix: in _transfer, add `if (from == address(0)) revert InvalidSender(from);`. This only affects calls from address(0), which can never hold a balance, so no intended behaviour changes.","severity":"info","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"Zero-value transferFrom from address(0) emits a mint-shaped Transfer event"}],"hash":"c5cffc4efd564259ccb92e69f636f8123d18a5fccfc9265adb1f85a13e201f02","nodeId":"21752f07-8498-40a5-8a94-57096a81059d","outcome":"completed","summary":"I found no real defects in the token's math, and nothing at low severity or above. The report has one info-level finding and a coverage row for each of the three entry points. It's in `.imd-findings.json`, which is valid JSON and quotes `src/MADToken.sol:56` exactly as it appears in the file. No tracked files changed; the scratch test I used was deleted afterwards.\n\n**Finding 1 (info):** `transferFrom(address(0), X, 0)` succeeds for any caller and emits `Transfer(address(0), X, 0)`. Explorers and indexers read that event as a mint, which clashes with \"minted once in the constructor\". No balances or supply change. The fix is one line: reject `from == address(0)` in `_transfer`, which is what OpenZeppelin does. I confirmed it with a scratch Foundry test that recorded the event.\n\n**What holds** (ran the three guides from the Pashov reference — Math Precision, Boundary, Numerical Gap — against `src/MADToken.sol`):\n- **Math:** the contract has no division, no fixed-point scaling and no casts. The supply constant, 1e27, is computed at compile time.\n- **Unchecked subtractions:** both the balance and the allowance subtraction are guarded by a check just before them.\n- **Unchecked addition:** `balanceOf[to] += value` can't overflow, because there's no way to mint and all balances add up to at most 1e27.\n- **Edge cases:** zero amounts, the unlimited (`type(uint256).max`) allowance, the zero address as receiver or spender, transfers to yourself, and moving a whole balance all behave correctly. I tested the self-transfer and whole-balance cases.\n- **Launch flows:** there's no fee or burn on transfer, so the transfers from the factory to the distributor, the pool seed and swaps all arrive in full.\n\nThe two aderyn leads are not defects. The large-number warning points at the supply constant, which is correct. `totalSupply` could be immutable, but that only affects gas.\n\nThe existing 11 project tests pass. I didn't run the protected launch tests, because they need environment settings and contracts that aren't in this tree. Nothing in my area went unchecked.","treeHash":null,"usage":{"cachedInputTokens":404373,"inputTokens":18,"model":"claude-opus-5-5","outputTokens":5064,"runtime":"claude","turns":9,"wallClockMs":63326}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ff35db055462d2ad","findings":[{"citation":"resolved","description":"Asymmetry in _transfer (src/MADToken.sol:55-64): the receiver is validated (`to == address(0)` reverts with InvalidReceiver) but the sender is not. transferFrom (src/MADToken.sol:43-53) takes `from` from calldata, so an unprivileged caller can pass from = address(0). allowance[address(0)][caller] is 0 and balanceOf[address(0)] is 0, so with value = 0 both guards (`allowed < value`, `bal < value`) are `0 < 0` = false and the call succeeds, emitting `Transfer(address(0), caller, 0)`. That event shape is the ERC-20 convention for a mint, which the README and the launch floor say must never happen after the constructor. No balance or totalSupply changes, so there is no fund impact; the harm is to anyone reading events: indexers, explorers and monitors that count Transfer-from-zero as mints will record spurious post-launch mints of this token from arbitrary unprivileged senders. OpenZeppelin's ERC20 rejects this case with ERC20InvalidSender. Minimal fix that preserves the intended design: in _transfer add `if (from == address(0)) revert InvalidSender(from);` (new error) before the balance check, mirroring the receiver check. Note: zero-value transferFrom from a non-zero account with zero allowance also succeeds, but that is standard ERC-20 (OpenZeppelin behaves the same) and is not part of this finding.","line":56,"path":"src/MADToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MADToken} from \"src/MADToken.sol\";\n\n/// @notice Fails on the current code: transferFrom(address(0), to, 0) succeeds and emits\n/// Transfer(address(0), to, 0). Passes once _transfer rejects from == address(0) the way it\n/// already rejects to == address(0).\ncontract ZeroFromProofTest is Test {\n    MADToken token;\n    address deployer = address(0xFAC7);\n    address attacker = address(0xBAD);\n\n    function setUp() public {\n        vm.prank(deployer);\n        token = new MADToken();\n    }\n\n    function test_transferFromZeroAddressReverts() public {\n        vm.prank(attacker);\n        (bool ok,) = address(token).call(\n            abi.encodeWithSelector(MADToken.transferFrom.selector, address(0), attacker, 0)\n        );\n        assertFalse(ok, \"transferFrom with from == address(0) should revert like transfer to address(0) does\");\n    }\n}","reproduction":"State: fresh MADToken deployed by 0xFAC7 (holds full supply). Attacker 0xBAD, never approved, holds 0 MAD. Call: vm.prank(0xBAD); token.transferFrom(address(0), 0xBAD, 0). Expected: revert (sender zero address is invalid, mirroring `transfer(address(0), 0)` which reverts with InvalidReceiver). Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=0xBAD, value=0). totalSupply stays 1_000_000_000e18 and balanceOf(0xBAD) stays 0. Verified with test/scratch/ZeroFromTransferEvent.t.sol (recordLogs shows exactly one Transfer log with topics[1] == address(0)) and the proof file below, which fails on the current code.","severity":"low","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"transferFrom accepts from == address(0): anyone can emit a zero-value mint-shaped Transfer(0x0, X, 0) event"}],"hash":"f7b4d87670620970f2012506acacdd96575b7c55276f6efa38d7f99e4588449a","nodeId":"ff2f24ef-bb6c-4553-8524-ac9bfd257792","outcome":"completed","summary":"No tracked file changed, and the findings file is valid. The review is complete.\n\n## Outcome\n\nThe MAD token's permission model is sound. I audited `src/MADToken.sol` against the Access Control, Asymmetry and Trust Gap guides and found one low-severity asymmetry and nothing higher. The report is in `.imd-findings.json` with one finding and six coverage rows.\n\n**The finding (low).** The internal transfer helper rejects a zero `to` address but never checks `from`. Through `transferFrom`, any unprivileged caller can pass `from = address(0)` with `value = 0`. Both guards compare zero against zero and pass, so the call succeeds and emits `Transfer(0x0, caller, 0)`. That is the event shape of a mint, which the launch floor says must never happen after the constructor. Balances and supply are untouched, so the harm is limited to indexers and monitors that count mint events. OpenZeppelin rejects this case. The minimal fix is a mirrored sender check in `_transfer`. The attached proof test fails on the current code and I confirmed it passes against a copy with that one line added.\n\n**What holds, and how I checked it.**\n- `approve` writes only the caller's own allowance slot, rejects a zero spender, and has no other writer or admin variant to drift from.\n- `transfer` always uses the caller as sender. The unchecked arithmetic is safe because the sum of balances equals the fixed supply, which a 2000-run fuzz over mixed transfer, approve and transferFrom sequences never broke, including self-transfers and infinite allowances.\n- `transferFrom` handles allowance correctly: infinite allowance is not decremented, finite allowance is checked before the unchecked subtraction, and self-spend without allowance reverts as in OpenZeppelin.\n- There are no roles, modifiers, owner storage, external calls, assembly, delegatecall or selfdestruct. The constructor mints the full supply to `msg.sender`, which is the factory under the launch probe, and hands out no role. Trust Gap seams need a privileged actor or an asymmetric economic primitive, and this contract has neither.\n\n**Static analysis leads.** Slither reported nothing. Aderyn's two low lines, a large numeric literal and a state variable that could be immutable, are gas and style items and fall under the guide's do-not-report list, so I left them out.\n\n**Not reached.** Nothing within the assigned area. I did not independently run the protected launch floor tests, since they need the Uniswap v4 dependencies and environment variables the verifier supplies. By reading them, a fee-free token with no exemption logic satisfies every flow they check.\n\nScratch tests live under `test/scratch/` and are not part of the submission.","treeHash":null,"usage":{"cachedInputTokens":925072,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":16033,"runtime":"claude","turns":31,"wallClockMs":311796}}],"verification":[{"checks":[{"durationMs":965,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 877.73ms\nCompiler run successful!\n","passed":true},{"durationMs":123,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 95559, ~: 99029)\nLogs:\n  Bound result 44925447955318285336\n\n[PASS] test_approveAndTransferFrom() (gas: 139203)\n[PASS] test_approveZeroSpenderReverts() (gas: 30289)\n[PASS] test_constructorEmitsMint() (gas: 5470)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 121951)\n[PASS] test_metadataAndSupply() (gas: 49597)\n[PASS] test_noMintEntryPoint() (gas: 37689)\n[PASS] test_transfer() (gas: 82482)\n[PASS] test_transferFromOverAllowanceReverts() (gas: 86846)\n[PASS] test_transferInsufficientReverts() (gas: 37388)\n[PASS] test_transferToZeroReverts() (gas: 32872)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 5.61ms (6.59ms CPU time)\n\nRan 1 test suite in 6.40ms (5.61ms CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":36,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":2,\"README.md\":30,\"foundry.toml\":9,\"remappings.txt\":1,\"src/MADToken.sol\":65,\"test/MADToken.t.sol\":102},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":728,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":523,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/MADToken.sol:11: Large Numeric Literal\n[low] state-variable-could-be-immutable at src/MADToken.sol:13: State Variable Could Be Immutable","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"611fe4d872bcd4d08150cb2f904cab314a481c479ff016b544d0c7e0b38381d1","verifiedTreeHash":"c8e7b7259845ae954f1c24bc84430043713349aa","verifierVersion":"0.1.0+962b3018"},{"checks":[{"durationMs":1175,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.07s\nCompiler run successful!\n","passed":true},{"durationMs":168,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 95559, ~: 99029)\nLogs:\n  Bound result 1000000000000000000000000000\n\n[PASS] test_approveAndTransferFrom() (gas: 139203)\n[PASS] test_approveZeroSpenderReverts() (gas: 30289)\n[PASS] test_constructorEmitsMint() (gas: 5470)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 121951)\n[PASS] test_metadataAndSupply() (gas: 49597)\n[PASS] test_noMintEntryPoint() (gas: 37689)\n[PASS] test_transfer() (gas: 82482)\n[PASS] test_transferFromOverAllowanceReverts() (gas: 86846)\n[PASS] test_transferInsufficientReverts() (gas: 37388)\n[PASS] test_transferToZeroReverts() (gas: 32872)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 5.30ms (5.94ms CPU time)\n\nRan 1 test suite in 6.28ms (5.30ms CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":57,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":2,\"README.md\":30,\"foundry.toml\":9,\"launch.json\":20,\"remappings.txt\":1,\"src/MADToken.sol\":65,\"test/MADToken.t.sol\":102},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"8ac5c76cb505ffaac4f6dfb7cf0503a15cd1cbed850f6c1ba814563aec44889f","verifiedTreeHash":"4b76b97508efb116fe13bcaf195a97bcea6821d0","verifierVersion":"0.1.0+962b3018"},{"checks":[{"durationMs":1639,"exitCode":0,"name":"build","output":"Compiling 27 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.54s\nCompiler run successful!\n","passed":true},{"durationMs":10176,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MADToken.t.sol:MADTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 97240, ~: 99029)\nLogs:\n  Bound result 8974\n\n[PASS] test_approveAndTransferFrom() (gas: 139203)\n[PASS] test_approveZeroSpenderReverts() (gas: 30289)\n[PASS] test_constructorEmitsMint() (gas: 5470)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 121951)\n[PASS] test_metadataAndSupply() (gas: 49597)\n[PASS] test_noMintEntryPoint() (gas: 37689)\n[PASS] test_transfer() (gas: 82482)\n[PASS] test_transferFromOverAllowanceReverts() (gas: 86846)\n[PASS] test_transferInsufficientReverts() (gas: 37388)\n[PASS] test_transferToZeroReverts() (gas: 32872)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 36.12ms (34.07ms CPU time)\n\nRan 41 tests for test/MADToken.edges.t.sol:MADTokenEdgesTest\n[PASS] testFuzz_approveSetsExactValue(address,address,uint256) (runs: 1000, μ: 60659, ~: 61016)\n[PASS] testFuzz_strangerCannotMoveAnotherHolder(address,uint256) (runs: 1000, μ: 51710, ~: 51526)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 1000, μ: 108724, ~: 109215)\nLogs:\n  Bound result 949\n  Bound result 30880\n\n[PASS] testFuzz_transferFromAboveAllowanceReverts(uint256,uint256) (runs: 1000, μ: 102598, ~: 102999)\nLogs:\n  Bound result 662753025269143259519298077\n  Bound result 1002516499241685124554152503161836324196064785387356604297312733713602998\n\n[PASS] testFuzz_transferFromSpendsExactly(uint256,uint256) (runs: 1000, μ: 156620, ~: 158361)\nLogs:\n  Bound result 3\n  Bound result 2\n\n[PASS] testFuzz_transferMovesExactly(address,uint256,uint256) (runs: 1000, μ: 170289, ~: 172300)\nLogs:\n  Bound result 1\n  Bound result 0\n\n[PASS] test_allowanceOneBelowMaxIsDecremented() (gas: 126110)\n[PASS] test_approvalsAreDirectional() (gas: 80022)\n[PASS] test_approveDoesNotRequireBalance() (gas: 65405)\n[PASS] test_approveEmitsAndOverwrites() (gas: 153078)\n[PASS] test_approveSelf() (gas: 62968)\n[PASS] test_approveZeroSpenderWithZeroValueReverts() (gas: 32834)\n[PASS] test_constantSupplyMatchesTotal() (gas: 32736)\n[PASS] test_constructorMintsOnlyToDeployer() (gas: 44113)\n[PASS] test_constructorSetsNoAllowances() (gas: 28067)\n[PASS] test_eachDeploymentMintsToItsOwnDeployer() (gas: 34575)\n[PASS] test_failedTransferLeavesStateUntouched() (gas: 110462)\n[PASS] test_frontRunApproveChangeIsBoundedByOldPlusNew() (gas: 230345)\n[PASS] test_infiniteAllowanceMovesWholeSupplyAndStaysInfinite() (gas: 172682)\n[PASS] test_noAdminOrSupplyChangingEntryPoints() (gas: 421392)\n[PASS] test_nonPayableFunctionsRejectValue() (gas: 47880)\n[PASS] test_ownerCannotTransferFromSelfWithoutAllowance() (gas: 38398)\n[PASS] test_rejectsEtherAndUnknownCalldata() (gas: 61477)\n[PASS] test_selfTransferKeepsBalance() (gas: 45884)\n[PASS] test_selfTransferOverBalanceReverts() (gas: 36061)\n[PASS] test_transferAfterSpendingRevertsOnRemainder() (gas: 164217)\n[PASS] test_transferFromAllowanceAboveBalanceRevertsOnBalance() (gas: 167557)\n[PASS] test_transferFromDoesNotEmitApproval() (gas: 122408)\n[PASS] test_transferFromExactAllowanceZeroesIt() (gas: 171039)\n[PASS] test_transferFromOnlySpendsCallersAllowance() (gas: 222607)\n[PASS] test_transferFromSelfToSelf() (gas: 104919)\n[PASS] test_transferFromToZeroAddressRevertsAndKeepsAllowance() (gas: 95589)\n[PASS] test_transferFromWithoutAllowanceReverts() (gas: 45364)\n[PASS] test_transferFromZeroWithoutAllowanceSucceeds() (gas: 68398)\n[PASS] test_transferMaxUintReverts() (gas: 38141)\n[PASS] test_transferOneMoreThanBalanceReverts() (gas: 38017)\n[PASS] test_transferOneWei() (gas: 82394)\n[PASS] test_transferToTokenContractIsAllowedAndStuck() (gas: 77919)\n[PASS] test_transferWholeSupply() (gas: 90784)\n[PASS] test_transferZeroSucceedsAndEmits() (gas: 62763)\n[PASS] test_transferZeroToZeroAddressReverts() (gas: 32889)\nSuite result: ok. 41 passed; 0 failed; 0 skipped; finished in 37.78ms (214.54ms CPU time)\n\nRan 1 test for test/MADToken.invariant.t.sol:MADTokenInvariantTest\n[PASS]\nMADTokenInvariantTest invariants:\n[PASS] invariant_allowancesMatchLedger\n[PASS] invariant_balancesMatchLedger\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_everyCallBehavedAsSpecified\n[PASS] invariant_totalSupplyIsFixed\n MADTokenInvariantTest invariants (runs: 256, calls: 25600, reverts: 0)\n\n╭------------+----------------+-------+---------+----------╮\n| Contract   | Selector       | Calls | Reverts | Discards |\n+==========================================================+\n| MADHandler | approve        | 5051  | 0       | 0        |\n|------------+----------------+-------+---------+----------|\n| MADHandler | approveZero    | 5029  | 0       | 0        |\n|------------+----------------+-------+---------+----------|\n| MADHandler | transfer       | 5136  | 0       | 0        |\n|------------+----------------+-------+---------+----------|\n| MADHandler | transferFrom   | 5254  | 0       | 0        |\n|------------+----------------+-------+---------+----------|\n| MADHandler | transferToZero | 5130  | 0       | 0        |\n╰------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 100000000000000000000000000\n  Bound result 100000000000000000000000000\n  Bound result 100000000000000000000000000\n  Bound result 100000000000000000000000000\n  Bound result 1\n  Bound result 115792089237316195423570985008687907853269984665640464039457584007913129640935\n  Bound result 7\n  Bound result 1\n  Bound result 115792089237316195423570985008687907853269984665639964039458584007913129639935\n  Bound result 30\n  Bound result 0\n  Bound result 1999999999999999999999999999\n  Bound result 0\n  Bound result 600000000000000000000000002\n  Bound result 1\n  Bound result 4178\n  Bound result 1729803125094266608231420230942714367987219794502696888919760185253\n  Bound result 608\n  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129639934\n  Bound result 6693\n  Bound result 204117694187575009241444902\n  Bound result 2127\n  Bound result 115792089237316195423570985008687907853269984665640259921763396432903888854951\n  Bound result 0\n  Bound result 265631128956909333533676\n  Bound result 2\n  Bound result 100\n  Bound result 7979439833698142\n  Bound result 0\n  Bound result 91941445260951968873843956\n  Bound result 1265744\n  Bound result 5503\n  Bound result 115792089237316195423570985008687907853269984665640464305088712964822463173868\n  Bound result 75\n  Bound result 0\n  Bound result 4876\n  Bound result 344\n  Bound result 115792089237316195423570985008687907853269984665640167891520642626013037554436\n  Bound result 30\n  Bound result 244851778380471\n  Bound result 0\n  Bound result 100\n  Bound result 244851778380470\n  Bound result 1638\n  Bound result 6682\n  Bound result 1000\n  Bound result 1\n  Bound result 86372634228886147901082441\n  Bound result 1044\n  Bound result 0\n  Bound result 134449122956634955676279606\n  Bound result 1\n  Bound result 214903558045759166752572493\n  Bound result 14\n  Bound result 115792089237316195423570985008687907853269984665640302340643599260968713833608\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 10113\n  Bound result 1\n  Bound result 1918926798\n  Bound result 1000000000\n  Bound result 23\n  Bound result 1\n  Bound result 100000000000489703556760939\n  Bound result 115792089237316195423570985008687907853269984665640259921763396432902888195045\n  Bound result 115792089237316195423570985008687907853269984665640259921763396432902888200512\n  Bound result 0\n  Bound result 209173276856783808965\n  Bound result 11\n  Bound result 2\n  Bound result 10\n  Bound result 2\n  Bound result 17010874615175220\n  Bound result 10\n  Bound result 4513\n  Bound result 18\n  Bound result 0\n  Bound result 889\n  Bound result 891641592049438671\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 10.05s (10.05s CPU time)\n\nRan 3 test suites in 10.06s (10.13s CPU time): 53 tests passed, 0 failed, 0 skipped (53 total tests)\n","passed":true},{"durationMs":47,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MADToken.approve(address,uint256)\",\"MADToken.transfer(address,uint256)\",\"MADToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":2,\"README.md\":30,\"foundry.toml\":9,\"remappings.txt\":1,\"src/MADToken.sol\":65,\"test/MADToken.edges.t.sol\":444,\"test/MADToken.invariant.t.sol\":186,\"test/MADToken.t.sol\":102},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"b4c59a073f981484e0ba3460b08df14a3fd472f396f14448b6416bc425fe2321","verifiedTreeHash":"0d1802019773a1d9cbb6632062c945614346e20d","verifierVersion":"0.1.0+962b3018"}]}