{"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":"c4a250b4-cc63-4505-b92c-ba262076a88a","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"29fad07a869ebeafdd46fc3c635a3db9cd3bdb71e977fc9cd92fbf2685dbd0db","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":"6f9ac63f015c663822ef209411d891cb7b86a85f820b8b75a7e9c54fa4737d1d","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":"70c1977bce1cfb59ea3fbbe4061fe637551fe162cc7d154ebe00cfc9f6fc848c","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":"402a31ca0617a08dd5f721fe5a9c6ec7607a6b975a0cf167e33b614d3c936da8","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":"4b034394112de941a1814e84510b4d24dbfcf41854b03974d60475622d7e52da","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":"af9d190cdd8e343b9a3feec091e4143e15f952d32e6d918a0aa7739aed50bc6b","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"95ee663953664180472da23ff13908f1ce466c008b819176050e120b34423a6a","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"8f7f22655d1910cbab564599a071bb90966ab9c7a6394ab2bf3f6ae233f1024f","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"A custom token: Initial Fee Offering (IFO).\nToken name: Initial Fee Offering\nToken symbol: IFO\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"c331e80dbb9d27b2caef3b7c9d2ae13a76a18983fa067effdca9918bddd761ff","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"c4a250b4-cc63-4505-b92c-ba262076a88a","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1452-initial-fee-offering"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52669","feedbackHash":"50df979356d2fdb1c2dcc4f38ce3a594417adaa366fe5cdb9e0123b4dd025c98","nodeKey":"audit_economics","submissionHash":"29fad07a869ebeafdd46fc3c635a3db9cd3bdb71e977fc9cd92fbf2685dbd0db","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51141","feedbackHash":"14cf73e598c38d3cd3a598c81ca847d6e4c37ce8f18b4460e8104351eed155cb","nodeKey":"audit_flow","submissionHash":"6f9ac63f015c663822ef209411d891cb7b86a85f820b8b75a7e9c54fa4737d1d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51334","feedbackHash":"2af66d1fcfdf81793571772c95207ae3009f967c942c41c666ca8ba26fcd9a53","nodeKey":"audit_judge","submissionHash":"70c1977bce1cfb59ea3fbbe4061fe637551fe162cc7d154ebe00cfc9f6fc848c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51465","feedbackHash":"bdbfa9d70b7b7cca1b1c62788ccd0fe844448f7008212c8c5c01f1292cc9cb87","nodeKey":"audit_math","submissionHash":"402a31ca0617a08dd5f721fe5a9c6ec7607a6b975a0cf167e33b614d3c936da8","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51558","feedbackHash":"0cb915b88368aeb91d4be71b6c0495577970b17368cea8d822080a5611f68053","nodeKey":"audit_permissions","submissionHash":"4b034394112de941a1814e84510b4d24dbfcf41854b03974d60475622d7e52da","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51237","feedbackHash":"848687d8491a187780eed4262ef37d84f9fee10386c6d2fecef430020d44745d","nodeKey":"build_contract_project","submissionHash":"af9d190cdd8e343b9a3feec091e4143e15f952d32e6d918a0aa7739aed50bc6b","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51128","feedbackHash":"35ce4174c36c14e054ab7f6f8f0afe379090146805504d5585b0ea1b1b85920a","nodeKey":"manifest","submissionHash":"95ee663953664180472da23ff13908f1ce466c008b819176050e120b34423a6a","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51153","feedbackHash":"bf86b8e1e0dd426b7656f85bda136829c111bfeab10f95596f57e113307738b4","nodeKey":"write_foundry_tests","submissionHash":"8f7f22655d1910cbab564599a071bb90966ab9c7a6394ab2bf3f6ae233f1024f","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"d5fd0f771d8499740f1e83df8f4b6116da4c94ba790fa9be528073002f389af9","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"7cb215928f3c9473","findings":[],"hash":"29fad07a869ebeafdd46fc3c635a3db9cd3bdb71e977fc9cd92fbf2685dbd0db","nodeId":"2521985d-ceff-4d19-a26d-51c72fa7ad06","outcome":"completed","summary":"I found no defects in the IFO token's economics, so `.imd-findings.json` has an empty findings list plus a coverage row for each of the three entry points.\n\n**What the code is:** `src/IFOToken.sol` is a plain OpenZeppelin v5.1.0 ERC-20. Its constructor mints 10^27 (1,000,000,000 tokens with 18 decimals) once, to `msg.sender`, which is the factory at launch. It doesn't override `_update` and has no owner, mint, burn, pause, blacklist or upgrade function. The vendored OpenZeppelin files match the SHA-256 checksums listed in `DEPENDENCIES.json`, and I read `_update` to confirm it hasn't been changed.\n\n**Coverage (all `holds`):**\n- **`approve`:** the standard OpenZeppelin allowance behaviour. The usual risk of a spender racing an allowance change is an ordinary ERC-20 property, and the README documents it.\n- **`transfer`:** the sender loses exactly what the recipient gains. With no tax, burn, rebase, limit or trading switch, every launch flow moves its full amount: the 10% swarm share to the distributor, the 80% pool seed (poolBps 8000) into the Uniswap v4 PoolManager, the 10% remainder, distributor claims, and buys and sells.\n- **`transferFrom`:** the allowance is reduced by exactly the amount sent, and a maximum allowance is treated as unlimited. A failure reverts the whole call.\n- **Invariants:** the supply stays at exactly 10^27 for good, nobody privileged can move or freeze a holder's balance, and the flows arrive exact. All three hold.\n\n**Checks run:** the existing 31 local tests pass, including the fuzz tests and the stateful invariant. I didn't run the supplied protected harness, because the Uniswap v4 and launch contracts it imports aren't in this tree.\n\n**Static-analysis leads:** Slither reported nothing. Aderyn's only lead, the large numeric literal `1_000_000_000 * 10 ** 18` at line 12, is the correct supply and not a defect.\n\nThe name \"Initial Fee Offering\" suggests a fee, but the brief asks for no fee mechanism and the code has none.","treeHash":null,"usage":{"cachedInputTokens":214029,"inputTokens":12,"model":"claude-opus-5-5","outputTokens":2625,"runtime":"claude","turns":6,"wallClockMs":41825}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f0c4ae5b8ada215c","findings":[],"hash":"402a31ca0617a08dd5f721fe5a9c6ec7607a6b975a0cf167e33b614d3c936da8","nodeId":"73f30c06-fb38-44d1-9287-c9c95e1cc751","outcome":"completed","summary":"The review is complete. The findings file is at the repository root with an empty findings list and a seven-row coverage record. The scratch directory is removed and no project file was changed.\n\n**Result: no defects in the assigned area.** The token is a bare OpenZeppelin v5.1.0 ERC-20 whose constructor mints a compile-time constant once to the deployer. Every failure mode in the Math Precision, Boundary and Numerical Gap guides is structurally absent, not just untriggered.\n\nWhat I verified:\n- **Math.** The only arithmetic is the supply literal, which evaluates to exactly 10^27, and one checked addition in the mint. There is no division, downcast, decimals conversion, fee or share formula anywhere. The inherited `_update` guards `fromBalance < value` before its unchecked subtraction, and the unchecked balance addition cannot wrap because the supply is fixed.\n- **Boundary.** The runtime bytecode has no CALL, STATICCALL, DELEGATECALL, CALLCODE or SELFDESTRUCT. There is no payable function, fallback, receive, sentinel-address branch or decoded bytes input. Decimals are 18, matching the stated token and the IMD pair.\n- **Numerical seams.** Scratch tests exercised 0, 1 wei, the whole supply, max uint256, self-transfer, max-minus-one allowance and a 512-run conservation fuzz. All passed, as did the project's 31 tests and its 256-run invariant.\n- **Dependencies.** The vendored OpenZeppelin files hash to the values in DEPENDENCIES.json, and ERC20.sol and Context.sol match the raw upstream files at commit 69c8def. No submodule exists.\n\nThe aderyn large-literal lead is benign. Outside my area, the Uniswap v4 seed and swap flows were not executed locally because the protected harness needs the launch system's contracts, which are not in this tree. The token's fee-free transfers give those flows no token-side reason to arrive short.","treeHash":null,"usage":{"cachedInputTokens":518223,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":9671,"runtime":"claude","turns":22,"wallClockMs":147574}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"323aec17bfc8d652","findings":[{"citation":"resolved","description":"README.md lines 139-143 state that lib/forge-std holds 'unmodified Solidity sources' and that the digests in DEPENDENCIES.json 'allow the vendored contents to be checked without installing dependencies again'. That check fails for seven forge-std files: src/StdAssertions.sol, src/StdJson.sol, src/StdToml.sol, src/Vm.sol, src/console.sol, src/interfaces/IERC7540.sol and src/interfaces/IMulticall3.sol. The recorded digests equal the upstream files at commit 77041d2ce690e692d6e03cc812b57d1ddaa4d505 (fetched and compared), so the records are correct for upstream, but the vendored copies were re-wrapped by `forge fmt` (line_length = 120 in foundry.toml) after the digests were taken. Every diff is whitespace/line-wrapping only; no token, semantic or bytecode change. All six OpenZeppelin files, including the production ERC20.sol the token inherits, match their recorded digests exactly, so the production dependency provenance claim holds. Impact is limited to the provenance procedure: an operator following the README's verification step sees seven mismatches on test-only files and cannot distinguish a reformat from a tamper without fetching upstream. Not an exploitable defect; no effect on IFOToken, its ABI or the launch flows. Minimal fix: either re-record the seven digests from the tree, or restore the upstream byte-exact files (and exclude lib/ from `forge fmt`), and soften the README wording to say which files were reformatted.","line":30,"path":"DEPENDENCIES.json","reproduction":"From the repository root run:\n\n  python3 -I - <<'EOF'\n  import json,hashlib\n  for dep in json.load(open('DEPENDENCIES.json')):\n      for f,h in dep['files'].items():\n          p=dep['path']+'/'+f\n          print('OK ' if hashlib.sha256(open(p,'rb').read()).hexdigest()==h else 'BAD', p)\n  EOF\n\nExpected (per README): every line prints OK. Actual: BAD for lib/forge-std/src/StdAssertions.sol (tree sha256 3fbf4a025b4fc94e..., recorded d4c89eec70d267de...), StdJson.sol, StdToml.sol, Vm.sol, console.sol, interfaces/IERC7540.sol, interfaces/IMulticall3.sol; all OpenZeppelin files OK. `diff` of each BAD file against the raw upstream file at commit 77041d2ce690e692d6e03cc812b57d1ddaa4d505 shows only function-signature line wrapping differences (e.g. StdAssertions.sol line 480: a four-line `assertApproxEqAbs(...) internal pure virtual {` header collapsed to one line).","severity":"info","snippet":"      \"src/StdAssertions.sol\": \"d4c89eec70d267dec6188461fbc74d3dc8c47e518d176a23417533a232ed9780\",","title":"DEPENDENCIES.json SHA-256 digests do not match seven vendored forge-std files (reformatted after hashing)"}],"hash":"4b034394112de941a1814e84510b4d24dbfcf41854b03974d60475622d7e52da","nodeId":"8c81cb37-9963-4300-9a68-1089375b551a","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds the result. The working tree is otherwise unchanged.\n\n**Outcome: no permission defects.** The token is an unmodified OpenZeppelin v5.1.0 ERC-20 with a constructor that mints exactly 1e27 units to its deployer. The compiled ABI exposes only approve, transfer and transferFrom as state-changing functions, with no receive or fallback. There is no owner, minter, pauser, blocklist, burnFrom, seize or upgrade path, so the Access Control, Trust Gap and Asymmetry checklists have nothing to attach to. I traced each entry point through the OZ internals, ran the project's 31 tests, and ran a scratch suite modelling the launch shape (a CREATE2 factory holding the supply, a stranger and the factory attempting to move a holder's balance, allowance pair symmetry, unknown selectors and ETH). Everything held.\n\n**One informational note recorded.** Seven forge-std files under lib/ do not match the SHA-256 digests in DEPENDENCIES.json. The recorded digests equal the pinned upstream files. The vendored copies were re-wrapped by `forge fmt` afterward, so every difference is whitespace only. All OpenZeppelin files, including the production ERC20.sol, match exactly. This only affects the README's dependency-verification procedure for test-only files and carries no runtime impact, so it is filed as info with the exact reproduction command.\n\n**Coverage** names all three listed entry points as holds, plus four invariant rows for the constructor mint, absence of hidden entry points, launch-flow requirements and the trust-gap seams. The static-analysis lead about the large numeric literal is the supply constant itself and is correct, so it was not promoted.","treeHash":null,"usage":{"cachedInputTokens":658977,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":13037,"runtime":"claude","turns":26,"wallClockMs":197140}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"7d454e6cee88c390","findings":[{"citation":"resolved","description":"IFOToken inherits the unmodified OpenZeppelin v5.1.0 ERC20 (vendored bytes match upstream commit 69c8def5 exactly). approve() overwrites the allowance rather than adjusting it, so an owner who lowers a nonzero allowance is exposed to the well-known ERC-20 approval race. This is the ERC-20 standard's behaviour, OpenZeppelin v5 deliberately dropped increaseAllowance/decreaseAllowance, and README.md lines 126-131 already instruct holders to revoke to zero first. It is recorded here only because it is the single Execution-Trace guide item (approval residuals) that applies to this contract; it is not a defect in the requester's code and needs no fix. Holders mitigate by approving 0, waiting for inclusion, then approving the new value.","line":127,"path":"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol","reproduction":"State: owner holds 150 IFO, spender is any EOA. 1) owner calls approve(spender, 100e18). 2) owner broadcasts approve(spender, 50e18). 3) spender sees it in the mempool and front-runs with transferFrom(owner, spender, 100e18) -> succeeds, allowance becomes 0. 4) owner's approve(spender, 50e18) lands, allowance = 50e18. 5) spender calls transferFrom(owner, spender, 50e18) -> succeeds. Actual: spender received 150e18, owner balance 0. Owner's intent: spender limited to 50e18. Verified with a Foundry test on this tree (test_approvalRaceIsStandardBehaviour, scratch, removed).","severity":"info","snippet":"    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }","title":"Standard ERC-20 approve ordering: changing a nonzero allowance lets a front-running spender collect old and new amounts (inherent to ERC-20, documented in README, no code change required)"}],"hash":"6f9ac63f015c663822ef209411d891cb7b86a85f820b8b75a7e9c54fa4737d1d","nodeId":"05c20983-ea8e-4763-9bac-25f9e6d691e1","outcome":"completed","summary":"The review is complete. The findings file is in place, the scratch directory is removed, and the working tree has no stray files.\n\n**Outcome: no defects found in the assigned area.** The IFO token is the unmodified OpenZeppelin v5.1.0 ERC-20 with a no-argument constructor that mints exactly 10^27 units to the deployer. Every Execution Trace, Periphery and First Principles failure mode I checked either does not apply or holds.\n\n**What I verified**\n\n- **Execution trace.** All three state-changing entry points were traced through the inherited base. Transfers deliver exact amounts with no fee, burn, hook or external call. Reverts leave no partial state. The factory cannot pull from a holder without allowance. There is no receive or fallback, so ether and unknown selectors revert.\n- **Periphery.** The five vendored OpenZeppelin files are byte-identical to the pinned upstream commit, confirmed by fetching them and comparing SHA-256 digests. No local modification.\n- **First principles.** Supply arithmetic equals 10^27 and matches the README's minor-unit figure. Decimals, name and symbol match the brief. Supply cannot grow after construction because mint and burn are internal only. The compiled runtime contains no DELEGATECALL, CALLCODE, SELFDESTRUCT, CALL or STATICCALL.\n- **Launch floor.** A scratch Foundry test mirrored the protected harness's ERC-20 pieces: CREATE2 deployment from a factory address, the ten percent distributor transfer and claim arriving whole, pool-style in and out transfers, and a sweep of 22 privileged selectors from both the factory and a stranger. All passed. The existing 31-test suite including the invariant run also passes.\n\n**What the file reports**\n\n- One `info` entry only: the standard ERC-20 approval ordering race, with a concrete sequence. It is inherent to the standard, already documented in the README, and needs no fix. I recorded it because it is the one Execution Trace guide item that applies.\n- Seven coverage rows: `holds` for approve, transfer, transferFrom, the constructor, the fixed-supply invariant, the opcode invariant and the vendored periphery.\n\n**Not reached.** The live Uniswap v4 seed and swap in the protected harness cannot run here because the v4 and launch contracts are not in this tree. Since the token has no transfer hooks or exemptions, nothing in it can alter that flow, so I covered it with plain-transfer equivalents.","treeHash":null,"usage":{"cachedInputTokens":990319,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":17094,"runtime":"claude","turns":36,"wallClockMs":251583}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"433c37ef2c9c708d","findings":[{"citation":"resolved","description":"Merged from audit_permissions (the only specialist that raised it); reproduced independently. README.md lines 142-148 state that lib/forge-std holds 'unmodified Solidity sources' at commit 77041d2ce690e692d6e03cc812b57d1ddaa4d505 and that the digests in DEPENDENCIES.json 'allow the vendored contents to be checked without installing dependencies again'. That check fails for seven files: lib/forge-std/src/StdAssertions.sol, StdJson.sol, StdToml.sol, Vm.sol, console.sol, interfaces/IERC7540.sol and interfaces/IMulticall3.sol. I fetched each of the seven from the upstream repository at that commit: every recorded digest equals the upstream file, and every vendored copy equals the upstream file once all whitespace is stripped, so the difference is `forge fmt` line re-wrapping (line_length = 120 in foundry.toml) applied after the digests were recorded. No token, semantic or bytecode change. All six OpenZeppelin files, including the production ERC20.sol that IFOToken inherits, are byte-identical to upstream commit 69c8def5f222ff96f2b5beff05dfba996368aa79 (fetched and compared with cmp), so the production dependency provenance claim holds. Impact is confined to the provenance procedure: an operator following the README sees seven mismatches on test-only files and cannot tell a reformat from a tamper without fetching upstream, which is exactly what the digests were meant to avoid. No effect on IFOToken, its ABI, bytecode or the launch flows. Minimal fix: re-record the seven digests from the tree, or restore the byte-exact upstream files and keep lib/ out of `forge fmt`, and change the README wording to match.","line":30,"path":"DEPENDENCIES.json","reproduction":"From the repository root run: python3 -I - <<'EOF'\nimport json,hashlib\nfor dep in json.load(open('DEPENDENCIES.json')):\n    for f,h in dep['files'].items():\n        p=dep['path']+'/'+f\n        print('OK ' if hashlib.sha256(open(p,'rb').read()).hexdigest()==h else 'BAD', p)\nEOF\nExpected (per README.md 'unmodified Solidity sources' and 'allow the vendored contents to be checked'): 36 lines of OK. Actual: BAD for lib/forge-std/src/StdAssertions.sol, StdJson.sol, StdToml.sol, Vm.sol, console.sol, interfaces/IERC7540.sol, interfaces/IMulticall3.sol; the other 29 lines (all OpenZeppelin files and the remaining forge-std files) print OK. Cross-check: for each BAD file, sha256 of https://raw.githubusercontent.com/foundry-rs/forge-std/77041d2ce690e692d6e03cc812b57d1ddaa4d505/<file> equals the recorded digest, and re.sub(r'\\s+','',upstream) == re.sub(r'\\s+','',vendored) is True, so the vendored copies differ from upstream only by whitespace.","severity":"low","snippet":"      \"src/StdAssertions.sol\": \"d4c89eec70d267dec6188461fbc74d3dc8c47e518d176a23417533a232ed9780\",","title":"DEPENDENCIES.json digests do not match seven vendored forge-std files, so the README's provenance check fails (reformatted after hashing)"},{"citation":"resolved","description":"README.md lines 93-94 say 'this repository deliberately does not provide one', yet launch.json exists at the repository root, added by commit 4ab2cec (the manifest step) after the README was written in commit a563872. The statement is stale rather than wrong about the token: the manifest's contents agree with the README table (contract IFOToken, name, symbol, decimals 18, constructorArgs [], totalSupply 1000000000000000000000000000, pairedCurrency, fee 12500, tickSpacing 60, initialPrice 79228162514264337593543950336, economics poolBps 8000 / initialMarketCapWei 2500000000000000000000 / remainderTo 0x6bf192ebef135e0f645e99d59d9bf44e7711606c), and I checked the manifest uses only schema keys, lowercase addresses, string uint256 values, numeric fee/tickSpacing/decimals, an empty constructorArgs matching the argument-free constructor, and notes of 401 characters. Only the README sentence is out of date. Documentation only; no code or deployment impact. Minimal fix: reword the sentence to say the manifest step wrote launch.json and the README describes what it must contain.","line":93,"path":"README.md","reproduction":"Run `ls launch.json` from the repository root: the file exists (20 lines, kind custom_token, token.contract IFOToken). Read README.md line 93-94: 'this repository deliberately does not provide one'. Expected: the README and the tree agree. Actual: the README denies a file that is committed (git log --stat shows launch.json added in 4ab2cec, after README.md in a563872).","severity":"info","snippet":"The manifest step owns `launch.json`; this repository deliberately does not","title":"README states the repository deliberately provides no launch.json, but launch.json is committed in the tree"},{"citation":"resolved","description":"Merged from audit_flow (the only specialist that raised it); reproduced with a scratch Foundry test on this tree. IFOToken inherits the unmodified OpenZeppelin v5.1.0 ERC20 (byte-identical to upstream, verified). approve() overwrites the stored allowance, so an owner reducing a nonzero allowance is exposed to the well-known ERC-20 approval race. This is the ERC-20 standard's behaviour; OpenZeppelin v5 deliberately removed increaseAllowance/decreaseAllowance, and README.md lines 126-130 already instruct holders to revoke to zero and wait for inclusion before approving a new amount. Recorded as a documented trust assumption on holder behaviour, not a defect in the requester's code, and it does not touch any launch flow (the factory, distributor and pool manager use transfer and settle paths, not allowance reductions). No fix required; holders mitigate by approve(0) first.","line":127,"path":"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol","reproduction":"State: token deployed, owner holds 150e18 IFO, spender is any address. 1) owner calls approve(spender, 100e18). 2) owner broadcasts approve(spender, 50e18). 3) spender front-runs with transferFrom(owner, spender, 100e18): succeeds, allowance becomes 0. 4) owner's approve(spender, 50e18) lands: allowance = 50e18. 5) spender calls transferFrom(owner, spender, 50e18): succeeds. Expected by the owner's intent: spender limited to 50e18 total. Actual: balanceOf(spender) = 150e18, balanceOf(owner) = 0. Verified by a scratch test (test/scratch/ApprovalRace.t.sol, removed) that executes exactly these five calls with vm.prank and asserts the final balances; it passes on this tree, confirming the trace.","severity":"info","snippet":"    function approve(address spender, uint256 value) public virtual returns (bool) {","title":"Standard ERC-20 approve ordering: lowering a nonzero allowance lets a front-running spender collect old and new amounts (inherent to ERC-20, documented, no code change required)"}],"hash":"70c1977bce1cfb59ea3fbbe4061fe637551fe162cc7d154ebe00cfc9f6fc848c","nodeId":"80b2fc47-8191-42a6-9406-d20d9193badf","outcome":"completed","summary":"The review is complete and written to `.imd-findings.json`. The working tree is otherwise unchanged, and my scratch test directory is removed.\n\n**Outcome:** no defect in the token itself. IFOToken is a seven-line wrapper over OpenZeppelin v5.1.0 ERC20 with an argument-free constructor minting the full supply to msg.sender. Its only state-changing entry points are approve, transfer and transferFrom, all unmodified. I confirmed the vendored OpenZeppelin files are byte-identical to the upstream commit, the manifest uses only schema keys and matches the code, creation and runtime bytecode are far under size limits, and the full suite of 46 tests passes, including the 256-run invariant.\n\n**Specialist findings, judged:**\n\n- **Kept at low, from audit_permissions:** seven vendored forge-std files fail the digest check that README.md promises. I reproduced the mismatch and fetched upstream myself: the recorded digests match upstream, and the vendored copies equal upstream once whitespace is stripped, so this is a post-hash reformat on test-only files. Production provenance holds. Raised from info to low because a documented verification procedure fails as shipped.\n- **Kept at info, from audit_flow:** the ERC-20 approve ordering race. Reproduced with a scratch test executing the five-call trace. It is inherent to the standard, documented in the README, and touches no launch flow, so no fix is required.\n- **Added at info, mine:** README.md line 93 says the repository deliberately provides no launch.json, but the manifest step committed one later. The manifest content agrees with the README table, so only the sentence is stale.\n\n**Coverage:** all three entry points answered as holds, plus four invariant rows covering fixed supply, exact launch flows, factory deployability and manifest consistency. No duplicates existed across specialists, and nothing was dropped. No finding reached critical or high, so no proof files were attached.","treeHash":null,"usage":{"cachedInputTokens":541323,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":13367,"runtime":"claude","turns":22,"wallClockMs":213626}},{"artifacts":[],"attempt":1,"bundleHash":"c44b2acb49471a4c399b0e0e41d04d9fe5e19346b63bd050df5c791f50a3afab","device":"294694a214b6ec04","findings":[],"hash":"8f7f22655d1910cbab564599a071bb90966ab9c7a6394ab2bf3f6ae233f1024f","nodeId":"85d36090-aa3e-4afa-80ed-386bd64cb078","outcome":"completed","summary":"Added 15 adversarial tests and expanded invariants to cover 32,768 random calls, including failure paths, allowance rollback, and holder transferability.\n\nValidation passed: clean offline `forge build` and all 46 tests. No defects found in these checks. All changes are under `test/`.","treeHash":"da3195451095226801e14aa33df6b479bbabb4e1","usage":{"cachedInputTokens":812672,"inputTokens":118824,"model":"gpt-6-astra","outputTokens":13268,"runtime":"codex","turns":5,"wallClockMs":400823}},{"artifacts":[],"attempt":1,"bundleHash":"556580fa7af816e1b4404d4dcc7b05eca464c4e815ceba67ae5c7807105b84ba","device":"48cf2e19b6c54386","findings":[],"hash":"95ee663953664180472da23ff13908f1ce466c008b819176050e120b34423a6a","nodeId":"effd6a05-18e6-4e5e-abc3-eeaa1a0ad88f","outcome":"completed","summary":"Created [launch.json](/home/imd/.identitymd/work/c4a250b4-cc63-4505-b92c-ba262076a88a/effd6a05-18e6-4e5e-abc3-eeaa1a0ad88f/launch.json) matching `IFOToken`, its empty constructor arguments, exact supply, and required pool/economics.\n\n`forge build` succeeded; `forge test` passed all 31 tests. Only the manifest is changed for submission.","treeHash":"3b7a4cae6a632678da43bae768ade4b0cc4b5cdf","usage":{"cachedInputTokens":186240,"inputTokens":26301,"model":"gpt-6-astra","outputTokens":2193,"runtime":"codex","turns":3,"wallClockMs":70903}},{"artifacts":[],"attempt":1,"bundleHash":"1305809849ee37d7acbc00483e25be419c9b818a2e92f1e642de271e88651f82","device":"308998a1407291a8","findings":[],"hash":"af9d190cdd8e343b9a3feec091e4143e15f952d32e6d918a0aa7739aed50bc6b","nodeId":"143ef173-e866-476b-9900-46a9c3fe7ba3","outcome":"completed","summary":"Implemented IFO with 18 decimals and a fixed supply of 1,000,000,000 tokens, minted once to the deployer. Included vendored dependencies, tests, and deployment documentation.\n\nVerification passed:\n\n- `forge build`\n- `forge test`: 31 tests passed\n- `forge fmt --check`\n- Clean offline build and tests with an empty environment","treeHash":"9b4c5032c749f24850fe73809517bfa712b0bf0b","usage":{"cachedInputTokens":431104,"inputTokens":60845,"model":"gpt-6-astra","outputTokens":15374,"runtime":"codex","turns":5,"wallClockMs":401099}}],"verification":[{"checks":[{"durationMs":1397,"exitCode":0,"name":"build","output":"Compiling 29 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.30s\nCompiler run successful!\n","passed":true},{"durationMs":9830,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 15 tests for test/IFOToken.adversarial.t.sol:IFOTokenAdversarialTest\n[PASS] testFuzz_ApprovalDoesNotFollowTransferredTokens(uint256) (runs: 1000, μ: 246548, ~: 246382)\nLogs:\n  Bound result 879706489509635516058999457\n\n[PASS] testFuzz_ApprovalReplacementIsIsolatedByOwnerAndSpender(uint256,uint256,uint256) (runs: 1000, μ: 341174, ~: 341593)\n[PASS] testFuzz_ApprovedBalanceOverrunRollsBackAllowance(uint256,uint256,uint256,bool) (runs: 1000, μ: 241427, ~: 239706)\nLogs:\n  Bound result 14937\n  Bound result 15088\n  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129633585\n\n[PASS] testFuzz_DelegatedSelfTransferPreservesBalanceAndSpendsApproval(uint256,uint256,uint256) (runs: 1000, μ: 239074, ~: 240252)\nLogs:\n  Bound result 9\n  Bound result 2\n\n[PASS] testFuzz_ExhaustedApprovalCannotBeReusedAfterTokensReturn(uint256,uint256) (runs: 1000, μ: 417292, ~: 417660)\nLogs:\n  Bound result 4\n  Bound result 0\n\n[PASS] testFuzz_ZeroRecipientFailurePreservesAnyAllowance(uint256,uint256) (runs: 1000, μ: 176936, ~: 177585)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_ZeroValueTransfersPreserveExistingApproval(uint256) (runs: 1000, μ: 241943, ~: 242205)\n[PASS] test_DelegatedSelfTransferCannotExceedBalance() (gas: 231653)\n[PASS] test_InfiniteApprovalCanBeReplacedAndRevokedAfterUse() (gas: 428221)\n[PASS] test_MaxMinusOneAllowanceIsFinite() (gas: 199754)\n[PASS] test_MaximumApprovalDoesNotAllowMaximumTransfer() (gas: 175659)\n[PASS] test_OneWeiAllowanceCannotBeSpentTwice() (gas: 286667)\n[PASS] test_TransferFromByHolderRequiresSelfApproval() (gas: 305421)\n[PASS] test_ZeroDelegatedTransferToZeroRejectsInfiniteApproval() (gas: 170503)\n[PASS] test_ZeroSpenderRejectsZeroAndMaximumApproval() (gas: 204299)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 108.67ms (735.58ms CPU time)\n\nRan 30 tests for test/IFOToken.t.sol:IFOTokenTest\n[PASS] testFuzz_AllowanceOverrunAlwaysReverts(uint256) (runs: 1000, μ: 119320, ~: 119478)\nLogs:\n  Bound result 243236174832095370969632076\n\n[PASS] testFuzz_DelegatedTransfersDeliverExactAmount(uint256,uint256) (runs: 1000, μ: 162926, ~: 164889)\nLogs:\n  Bound result 8\n  Bound result 1\n\n[PASS] testFuzz_TransfersConserveSupply(uint256,address) (runs: 1000, μ: 93288, ~: 93578)\nLogs:\n  Bound result 1354642679463712231699189836009933487270929324138\n  Bound result 540695260460153410714249779\n\n[PASS] test_ApprovalCanBeReplacedAndRevoked() (gas: 183149)\n[PASS] test_ApproveEmitsEventWithoutMovingTokens() (gas: 88821)\n[PASS] test_ApproveZeroSpenderReverts() (gas: 37633)\n[PASS] test_ConstructorEmitsExactlyOneMintEvent() (gas: 9654)\n[PASS] test_Create2FactoryReceivesEntireSupply() (gas: 297029)\n[PASS] test_DeployerCannotSpendHolderTokensWithoutApproval() (gas: 157899)\n[PASS] test_DirectEtherPaymentReverts() (gas: 36819)\n[PASS] test_EOADeployerReceivesEntireSupply() (gas: 28202)\n[PASS] test_InfiniteAllowanceIsNotDecremented() (gas: 139420)\n[PASS] test_LaunchDistributionClaimsAndPoolTransfersArriveWhole() (gas: 645436)\n[PASS] test_MetadataAndInitialSupply() (gas: 107584)\n[PASS] test_NoPostDeploymentMintOrAdministrativeEntryPoints() (gas: 1463739)\n[PASS] test_RuntimeHasNoForbiddenOpcodesAndFitsDeploymentLimit() (gas: 1038922)\n[PASS] test_SelfTransferFromSpendsAllowanceButPreservesBalance() (gas: 103290)\n[PASS] test_SelfTransferPreservesBalance() (gas: 51442)\n[PASS] test_TransferEmitsEventAndDeliversExactAmount() (gas: 91539)\n[PASS] test_TransferEntireSupply() (gas: 75722)\n[PASS] test_TransferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 202010)\n[PASS] test_TransferFromInsufficientAllowanceRevertsWithoutStateChange() (gas: 115701)\n[PASS] test_TransferFromInsufficientBalanceRollsBackAllowance() (gas: 126219)\n[PASS] test_TransferFromToZeroRollsBackAllowance() (gas: 114264)\n[PASS] test_TransferFromZeroSenderRevertsEvenForZeroAmount() (gas: 55140)\n[PASS] test_TransferInsufficientBalanceRevertsWithoutStateChange() (gas: 120026)\n[PASS] test_TransferMaxUintRevertsWithBalanceError() (gas: 54955)\n[PASS] test_TransferToZeroRevertsEvenForZeroAmount() (gas: 71926)\n[PASS] test_ZeroTransferFromDoesNotRequireAllowance() (gas: 78694)\n[PASS] test_ZeroTransferFromEmptyAccountEmitsEvent() (gas: 73421)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 108.62ms (316.29ms CPU time)\n\nRan 1 test for test/IFOToken.invariant.t.sol:IFOTokenInvariantTest\n[PASS] invariant_FixedSupplyAndIndependentLedgerMatch() (runs: 256, calls: 32768, reverts: 0)\n\n╭--------------+--------------------------+-------+---------+----------╮\n| Contract     | Selector                 | Calls | Reverts | Discards |\n+======================================================================+\n| TokenHandler | approve                  | 3603  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | attemptAllowanceOverrun  | 3729  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | attemptApprovedOverspend | 3554  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | attemptOverspend         | 3659  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | attemptZeroRecipient     | 3624  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | attemptZeroSpender       | 3629  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | revoke                   | 3708  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | transfer                 | 3614  | 0       | 0        |\n|--------------+--------------------------+-------+---------+----------|\n| TokenHandler | transferFrom             | 3648  | 0       | 0        |\n╰--------------+--------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 250000000000000000000000000\n  Bound result 250000000000000000000000000\n  Bound result 250000000000000000000000000\n  Bound result 250000000000000000000000001\n  Bound result 250000000000000000000000001\n  Bound result 250000000000000000000000001\n  Bound result 250000000000000000000000001\n  Bound result 794671362005561552158141156\n  Bound result 6783\n  Bound result 0\n  Bound result 249999999999999999999999997\n  Bound result 1\n  Bound result 2\n  Bound result 3163692633\n  Bound result 54137669600113065165772264\n  Bound result 0\n  Bound result 0\n  Bound result 5643\n  Bound result 0\n  Bound result 96\n  Bound result 3\n  Bound result 57\n  Bound result 13\n  Bound result 238182009500613346054960938\n  Bound result 0\n  Bound result 11000000000000000000\n  Bound result 6843\n  Bound result 9590\n  Bound result 10\n  Bound result 96\n  Bound result 0\n  Bound result 1602\n  Bound result 0\n  Bound result 850\n  Bound result 7875\n  Bound result 6282\n  Bound result 6052\n  Bound result 29\n  Bound result 6000000000000000000\n  Bound result 0\n  Bound result 48981637211121400341468038\n  Bound result 9\n  Bound result 11000000000000000000\n  Bound result 40000000000000000000\n  Bound result 235\n  Bound result 16\n  Bound result 515795702217614677937553269\n  Bound result 3\n  Bound result 0\n  Bound result 424052780402177571145692441\n  Bound result 13\n  Bound result 3946\n  Bound result 241\n  Bound result 33239281062329037253940691\n  Bound result 859231741761180943291822325\n  Bound result 132980996682701340417632543\n  Bound result 130291372024646508487556124\n  Bound result 202434187206577439073918808\n  Bound result 132980996682701340417632543\n  Bound result 1319\n  Bound result 66\n  Bound result 9411\n  Bound result 0\n  Bound result 1610\n  Bound result 50421386050432785876978495\n  Bound result 60000000000000000000\n  Bound result 3106\n  Bound result 0\n  Bound result 1382754376766993202\n  Bound result 8\n  Bound result 123000000000000000000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.75s (9.75s CPU time)\n\nRan 3 test suites in 9.75s (9.97s CPU time): 46 tests passed, 0 failed, 0 skipped (46 total tests)\n","passed":true},{"durationMs":33,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IFOToken.approve(address,uint256)\",\"IFOToken.transfer(address,uint256)\",\"IFOToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":58,\"README.md\":148,\"foundry.toml\":21,\"remappings.txt\":2,\"src/IFOToken.sol\":17,\"test/IFOToken.adversarial.t.sol\":246,\"test/IFOToken.invariant.t.sol\":236,\"test/IFOToken.t.sol\":392,\"test/README.md\":41,\"test/helpers/TokenFactory.sol\":15},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"8f7f22655d1910cbab564599a071bb90966ab9c7a6394ab2bf3f6ae233f1024f","verifiedTreeHash":"da3195451095226801e14aa33df6b479bbabb4e1","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":1319,"exitCode":0,"name":"build","output":"Compiling 28 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.22s\nCompiler run successful!\n","passed":true},{"durationMs":3868,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 30 tests for test/IFOToken.t.sol:IFOTokenTest\n[PASS] testFuzz_AllowanceOverrunAlwaysReverts(uint256) (runs: 512, μ: 119071, ~: 119442)\nLogs:\n  Bound result 580932602041105790449312973\n\n[PASS] testFuzz_DelegatedTransfersDeliverExactAmount(uint256,uint256) (runs: 512, μ: 162649, ~: 164885)\nLogs:\n  Bound result 511278739690686098978735884\n  Bound result 9527776885591397076431835\n\n[PASS] testFuzz_TransfersConserveSupply(uint256,address) (runs: 512, μ: 92943, ~: 93131)\nLogs:\n  Bound result 726793634716888591578695590\n\n[PASS] test_ApprovalCanBeReplacedAndRevoked() (gas: 183149)\n[PASS] test_ApproveEmitsEventWithoutMovingTokens() (gas: 88821)\n[PASS] test_ApproveZeroSpenderReverts() (gas: 37633)\n[PASS] test_ConstructorEmitsExactlyOneMintEvent() (gas: 9654)\n[PASS] test_Create2FactoryReceivesEntireSupply() (gas: 297029)\n[PASS] test_DeployerCannotSpendHolderTokensWithoutApproval() (gas: 157899)\n[PASS] test_DirectEtherPaymentReverts() (gas: 36819)\n[PASS] test_EOADeployerReceivesEntireSupply() (gas: 28202)\n[PASS] test_InfiniteAllowanceIsNotDecremented() (gas: 139420)\n[PASS] test_LaunchDistributionClaimsAndPoolTransfersArriveWhole() (gas: 645436)\n[PASS] test_MetadataAndInitialSupply() (gas: 107584)\n[PASS] test_NoPostDeploymentMintOrAdministrativeEntryPoints() (gas: 1463739)\n[PASS] test_RuntimeHasNoForbiddenOpcodesAndFitsDeploymentLimit() (gas: 1038922)\n[PASS] test_SelfTransferFromSpendsAllowanceButPreservesBalance() (gas: 103290)\n[PASS] test_SelfTransferPreservesBalance() (gas: 51442)\n[PASS] test_TransferEmitsEventAndDeliversExactAmount() (gas: 91539)\n[PASS] test_TransferEntireSupply() (gas: 75722)\n[PASS] test_TransferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 202010)\n[PASS] test_TransferFromInsufficientAllowanceRevertsWithoutStateChange() (gas: 115701)\n[PASS] test_TransferFromInsufficientBalanceRollsBackAllowance() (gas: 126219)\n[PASS] test_TransferFromToZeroRollsBackAllowance() (gas: 114264)\n[PASS] test_TransferFromZeroSenderRevertsEvenForZeroAmount() (gas: 55140)\n[PASS] test_TransferInsufficientBalanceRevertsWithoutStateChange() (gas: 120026)\n[PASS] test_TransferMaxUintRevertsWithBalanceError() (gas: 54955)\n[PASS] test_TransferToZeroRevertsEvenForZeroAmount() (gas: 71926)\n[PASS] test_ZeroTransferFromDoesNotRequireAllowance() (gas: 78694)\n[PASS] test_ZeroTransferFromEmptyAccountEmitsEvent() (gas: 73421)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 11.70ms (45.76ms CPU time)\n\nRan 1 test for test/IFOToken.invariant.t.sol:IFOTokenInvariantTest\n[PASS] invariant_FixedSupplyAndIndependentLedgerMatch() (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------+------------------+-------+---------+----------╮\n| Contract     | Selector         | Calls | Reverts | Discards |\n+==============================================================+\n| TokenHandler | approve          | 4097  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | attemptOverspend | 4066  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | transfer         | 4155  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | transferFrom     | 4066  | 0       | 0        |\n╰--------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 24576\n  Bound result 0\n  Bound result 3208\n  Bound result 18\n  Bound result 699093182839363483699197611\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 11\n  Bound result 0\n  Bound result 60000000000000000000\n  Bound result 6079\n  Bound result 999999999999999999999999999\n  Bound result 0\n  Bound result 0\n  Bound result 244\n  Bound result 588459595917906373323185377\n  Bound result 552\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 9\n  Bound result 0\n  Bound result 0\n  Bound result 472701752663712782564\n  Bound result 805429225866880690787776609\n  Bound result 7\n  Bound result 2651\n  Bound result 259788491286\n  Bound result 0\n  Bound result 228\n  Bound result 13\n  Bound result 273\n  Bound result 176920137239318593648918438\n  Bound result 1498\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.79s (3.79s CPU time)\n\nRan 2 test suites in 3.79s (3.81s CPU time): 31 tests passed, 0 failed, 0 skipped (31 total tests)\n","passed":true},{"durationMs":34,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IFOToken.approve(address,uint256)\",\"IFOToken.transfer(address,uint256)\",\"IFOToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":58,\"README.md\":148,\"foundry.toml\":21,\"launch.json\":20,\"remappings.txt\":2,\"src/IFOToken.sol\":17,\"test/IFOToken.invariant.t.sol\":111,\"test/IFOToken.t.sol\":391,\"test/helpers/TokenFactory.sol\":15},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"95ee663953664180472da23ff13908f1ce466c008b819176050e120b34423a6a","verifiedTreeHash":"3b7a4cae6a632678da43bae768ade4b0cc4b5cdf","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":1196,"exitCode":0,"name":"build","output":"Compiling 28 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.08s\nCompiler run successful!\n","passed":true},{"durationMs":3823,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 30 tests for test/IFOToken.t.sol:IFOTokenTest\n[PASS] testFuzz_AllowanceOverrunAlwaysReverts(uint256) (runs: 512, μ: 119245, ~: 119484)\nLogs:\n  Bound result 6\n\n[PASS] testFuzz_DelegatedTransfersDeliverExactAmount(uint256,uint256) (runs: 512, μ: 162677, ~: 164885)\nLogs:\n  Bound result 1\n  Bound result 0\n\n[PASS] testFuzz_TransfersConserveSupply(uint256,address) (runs: 512, μ: 92911, ~: 93125)\nLogs:\n  Bound result 243835204621376929926914350\n\n[PASS] test_ApprovalCanBeReplacedAndRevoked() (gas: 183149)\n[PASS] test_ApproveEmitsEventWithoutMovingTokens() (gas: 88821)\n[PASS] test_ApproveZeroSpenderReverts() (gas: 37633)\n[PASS] test_ConstructorEmitsExactlyOneMintEvent() (gas: 9654)\n[PASS] test_Create2FactoryReceivesEntireSupply() (gas: 297029)\n[PASS] test_DeployerCannotSpendHolderTokensWithoutApproval() (gas: 157899)\n[PASS] test_DirectEtherPaymentReverts() (gas: 36819)\n[PASS] test_EOADeployerReceivesEntireSupply() (gas: 28202)\n[PASS] test_InfiniteAllowanceIsNotDecremented() (gas: 139420)\n[PASS] test_LaunchDistributionClaimsAndPoolTransfersArriveWhole() (gas: 645436)\n[PASS] test_MetadataAndInitialSupply() (gas: 107584)\n[PASS] test_NoPostDeploymentMintOrAdministrativeEntryPoints() (gas: 1463739)\n[PASS] test_RuntimeHasNoForbiddenOpcodesAndFitsDeploymentLimit() (gas: 1038922)\n[PASS] test_SelfTransferFromSpendsAllowanceButPreservesBalance() (gas: 103290)\n[PASS] test_SelfTransferPreservesBalance() (gas: 51442)\n[PASS] test_TransferEmitsEventAndDeliversExactAmount() (gas: 91539)\n[PASS] test_TransferEntireSupply() (gas: 75722)\n[PASS] test_TransferFromConsumesFiniteAllowanceAndEmitsTransfer() (gas: 202010)\n[PASS] test_TransferFromInsufficientAllowanceRevertsWithoutStateChange() (gas: 115701)\n[PASS] test_TransferFromInsufficientBalanceRollsBackAllowance() (gas: 126219)\n[PASS] test_TransferFromToZeroRollsBackAllowance() (gas: 114264)\n[PASS] test_TransferFromZeroSenderRevertsEvenForZeroAmount() (gas: 55140)\n[PASS] test_TransferInsufficientBalanceRevertsWithoutStateChange() (gas: 120026)\n[PASS] test_TransferMaxUintRevertsWithBalanceError() (gas: 54955)\n[PASS] test_TransferToZeroRevertsEvenForZeroAmount() (gas: 71926)\n[PASS] test_ZeroTransferFromDoesNotRequireAllowance() (gas: 78694)\n[PASS] test_ZeroTransferFromEmptyAccountEmitsEvent() (gas: 73421)\nSuite result: ok. 30 passed; 0 failed; 0 skipped; finished in 14.00ms (51.44ms CPU time)\n\nRan 1 test for test/IFOToken.invariant.t.sol:IFOTokenInvariantTest\n[PASS] invariant_FixedSupplyAndIndependentLedgerMatch() (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------+------------------+-------+---------+----------╮\n| Contract     | Selector         | Calls | Reverts | Discards |\n+==============================================================+\n| TokenHandler | approve          | 4096  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | attemptOverspend | 4070  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | transfer         | 4113  | 0       | 0        |\n|--------------+------------------+-------+---------+----------|\n| TokenHandler | transferFrom     | 4105  | 0       | 0        |\n╰--------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 12\n  Bound result 1\n  Bound result 96\n  Bound result 18\n  Bound result 0\n  Bound result 3\n  Bound result 4228666474\n  Bound result 170024929213363468026455463\n  Bound result 3386\n  Bound result 5\n  Bound result 1057502096\n  Bound result 5163\n  Bound result 2\n  Bound result 313\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 16\n  Bound result 2074101768\n  Bound result 24576\n  Bound result 646442475\n  Bound result 2719046647874867270544356\n  Bound result 3430\n  Bound result 226\n  Bound result 14\n  Bound result 1350242121\n  Bound result 0\n  Bound result 16\n  Bound result 2274\n  Bound result 4600051224516056617418233\n  Bound result 283020605275025852017499694\n  Bound result 3386\n  Bound result 2\n  Bound result 6081\n  Bound result 4769\n  Bound result 11\n  Bound result 193294211\n  Bound result 2\n  Bound result 3872\n  Bound result 211801473\n  Bound result 242\n  Bound result 1074\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.74s (3.73s CPU time)\n\nRan 2 test suites in 3.74s (3.75s CPU time): 31 tests passed, 0 failed, 0 skipped (31 total tests)\n","passed":true},{"durationMs":33,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IFOToken.approve(address,uint256)\",\"IFOToken.transfer(address,uint256)\",\"IFOToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":58,\"README.md\":148,\"foundry.toml\":21,\"remappings.txt\":2,\"src/IFOToken.sol\":17,\"test/IFOToken.invariant.t.sol\":111,\"test/IFOToken.t.sol\":391,\"test/helpers/TokenFactory.sol\":15},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":476,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":255,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/IFOToken.sol:12: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"af9d190cdd8e343b9a3feec091e4143e15f952d32e6d918a0aa7739aed50bc6b","verifiedTreeHash":"9b4c5032c749f24850fe73809517bfa712b0bf0b","verifierVersion":"0.1.0+fb8278c5"}]}