{"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":"6af89013-3562-4138-80fc-4d13a56d6313","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"8e44d1d187132bd1f236d62a140f8b2d5ededb9995dd454d735fd1ce11786d3d","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":"0514d898aedd42361a597cbf93345986c3f42ec09bed637fc9773f30fa225892","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":"3fc2f98e3a9795343247c508cda5fc52255116ec061f812ba0fdb5772ac24276","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"26e0b46f4033205b75b79fbaddb026071fd2f340b0244f75eb8e92829266e477","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":"aebe21dccb25d28111bc1e76053bf74fca4c4674c4ba3228a34fd12870327c2d","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":"99e67e54f741862978b60895c7a19a6b274415b10a57cfe44374a414ef7f366b","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"5b568a5d9dcb87d3a575906fd2a57a765e2afbdf6ff0870ca20158eaa69999c7","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"5b568a5d9dcb87d3a575906fd2a57a765e2afbdf6ff0870ca20158eaa69999c7","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"787ca1e4d395538f0053ff4b4389e1b8bcccad9356ae9f4ea5f7d994db756213","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"40600fd493504ea0445b0d8020fe2992cd0bd8cfe2463522f6ea6e6cc43f59aa","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: AutonomoUs oracle (ORACLE).\nToken name: AutonomoUs oracle\nToken symbol: ORACLE\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"d8166c33a078e87b4017fa13dabd7cd608239513fbf5fb74efd804323cbc92c5","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"6af89013-3562-4138-80fc-4d13a56d6313","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1132-autonomous-oracle"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52129","feedbackHash":"28c5008b5331bedca68a476eaa19da2826ff3f65fdb05e0f8f3789935c3ec0cc","nodeKey":"audit_economics","submissionHash":"8e44d1d187132bd1f236d62a140f8b2d5ededb9995dd454d735fd1ce11786d3d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51382","feedbackHash":"d05373b1410fa71ae60213a13eba585096049b9550ce243412acbe81a51127ee","nodeKey":"audit_flow","submissionHash":"0514d898aedd42361a597cbf93345986c3f42ec09bed637fc9773f30fa225892","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52131","feedbackHash":"a60caa84552ee2fd281c8f6970083439f6d67664255104de0009476fa9005195","nodeKey":"audit_judge","submissionHash":"3fc2f98e3a9795343247c508cda5fc52255116ec061f812ba0fdb5772ac24276","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51225","feedbackHash":"a8d2124614b7230daaf959e01602d47e64c3909816bc449faf15aa955587372c","nodeKey":"audit_math","submissionHash":"26e0b46f4033205b75b79fbaddb026071fd2f340b0244f75eb8e92829266e477","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52138","feedbackHash":"82d2e0362edf926defb10c286fb361e37c0cd9778af84c165432ca3e1cf0a789","nodeKey":"audit_permissions","submissionHash":"aebe21dccb25d28111bc1e76053bf74fca4c4674c4ba3228a34fd12870327c2d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51071","feedbackHash":"1c5834a773d2db3362b6a1838327a3ed77622e127d90ab8d2b03262e48ea065f","nodeKey":"build_contract_project","submissionHash":"99e67e54f741862978b60895c7a19a6b274415b10a57cfe44374a414ef7f366b","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51041","feedbackHash":"fe488d1329c7143e5dae2f061d0a08f564c5d3e46d87fc49069fe2db2c1a2e15","nodeKey":"manifest","submissionHash":"787ca1e4d395538f0053ff4b4389e1b8bcccad9356ae9f4ea5f7d994db756213","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52190","feedbackHash":"bbbecfc96ac5676c6dd61f0a30540d1842c59cb0b17be44924ba578939645b66","nodeKey":"write_foundry_tests","submissionHash":"40600fd493504ea0445b0d8020fe2992cd0bd8cfe2463522f6ea6e6cc43f59aa","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"049de516097d9c5dcac2c94e0f623f03c4e16a4d5463073d0705ae7cd2a93625","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"85f29f4c09dba910","findings":[{"citation":"resolved","description":"The contract declares ERC-6093 style errors but omits ERC20InvalidSender: `_transfer` validates `to` and the balance only, never `from`. Because `_allowances[address(0)][anyone]` is 0 and `_balances[address(0)]` is 0, a zero-value `transferFrom(address(0), to, 0)` passes both checks (0 < 0 is false) and emits `Transfer(address(0), to, 0)`, the exact shape of a mint event. Balances and totalSupply are untouched, so there is no fund impact; the effect is limited to event-driven indexers or explorers that treat Transfer-from-zero as a mint and could display spurious zero-value mints to arbitrary recipients. OpenZeppelin's ERC20 rejects this input with ERC20InvalidSender(address(0)). Minimal fix: `if (from == address(0)) revert ERC20InvalidSender(address(0));` at the top of `_transfer` (adding the error declaration). Any non-zero value from address(0) already reverts with ERC20InsufficientAllowance, verified.","line":139,"path":"src/OracleToken.sol","reproduction":"State: fresh OracleToken deployed by `deployer`. Call from any EOA `alice` (no allowance, no balance): `token.transferFrom(address(0), bob, 0)`. Expected (ERC-6093 semantics the contract claims to follow): revert ERC20InvalidSender(address(0)). Actual: returns true and emits Transfer(from=address(0), to=bob, value=0). Verified with forge: `vm.expectEmit(true,true,true,true); emit IERC20.Transfer(address(0), bob, 0); vm.prank(alice); assertTrue(token.transferFrom(address(0), bob, 0));` passes on the current code. Control: `token.transferFrom(address(0), bob, 1)` reverts with ERC20InsufficientAllowance(alice, 0, 1), so no balance can ever be created.","severity":"info","snippet":"        if (to == address(0)) revert ERC20InvalidReceiver(address(0));\n        uint256 fromBalance = _balances[from];\n        if (fromBalance < value) revert ERC20InsufficientBalance(from, fromBalance, value);","title":"transferFrom accepts address(0) as `from`, so anyone can emit a mint-shaped Transfer(address(0), x, 0) event"}],"hash":"0514d898aedd42361a597cbf93345986c3f42ec09bed637fc9773f30fa225892","nodeId":"79a2fdb4-71ee-4b35-ab30-c900560269d7","outcome":"completed","summary":"Review complete. The findings file is written at the repository root, no source files were changed, and my scratch test directory is removed.\n\n**Result: no fund-affecting defect in the ORACLE token.** `src/OracleToken.sol` is a 150-line self-contained ERC-20 with no external calls, no owner, no mint or burn path, and a constructor that writes the whole 1e27 supply to msg.sender once. I traced all three state-changing entry points against the Execution Trace, Periphery and First Principles guides, and confirmed each by Foundry probes rather than by reading alone.\n\n**One finding, severity info.** `transferFrom(address(0), to, 0)` succeeds from any caller and emits `Transfer(address(0), to, 0)`, which is the shape of a mint event. The cause is that `_transfer` never validates `from`, so the zero allowance and zero balance of address(0) pass the two `<` checks at value 0. Balances and total supply are untouched, and any non-zero value from address(0) reverts, so the impact is limited to event-driven indexers. The fix is a one-line `ERC20InvalidSender` check, matching the ERC-6093 convention the contract already claims.\n\n**Coverage recorded** for all three listed entry points plus the constructor, two invariants, the periphery files and the launch flows. All hold except `transferFrom`, which points at the finding above. Specifically verified:\n\n- Unchecked arithmetic in `_transfer` is sound: the sum of balances is the constructor constant, fuzzed over random multi-actor sequences.\n- Self-transfer, self-recipient `transferFrom`, max allowance, and allowance left intact on a balance revert all behave as intended.\n- Interface selectors match canonical ERC-20 values, and the deploy script reads nothing from the environment.\n- The aderyn large-literal lead resolves to exactly 1e27 and is not a defect.\n\nNothing in my area was left unreached. The existing 31-test suite passes on the current code.","treeHash":null,"usage":{"cachedInputTokens":563580,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":13060,"runtime":"claude","turns":23,"wallClockMs":205930}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4dd74fd7c315da80","findings":[{"citation":"resolved","description":"Boundary (zero input) check from the Boundary guide. `_transfer` rejects a zero recipient but not a zero sender, and `transferFrom` only requires `allowance >= value`, which `0 >= 0` satisfies. So any caller can run `transferFrom(address(0), x, 0)`: the balance check passes (0 < 0 is false), no balance changes, and the contract emits `Transfer(address(0), x, 0)`. The contract says its errors mirror ERC-6093, but it omits `ERC20InvalidSender`, which is the error OpenZeppelin uses to refuse exactly this call. Impact is cosmetic only: no balance or allowance changes, `totalSupply()` is a constant, and an indexer that derives supply from Transfer events adds zero. Indexers or explorers that list `from == address(0)` events as mints will show spurious zero-value mint rows that anyone can create at will. EIP-20 itself permits this (zero-value transfers must emit), so this is a deviation from the OpenZeppelin convention the contract otherwise follows, not a standards violation. Minimal fix, if wanted: `if (from == address(0)) revert ERC20InvalidSender(address(0));` at the top of `_transfer`, with the matching ERC-6093 error declared. Note the same path also lets `transfer(x, 0)` from any empty account emit a zero-value Transfer, which is standard EIP-20 behavior and not a defect.","line":138,"path":"src/OracleToken.sol","reproduction":"State: fresh deployment, deployer holds 1e27. Call, from any address B: `token.transferFrom(address(0), A, 0)`. Expected (OpenZeppelin convention): revert ERC20InvalidSender(address(0)). Actual: returns true and emits `Transfer(address(0), A, 0)`; `balanceOf(A) == 0`, `totalSupply() == 1e27`, allowance(address(0), B) == 0. Verified with a Foundry test using `vm.expectEmit(true,true,true,true); emit Transfer(address(0), A, 0); vm.prank(B); assertTrue(token.transferFrom(address(0), A, 0));` which passes on the current code.","severity":"info","snippet":"    function _transfer(address from, address to, uint256 value) private {\n        if (to == address(0)) revert ERC20InvalidReceiver(address(0));\n        uint256 fromBalance = _balances[from];\n        if (fromBalance < value) revert ERC20InsufficientBalance(from, fromBalance, value);","title":"transferFrom accepts the zero address as `from`, so anyone can emit a zero-value Transfer(address(0), x, 0) that looks like a mint"}],"hash":"26e0b46f4033205b75b79fbaddb026071fd2f340b0244f75eb8e92829266e477","nodeId":"ed97af4e-f624-4af2-8aa9-7dc9da71bb06","outcome":"completed","summary":"The review is complete and the findings file is in place.\n\n**Outcome:** the token holds up under the Math Precision, Boundary and Numerical Gap guides. I found no defect that moves or loses value, and one cosmetic deviation recorded as info.\n\n**What I checked**\n\n- Build and the existing 31 unit and fuzz tests pass under solc 0.8.26.\n- The supply constant on line 37, the only lead from static analysis, is a compile-time checked product equal to 1e27 and nowhere near overflow.\n- The unchecked block in the transfer path is safe. The subtraction is guarded by the balance check and the addition cannot overflow because balances always sum to the constant supply. A full-balance self-transfer nets to zero because the recipient slot is read after the sender slot is written.\n- The allowance path decrements at max minus one, skips the decrement at the max sentinel, and reverts on balance before any write when the value is the max integer.\n- Boundary enumeration is trivial. The contract has no external calls, no payable or fallback paths, no byte decoding and no token-address parameters, so the only sentinel branches are the zero recipient and zero spender, both of which revert as intended.\n- A scratch fuzz test over random transfers among four accounts kept the sum of balances at exactly 1e27 across 256 runs. The scratch directory has been removed.\n\n**The one finding, severity info:** anyone can call transferFrom with the zero address as sender and a zero value. It passes both checks, moves nothing, and emits a Transfer from the zero address that looks like a mint. OpenZeppelin refuses this with ERC20InvalidSender, which the contract omits despite claiming ERC-6093 errors. Indexers that list zero-sender events as mints will show spurious zero-value rows. The reproduction and a one-line fix are in the report.\n\n**Coverage:** all three entry points have rows, plus rows for the supply invariant, the literal lead, the boundary enumeration and the launch flows. Git status is clean apart from the gitignored findings file.","treeHash":null,"usage":{"cachedInputTokens":691903,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":11745,"runtime":"claude","turns":18,"wallClockMs":176048}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"de319b702da6aa2e","findings":[{"citation":"resolved","description":"Merged from audit_math (info), audit_flow (info), audit_economics (low) and write_foundry_tests (low): all four report the same root cause. `_transfer` checks the receiver (`to == address(0)`) but never the sender. `transferFrom` passes any `from` through, and with `from = address(0)` and `value = 0` every guard passes: `_allowances[address(0)][caller]` is 0 and `0 < 0` is false (line 125), and `_balances[address(0)]` is 0 and `0 < 0` is false (line 141). No state changes, and the call emits `Transfer(address(0), to, 0)`. The token's own interface (src/interfaces/IERC20.sol:7) says that shape is a mint, and the contract's NatSpec promises the constructor's mint is the only one. Impact is off-chain only. Balances, allowances and totalSupply (a constant) do not change, and a non-zero value from address(0) reverts with ERC20InsufficientAllowance, so no value can be created or moved. But an unprivileged caller can make explorers, indexers and 'mint after launch' monitors show spurious post-launch mints, with any recipient, as often as they like. The contract adopts the ERC-6093 error set but leaves out ERC20InvalidSender, which OpenZeppelin's ERC20 uses to refuse this call. Severity is low: no funds are at risk and it breaks no on-chain guarantee, only the documented meaning of the event. Minimal fix that keeps intended behaviour: declare `error ERC20InvalidSender(address sender);` and add `if (from == address(0)) revert ERC20InvalidSender(address(0));` as the first line of `_transfer`. The constructor writes `_balances` directly, so the one-time mint is unaffected.","line":138,"path":"src/OracleToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test, Vm} from \"forge-std/Test.sol\";\nimport {OracleToken} from \"src/OracleToken.sol\";\n\n/// @notice Proof for the finding \"transferFrom accepts the zero address as `from`\".\n/// @dev Fails on the current code: `transferFrom(address(0), to, 0)` succeeds from any caller with no\n///      allowance and emits `Transfer(address(0), to, 0)`, which is the shape of a mint event. The\n///      fix is a `from == address(0)` guard in `_transfer` (or `transferFrom`), after which this test\n///      passes because the call reverts.\ncontract ZeroSenderProofTest is Test {\n    OracleToken internal token;\n    address internal deployer = makeAddr(\"deployer\");\n    address internal anyone = makeAddr(\"anyone\");\n\n    function setUp() public {\n        vm.prank(deployer);\n        token = new OracleToken();\n    }\n\n    function test_transferFromZeroAddressSenderReverts() public {\n        vm.prank(anyone);\n        (bool ok,) = address(token).call(abi.encodeCall(OracleToken.transferFrom, (address(0), anyone, 0)));\n        assertFalse(ok, \"transferFrom with from == address(0) must revert; it succeeded and emitted a mint-shaped Transfer\");\n    }\n\n    function test_transferFromZeroAddressSenderEmitsNoMintShapedEvent() public {\n        vm.recordLogs();\n        vm.prank(anyone);\n        (bool ok,) = address(token).call(abi.encodeCall(OracleToken.transferFrom, (address(0), anyone, 0)));\n        ok;\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        for (uint256 i = 0; i < logs.length; i++) {\n            if (logs[i].emitter != address(token)) continue;\n            if (logs[i].topics[0] != keccak256(\"Transfer(address,address,uint256)\")) continue;\n            assertTrue(\n                logs[i].topics[1] != bytes32(0), \"a Transfer event with from == address(0) was emitted after construction\"\n            );\n        }\n    }\n}","reproduction":"State: a fresh OracleToken deployed by `deployer` (holds 1e27). From any address `anyone` with no balance and no allowance, call `token.transferFrom(address(0), anyone, 0)`. Expected: revert (ERC20InvalidSender(address(0))) and no event. Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=anyone, value=0); balanceOf(anyone)==0 and totalSupply()==1e27 are unchanged. Control: `transferFrom(address(0), anyone, 1)` reverts with ERC20InsufficientAllowance(anyone, 0, 1). Reproduced by the judge: I copied both specialist proofs to test/scratch and ran `forge test`. On the current code, test_transferFromZeroAddressReverts, test_transferFromZeroAddressSenderReverts and test_transferFromZeroAddressSenderEmitsNoMintShapedEvent fail with their stated messages. In a scratch copy with the two-line fix applied, all 64 tests pass: the 3 proof tests plus the existing 61 (unit, edge and invariant).","severity":"low","snippet":"    function _transfer(address from, address to, uint256 value) private {\n        if (to == address(0)) revert ERC20InvalidReceiver(address(0));","title":"transferFrom accepts address(0) as `from`, so any caller can emit a mint-shaped Transfer(address(0), to, 0) after launch"}],"hash":"3fc2f98e3a9795343247c508cda5fc52255116ec061f812ba0fdb5772ac24276","nodeId":"d59b5521-aa99-4a56-8496-6a8e3b154391","outcome":"completed","summary":"I found one real defect, rated low, and wrote it to `.imd-findings.json`. Nothing in the tracked tree changed; the only leftovers are git-ignored build output in `out/` and `cache/`.\n\n**Finding 1 (low): `transferFrom` accepts the zero address as the sender** (`src/OracleToken.sol:138`)\n- **Merged:** all four specialist reports describe this same cause, so it is one finding. Two rated it info and two rated it low.\n- **Cause:** `_transfer` refuses a zero recipient but never checks the sender.\n- **Effect:** any caller can run `transferFrom(address(0), to, 0)`. It passes the allowance and balance checks (both are 0, and 0 < 0 is false). It then emits `Transfer(address(0), to, 0)`, which the token's own interface describes as a mint (`IERC20.sol:7`).\n- **Impact:** off-chain only. Balances, allowances and total supply never change, and a non-zero amount from the zero address reverts on the allowance check. Explorers and \"mint after launch\" monitors can be made to show fake mints whenever someone wants.\n- **Fix:** add `if (from == address(0)) revert ERC20InvalidSender(address(0));` at the top of `_transfer` and declare that error.\n- **How I reproduced it:** I ran both proofs the specialists attached. All three of their tests fail on the current code with the reasons the findings give. In a throwaway copy with the fix applied, all 64 tests pass (the three proof tests plus the 61 existing ones). The finding carries the write_foundry_tests proof, which checks both that the call reverts and that no mint-shaped event is emitted.\n\n**Coverage**\n- **`approve`:** holds. It refuses a zero spender and sets the allowance outright.\n- **`transfer`:** holds. A transfer to yourself is handled correctly, there is no fee, and the launch transfers arrive whole.\n- **`transferFrom`:** this is finding 1. Its allowance handling is otherwise correct.\n- **Supply invariant:** holds. The constructor mints 1e27 once to the deployer and nothing can mint, burn or exercise any privilege afterwards. This matches `launch.json` (`totalSupply` and empty `constructorArgs`).\n\n**Leads I dropped**\n- **aderyn \"large numeric literal\" at line 37:** `1_000_000_000 * 10**18` is exactly what the manifest states, so it is not a defect.\n- **slither:** reported nothing.\n\nI couldn't run the protected launch test locally, because it needs the verifier's settings and v4 sources that aren't in this tree. A reading of the token gives no reason to expect it to fail.","treeHash":null,"usage":{"cachedInputTokens":552907,"inputTokens":22,"model":"claude-opus-5-5","outputTokens":7387,"runtime":"claude","turns":13,"wallClockMs":119327}},{"artifacts":[],"attempt":1,"bundleHash":"7b0066bfb71c7dd51428968d0dbcd4d8122703b1b61b0c15796b5f3396571411","device":"3beb94a990617d46","findings":[{"description":"`_transfer` guards `to == address(0)` but not `from == address(0)`, and `transferFrom` reaches it with any `from`. Because `_allowances[address(0)][caller]` is 0 and `0 < 0` is false, and `_balances[address(0)]` is 0 and `0 < 0` is false, `transferFrom(address(0), to, 0)` succeeds from any caller with no allowance and emits `Transfer(address(0), to, 0)`. No balance or supply changes, so no value is at risk; the sum-of-balances and constant-supply invariants still hold. But a `Transfer` whose `from` is the zero address is the ERC-20 convention for a mint, and the contract's own NatSpec on the event says so. Any address can therefore make the token appear to mint (zero-value) to any recipient at any time, after a launch whose floor forbids supply growth. Indexers, explorers and monitoring that flag or count mint events will see spurious mints; a holder-count indexer that adds `to` on a mint will register phantom holders. The ERC-6093 error set the contract adopts includes `ERC20InvalidSender`, which OpenZeppelin's ERC20 raises exactly here; this implementation declares the other four errors but not that one. Fix: revert with `ERC20InvalidSender(address(0))` when `from == address(0)` in `_transfer` (or at the top of `transferFrom`).","line":138,"path":"src/OracleToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test, Vm} from \"forge-std/Test.sol\";\nimport {OracleToken} from \"src/OracleToken.sol\";\n\n/// @notice Proof for the finding \"transferFrom accepts the zero address as `from`\".\n/// @dev Fails on the current code: `transferFrom(address(0), to, 0)` succeeds from any caller with no\n///      allowance and emits `Transfer(address(0), to, 0)`, which is the shape of a mint event. The\n///      fix is a `from == address(0)` guard in `_transfer` (or `transferFrom`), after which this test\n///      passes because the call reverts.\ncontract ZeroSenderProofTest is Test {\n    OracleToken internal token;\n    address internal deployer = makeAddr(\"deployer\");\n    address internal anyone = makeAddr(\"anyone\");\n\n    function setUp() public {\n        vm.prank(deployer);\n        token = new OracleToken();\n    }\n\n    function test_transferFromZeroAddressSenderReverts() public {\n        vm.prank(anyone);\n        (bool ok,) = address(token).call(abi.encodeCall(OracleToken.transferFrom, (address(0), anyone, 0)));\n        assertFalse(ok, \"transferFrom with from == address(0) must revert; it succeeded and emitted a mint-shaped Transfer\");\n    }\n\n    function test_transferFromZeroAddressSenderEmitsNoMintShapedEvent() public {\n        vm.recordLogs();\n        vm.prank(anyone);\n        (bool ok,) = address(token).call(abi.encodeCall(OracleToken.transferFrom, (address(0), anyone, 0)));\n        ok;\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        for (uint256 i = 0; i < logs.length; i++) {\n            if (logs[i].emitter != address(token)) continue;\n            if (logs[i].topics[0] != keccak256(\"Transfer(address,address,uint256)\")) continue;\n            assertTrue(\n                logs[i].topics[1] != bytes32(0), \"a Transfer event with from == address(0) was emitted after construction\"\n            );\n        }\n    }\n}","reproduction":"Deploy OracleToken from `deployer`. From any address `anyone` with no allowance, call `token.transferFrom(address(0), anyone, 0)`. Expected: revert (ERC20InvalidSender or equivalent), no event. Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=anyone, value=0). Run `forge test --match-path test/scratch/ZeroSenderProof.t.sol`: both tests fail on the current code (`transferFrom with from == address(0) must revert; it succeeded and emitted a mint-shaped Transfer` and `a Transfer event with from == address(0) was emitted after construction`) and pass once the guard is added.","severity":"low","title":"transferFrom accepts the zero address as `from`, so anyone can emit a mint-shaped Transfer(0x0, to, 0) after construction"}],"hash":"40600fd493504ea0445b0d8020fe2992cd0bd8cfe2463522f6ea6e6cc43f59aa","nodeId":"189e4b0f-941f-46e9-a54f-f3cdfc39923f","outcome":"completed","summary":"Done. All deliverables are in place and verified.\n\n**What I delivered** (two new files under `test/`, building on the existing 31-test suite rather than rewriting it):\n\n- `test/OracleToken.invariant.t.sol` adds the missing invariant coverage. A handler drives the token from five actors with bounded inputs across eight entry points, four happy paths and four planned failure paths that expect the exact revert and assert nothing moved. Ghost accounting tracks balances, allowances, and per-holder inflow and outflow, and random recipients are registered so the sum invariant stays complete. The suite runs with `fail-on-revert` on, so any unplanned revert is a failure. Inline config sets 256 runs at depth 64. Eight invariants hold: constant supply, sum of balances equals supply, balances and allowances match the ghost record, no balance exceeds supply, the zero address holds nothing, the contract holds no ether, and tokens sent to the token itself never leave. A vacuity guard in `afterInvariant` confirms every sequence actually ran calls.\n- `test/OracleTokenEdge.t.sol` adds 29 unit and property tests for inputs the original suite skipped: the owner needing a self-allowance, `from == to` pulls, zero-value pulls without allowance, the `max` versus `max - 1` allowance boundary, two spenders racing for one balance, no stray `Approval` on pulls, the exact one-word `true` return shape, short calldata rejection, the mint event emitted exactly once, a CREATE2 factory deployment, and the launch flows at their exact percentages. Fuzz tests run at 1000 runs each.\n\n**Result**\n\n| Suite | Tests | Status |\n|---|---|---|\n| Existing unit/fuzz | 31 | pass |\n| Edge cases | 29 | pass |\n| Invariants (256 runs, 16,384 calls) | 1 | pass |\n\n**One finding reported, not tested around.** I wrote it to `.imd-findings.json` at low severity with a self-contained proof. The `_transfer` function guards the recipient but not the sender against the zero address. Anyone can call `transferFrom(address(0), to, 0)` with no allowance and it succeeds, emitting a `Transfer` from the zero address, which is the ERC-20 shape of a mint. No value or supply moves, but after a launch that forbids supply growth, any address can make explorers and indexers see phantom mints. OpenZeppelin reverts here with `ERC20InvalidSender`, which this contract omits from its otherwise ERC-6093 error set. The proof in `test/scratch/ZeroSenderProof.t.sol` fails on the current code with both of its tests and passes once the guard is added.\n\nNothing outside `test/` and the findings file was changed, and nothing was installed. The new test files are uncommitted in the working tree, since the brief did not ask me to commit.","treeHash":"b1b51973d664b36e217a1283e5cd1488aa410309","usage":{"cachedInputTokens":1346498,"inputTokens":578,"model":"claude-fable-5-1","outputTokens":37050,"runtime":"claude","turns":42,"wallClockMs":539251}},{"artifacts":[],"attempt":1,"bundleHash":"cf464fa9866af566f1b1448f33086e79a4df72e5bf174a988cecd67e2aa5f4eb","device":"3bed38612db34f32","findings":[],"hash":"787ca1e4d395538f0053ff4b4389e1b8bcccad9356ae9f4ea5f7d994db756213","nodeId":"6d24d387-1425-4c96-a569-85a99b81acd7","outcome":"completed","summary":"`launch.json` is written and verified. It is the only new or changed file in the tree.\n\n**What the manifest says**\n\n- Kind is custom_token. The token entry names the Solidity contract `OracleToken` with name \"AutonomoUs oracle\", symbol ORACLE, 18 decimals, empty constructorArgs, and totalSupply of 1000000000000000000000000000.\n- The contracts list is empty, since the accepted tree contains only the token and no application contracts.\n- Pool and economics are copied exactly as the launch gives them: IMD pair address, fee 12500, tick spacing 60, one-to-one initialPrice, and the requester's poolBps, initialMarketCapWei and remainderTo.\n- Notes describe the token's fixed supply, absence of privileged roles and fee-free transfers, and state that the swarm share is the factory's and not written in the manifest.\n\n**How I checked it**\n\n- Read the accepted source. The constructor takes no parameters, matching the empty constructorArgs, and mints a constant 1e9 times 1e18 to msg.sender. The ABI from forge inspect confirms a zero-input constructor.\n- Ran a scratch script that parses the manifest and asserts the schema keys, the supply equals the constructor's constant, the economics object is byte-identical to the job's, addresses are lowercase, initialPrice is below 2^256, and notes stay under the 4000-character limit. All assertions passed.\n- Ran forge build and forge test. The build succeeded and all 31 existing tests passed.\n- Confirmed with git status that launch.json is the only untracked or modified path.","treeHash":"9f7c06ea2375fb13f20f2ba7ea871431a1d1ee47","usage":{"cachedInputTokens":177119,"inputTokens":130,"model":"claude-fable-5-1","outputTokens":3227,"runtime":"claude","turns":8,"wallClockMs":66845}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"63c29c49a249ab7e","findings":[{"citation":"resolved","description":"_transfer validates the receiver but never the sender. transferFrom(from=address(0), to, value=0) passes every guard: the allowance of address(0) to msg.sender is 0 and 0 < 0 is false, the balance of address(0) is 0 and 0 < 0 is false, so the unchecked block runs with value 0 and the function emits Transfer(address(0), to, 0) and returns true. The token's own interface documents that a Transfer with from == address(0) is the mint (src/interfaces/IERC20.sol:7), and the design promise is that the only mint event is the constructor's. Any unprivileged caller can therefore produce an arbitrary number of post-launch 'mint' events naming any recipient. On-chain state is untouched: balances, totalSupply and allowances do not change, and a non-zero value from address(0) reverts on the allowance check, so there is no loss of funds. The impact is confined to off-chain consumers that detect minting or build supply history from Transfer-from-zero events (explorers, token-tracker 'mint after launch' alerts, indexers that count mint events rather than sum values), which can be made to show spurious mints of the launched token. OpenZeppelin's ERC20._transfer rejects this with ERC20InvalidSender; the token already uses the ERC-6093 error set but omits that one. Minimal fix that preserves intended behaviour: declare `error ERC20InvalidSender(address sender);` and add `if (from == address(0)) revert ERC20InvalidSender(address(0));` as the first line of _transfer. The constructor writes _balances directly and does not go through _transfer, so the one-time mint is unaffected; verified on a scratch copy that the proof test passes with that change and the existing 31 tests still hold.","line":139,"path":"src/OracleToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {OracleToken} from \"src/OracleToken.sol\";\n\n/// @notice After deployment, nobody should be able to make the token emit a Transfer whose `from` is\n///         the zero address: that shape is reserved for the one-time mint in the constructor\n///         (IERC20 doc: \"Minting emits it with `from` as the zero address\"). On the current code an\n///         unprivileged caller can emit `Transfer(address(0), anyone, 0)` at will through\n///         `transferFrom(address(0), to, 0)`, because `_transfer` checks the receiver but never the\n///         sender, and a zero value passes both the allowance and the balance check.\ncontract ZeroSenderMintEventTest is Test {\n    OracleToken token;\n    address deployer = makeAddr(\"deployer\");\n    address attacker = makeAddr(\"attacker\");\n\n    function setUp() public {\n        vm.prank(deployer);\n        token = new OracleToken();\n    }\n\n    function test_transferFromZeroAddressReverts() public {\n        vm.prank(attacker);\n        (bool ok,) = address(token).call(abi.encodeCall(OracleToken.transferFrom, (address(0), attacker, 0)));\n        assertFalse(ok, \"transferFrom(address(0), to, 0) succeeded and emitted a mint-shaped Transfer\");\n    }\n}","reproduction":"State: token deployed by any deployer; attacker = any address with no balance and no allowance. Call: vm.prank(attacker); token.transferFrom(address(0), attacker, 0). Expected (per the interface doc and OpenZeppelin semantics): revert with ERC20InvalidSender(address(0)). Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=attacker, value=0), as shown in the forge trace. Control: transferFrom(address(0), attacker, 1) reverts with ERC20InsufficientAllowance(attacker, 0, 1), so only the zero-value event spoof is reachable.","severity":"low","snippet":"        if (to == address(0)) revert ERC20InvalidReceiver(address(0));","title":"transferFrom(address(0), to, 0) succeeds and emits a mint-shaped Transfer event after deployment"}],"hash":"8e44d1d187132bd1f236d62a140f8b2d5ededb9995dd454d735fd1ce11786d3d","nodeId":"b2c720b5-5e7a-41f9-ba0d-bf150ec52258","outcome":"completed","summary":"Review complete. The findings file is at the repository root with one low-severity finding and ten coverage rows. No tracked file was changed.\n\n**Outcome.** The token is economically sound for the launch. Supply is a compile-time constant minted once to msg.sender, there are no external calls, no privileged roles, no fee or burn on any path, and the sum of balances stayed equal to total supply under a stateful invariant run. A sync/settle balance-delta mimic of the Uniswap v4 PoolManager received exactly the seeded and sold amounts, so the factory, distributor, pool and trader flows all move what they say.\n\n**One finding, severity low.** A zero-value pull from the zero address succeeds and emits a mint-shaped event.\n\n- Any unprivileged caller can run `transferFrom(address(0), anyone, 0)` and the token emits `Transfer(0x0, anyone, 0)` and returns true. The internal transfer checks the receiver but never the sender, and a zero value passes both the allowance and balance checks at `src/OracleToken.sol:139`.\n- No on-chain state changes, and a non-zero value from the zero address reverts on allowance. The impact is limited to off-chain consumers that treat Transfer-from-zero as a mint, which can be made to show spurious post-launch mints.\n- Minimal fix: add an `ERC20InvalidSender` revert as the first line of the internal transfer, matching OpenZeppelin. The constructor does not go through that function, so the one-time mint is unaffected. I verified the proof test fails on the current code and passes on a scratch copy with that change, with the existing 31 tests still green.\n\n**Coverage.** All three listed entry points have rows: approve and transfer hold, transferFrom carries the finding. Extra rows record the invariants and flows checked from the Economic Security, Invariant and Flow Gap guides: supply conservation, no supply growth, constructor mint to the factory, launch flow exactness, absence of dependencies and privileged powers, and metadata against the brief. Nothing in the assigned area was left unreached.\n\n**Leads not promoted.** The approve overwrite race and the fact that tokens sent to the contract itself are stuck are both standard ERC-20 behaviour and documented in the README, so they are not reported. The aderyn large-literal note at line 37 is the supply constant and is correct.\n\nThe proof test lives at `test/scratch/ZeroSenderMintEvent.t.sol` and its source is embedded in the finding.","treeHash":null,"usage":{"cachedInputTokens":970224,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":15523,"runtime":"claude","turns":22,"wallClockMs":229879}},{"artifacts":[],"attempt":1,"bundleHash":"3dc986b8d090c64553e8c6e1f1b1931399eb4af457eaad327a2ba4ccce5e3e6c","device":"39da99ded7f125c8","findings":[],"hash":"99e67e54f741862978b60895c7a19a6b274415b10a57cfe44374a414ef7f366b","nodeId":"22e00286-fb7c-4b54-99cc-8ff9cafd5d25","outcome":"completed","summary":"The deliverable is complete and verified. `forge build`, `forge test` (31 tests, 0 failures) and `forge fmt --check` all pass with solc 0.8.26 pinned.\n\n**What was built**\n\n- `src/OracleToken.sol`: a self-contained, fixed-supply ERC-20. It returns the name \"AutonomoUs oracle\", symbol \"ORACLE\" and 18 decimals. The constructor takes no arguments and mints 1,000,000,000 × 10^18 to `msg.sender` once. There is no owner, mint, burn, fee, pause, blocklist, library, delegatecall or selfdestruct, so the launch flows the protected harness checks move exactly what they say.\n- `src/interfaces/IERC20.sol`: the interface the token implements.\n- `script/DeployOracleToken.s.sol`: a standalone deploy script whose `run()` reads no environment and hands off to a `deploy()` function the tests call directly. The launch itself deploys through the factory, not this script.\n- `test/OracleToken.t.sol`: unit and fuzz tests for metadata, exact supply, minting to an EOA, a contract deployer and the script, success paths with events, every revert path, the absence of mint or admin or freeze entry points, rejection of ETH and unknown selectors, an opcode scan, and conservation of supply.\n- `foundry.toml` at the repository root with `bytecode_hash = \"none\"`, `cbor_metadata = false`, optimizer on, no ffi and no fs permissions. `remappings.txt` maps forge-std.\n- `lib/forge-std/`: forge-std v1.11.0 vendored as plain files, exported with `git archive` so no nested repository or submodule remains.\n- `README.md`: parameters, launch flow, assumptions, deployment paths, \"After launch\" (nothing to set), security notes and trust assumptions, and the tooling that ran.\n\n**Things to note**\n\n- No `launch.json` and no `.imd-blocked.json` were written. Nothing in the brief needed requester input.\n- Slither and Mythril were not available here and did not run; the README says so.\n- Nothing is committed. The working tree holds only the eight new paths listed above, and the vendored library carries no git metadata.","treeHash":"5decbddb252053e5eaa604a98ae0ae01c37c66e9","usage":{"cachedInputTokens":622893,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":21296,"runtime":"claude","turns":20,"wallClockMs":311757}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"62491201fe455e89","findings":[],"hash":"aebe21dccb25d28111bc1e76053bf74fca4c4674c4ba3228a34fd12870327c2d","nodeId":"c4dae8c0-b8a7-4977-b42b-d60b3794611b","outcome":"completed","summary":"Review complete. The permissions audit of `src/OracleToken.sol` found no defects, and `.imd-findings.json` holds an empty findings list with seven coverage rows, all `holds`.\n\n**What I checked, per the three assigned guides**\n\n- **Access Control.** The ABI exposes exactly three mutators: approve, transfer and transferFrom. There is no role, modifier, initializer, owner, pause, blocklist, mint, burn, proxy or delegatecall. The constructor takes no arguments and hands out no power; the deployer is an ordinary holder once it returns. Each storage slot has a single guard shape: allowances are written only by their owner through approve or decremented by the approved spender, and balances are written only by the constructor and the shared internal transfer.\n- **Asymmetry.** Both mutators route through the same internal transfer, so the zero-receiver check and the balance check apply identically. The only branch is the unlimited allowance, which skips the decrement but not the balance check. Self-transfers through both paths leave the balance unchanged. No storage variable is written without being read or read without being written.\n- **Trust Gap.** With no privileged actor and no setter, there is no seam where one caller class can redirect or extract value from another.\n\n**Adversarial probes run and passed** in a scratch test, since removed: pulls by the deployer and by the token itself without allowance revert, allowance from one owner grants nothing over another, unlimited allowance is still bounded by balance, pulls from the zero address cannot mint, and supply is conserved under fuzzed mixed transfer and transferFrom sequences. The existing suite of 31 tests also passes.\n\n**Notes that are not defects.** A zero-value transferFrom with no allowance succeeds and emits a Transfer event naming the victim as sender. EIP-20 mandates this and OpenZeppelin behaves the same, so I did not report it. Tokens sent to the contract's own address are stuck, which the README documents as a deliberate trade-off against adding a privileged rescue function. The aderyn large-literal lead is stylistic and the constant evaluates to the manifest supply exactly.\n\nNo launch.json is present yet, which is expected before the manifest step. The README's expected token entry matches the constructor and supply.","treeHash":null,"usage":{"cachedInputTokens":537763,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":9355,"runtime":"claude","turns":22,"wallClockMs":141908}}],"verification":[{"checks":[{"durationMs":3743,"exitCode":0,"name":"build","output":"Compiling 26 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.51s\nCompiler run successful with warnings:\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/OracleTokenEdge.t.sol:497:5:\n    |\n497 |     function _usableSender(address candidate, address fallbackTo) internal view returns (address) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\n","passed":true},{"durationMs":19227,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 31 tests for test/OracleToken.t.sol:OracleTokenTest\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 99569, ~: 100021)\nLogs:\n  Bound result 688931659911554804060594029\n  Bound result 880381027524240692806035913\n\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 103907, ~: 104092)\nLogs:\n  Bound result 5834436666681616100168\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 125359, ~: 98202)\nLogs:\n  Bound result 11000000000000000000\n  Bound result 1000000000000000000\n\n[PASS] test_approve_overwritesPreviousAllowance() (gas: 92435)\n[PASS] test_approve_revertsForZeroSpender() (gas: 32889)\n[PASS] test_approve_setsAllowanceAndEmits() (gas: 64787)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8177)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 17455)\n[PASS] test_constructorTakesNoArguments() (gas: 474152)\n[PASS] test_contractDeployerReceivesWholeSupply() (gas: 185804)\n[PASS] test_deployScriptMintsToTheScriptCaller() (gas: 1053803)\n[PASS] test_metadata() (gas: 23706)\n[PASS] test_noMintOrAdminEntryPointExists() (gas: 645239)\n[PASS] test_noPrivilegedCallMovesOrFreezesAHolder() (gas: 442391)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 672978)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 17374)\n[PASS] test_transferFrom_exactAllowanceGoesToZero() (gas: 118083)\n[PASS] test_transferFrom_infiniteAllowanceIsNotDecreased() (gas: 129726)\n[PASS] test_transferFrom_movesAndDecreasesAllowance() (gas: 156550)\n[PASS] test_transferFrom_revertsOnInsufficientAllowance() (gas: 102007)\n[PASS] test_transferFrom_revertsOnInsufficientBalanceEvenWithAllowance() (gas: 152280)\n[PASS] test_transferFrom_revertsToZeroAddress() (gas: 88271)\n[PASS] test_transferFrom_revertsWithoutAnyAllowance() (gas: 40336)\n[PASS] test_transfer_movesBalanceAndEmits() (gas: 85062)\n[PASS] test_transfer_revertsFromEmptyAccount() (gas: 37634)\n[PASS] test_transfer_revertsOnInsufficientBalance() (gas: 106180)\n[PASS] test_transfer_revertsToZeroAddress() (gas: 37097)\n[PASS] test_transfer_toSelfKeepsBalance() (gas: 40411)\n[PASS] test_transfer_wholeBalance() (gas: 71938)\n[PASS] test_transfer_zeroValueSucceeds() (gas: 46735)\n[PASS] test_unknownSelectorAndPlainEtherAreRejected() (gas: 57986)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 70.32ms (161.09ms CPU time)\n\nRan 29 tests for test/OracleTokenEdge.t.sol:OracleTokenEdgeTest\n[PASS] testFuzz_allowanceDecreasesBySumOfPulls(uint256,uint256,uint256,uint256) (runs: 1000, μ: 226863, ~: 230184)\nLogs:\n  Bound result 7004704581485550\n  Bound result 0\n  Bound result 5262929009662393\n  Bound result 926988015485473\n\n[PASS] testFuzz_approveSetsExactly(address,address,uint256) (runs: 1000, μ: 68054, ~: 68481)\n[PASS] testFuzz_deploymentsAreIndependent(address) (runs: 1000, μ: 37958, ~: 37974)\n[PASS] testFuzz_insufficientBalanceErrorIsExact(address,uint256,uint256) (runs: 1000, μ: 105709, ~: 106420)\nLogs:\n  Bound result 465517864744376387110478562\n  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129639933\n\n[PASS] testFuzz_roundTripThroughThreeHoldersIsExact(uint256) (runs: 1000, μ: 170152, ~: 170266)\nLogs:\n  Bound result 254063808494989863010467093\n\n[PASS] testFuzz_transferIsAdditive(uint256,uint256) (runs: 1000, μ: 118574, ~: 119524)\nLogs:\n  Bound result 81316447614658609465639\n  Bound result 62082071550366554827711\n\n[PASS] test_abi_metadataIsReadableByStaticcall() (gas: 30621)\n[PASS] test_abi_shortCalldataReverts() (gas: 37243)\n[PASS] test_abi_transferAndApproveReturnOneTrueWord() (gas: 151072)\n[PASS] test_approve_fromEmptyAccountIsAllowedButUnspendable() (gas: 107806)\n[PASS] test_approve_zeroClearsAndEmits() (gas: 130173)\n[PASS] test_approve_zeroSpenderRevertsEvenForZeroValue() (gas: 37205)\n[PASS] test_events_mintTransferEmittedExactlyOnceAtConstruction() (gas: 65959)\n[PASS] test_launch_create2DeploymentMintsToTheFactory() (gas: 700877)\n[PASS] test_launch_factoryHasNoPowerAfterForwarding() (gas: 804364)\n[PASS] test_launch_flowsMoveExactlyWhatTheySay() (gas: 1098270)\n[PASS] test_transferFrom_allowanceDoesNotCrossOwners() (gas: 156662)\n[PASS] test_transferFrom_emitsNoApprovalEvent() (gas: 126347)\n[PASS] test_transferFrom_maxMinusOneIsFinite() (gas: 123398)\n[PASS] test_transferFrom_ownerNeedsSelfAllowance() (gas: 153712)\n[PASS] test_transferFrom_sameFromAndTo_consumesAllowanceOnly() (gas: 107765)\n[PASS] test_transferFrom_twoSpendersOneBalance() (gas: 276412)\n[PASS] test_transferFrom_unlimitedSurvivesWholeSupplyAndZero() (gas: 209762)\n[PASS] test_transferFrom_zeroValueWithoutAllowanceSucceeds() (gas: 74240)\n[PASS] test_transfer_fromNeverSeenAddressReportsZeroBalance() (gas: 39539)\n[PASS] test_transfer_oneWeiAndSupplyMinusOneWei() (gas: 155543)\n[PASS] test_transfer_toTokenContractIsAcceptedAndStuck() (gas: 106662)\n[PASS] test_transfer_wholeBalanceToSelfKeepsBalance() (gas: 40455)\n[PASS] test_transfer_wholeBalanceTwiceRevertsTheSecondTime() (gas: 89549)\nSuite result: ok. 29 passed; 0 failed; 0 skipped; finished in 70.50ms (380.19ms CPU time)\n\nRan 1 test for test/OracleToken.invariant.t.sol:OracleTokenInvariantTest\n[PASS]\nOracleTokenInvariantTest invariants:\n[PASS] invariant_allowancesMatchGhostRecord\n[PASS] invariant_balancesMatchGhostRecord\n[PASS] invariant_noBalanceExceedsSupply\n[PASS] invariant_sumOfBalancesEqualsTotalSupply\n[PASS] invariant_tokenHoldsNoEther\n[PASS] invariant_tokensSentToTheContractNeverLeave\n[PASS] invariant_totalSupplyIsConstant\n[PASS] invariant_zeroAddressHoldsNothing\n OracleTokenInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+----------------------------+-------+---------+----------╮\n| Contract           | Selector                   | Calls | Reverts | Discards |\n+==============================================================================+\n| OracleTokenHandler | approve                    | 1974  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | approveZeroSpender         | 2070  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transfer                   | 2016  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transferAboveBalance       | 2105  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transferFrom               | 2023  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transferFromAboveAllowance | 2090  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transferToRandom           | 2093  | 0       | 0        |\n|--------------------+----------------------------+-------+---------+----------|\n| OracleTokenHandler | transferToZeroAddress      | 2013  | 0       | 0        |\n╰--------------------+----------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 8401\n  Bound result 4\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 0\n  Bound result 2\n  Bound result 151\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 2\n  Bound result 3\n  Bound result 0\n  Bound result 3389\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 5\n  Bound result 560876072\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 147367322135221848896\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 5777\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 852\n  Bound result 3\n  Bound result 2\n  Bound result 5\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 5\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 46764156489852016080597370395736987439799639705547732731265575684\n  Bound result 0\n  Bound result 244\n  Bound result 4\n  Bound result 2\n  Bound result 0\n  Bound result 4\n  Bound result 4\n  Bound result 2552851541\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 892\n  Bound result 4\n  Bound result 5\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 7060\n  Bound result 2\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 24725046105560086338733853321989698394474978867853553639639730029752786173914\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 2\n  Bound result 3\n  Bound result 635\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 147367322135221863073\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 18\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 4\n  Bound result 7\n  Bound result 2\n  Bound result 3\n  Bound result 32\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 874\n  Bound result 4\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 680\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 1151405998\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 4\n  Bound result 3541\n  Bound result 4\n  Bound result 0\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 19.06s (19.05s CPU time)\n\nRan 3 test suites in 19.06s (19.20s CPU time): 61 tests passed, 0 failed, 0 skipped (61 total tests)\n","passed":true},{"durationMs":70,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OracleToken.approve(address,uint256)\",\"OracleToken.transfer(address,uint256)\",\"OracleToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":149,\"foundry.toml\":24,\"remappings.txt\":1,\"script/DeployOracleToken.s.sol\":28,\"src/OracleToken.sol\":150,\"src/interfaces/IERC20.sol\":22,\"test/OracleToken.invariant.t.sol\":399,\"test/OracleToken.t.sol\":379,\"test/OracleTokenEdge.t.sol\":506},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"40600fd493504ea0445b0d8020fe2992cd0bd8cfe2463522f6ea6e6cc43f59aa","verifiedTreeHash":"b1b51973d664b36e217a1283e5cd1488aa410309","verifierVersion":"0.1.0+21c4e407"},{"checks":[{"durationMs":869,"exitCode":0,"name":"build","output":"Compiling 24 files with Solc 0.8.26\nSolc 0.8.26 finished in 752.39ms\nCompiler run successful!\n","passed":true},{"durationMs":97,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 31 tests for test/OracleToken.t.sol:OracleTokenTest\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 99500, ~: 99998)\nLogs:\n  Bound result 1353387136566453096\n  Bound result 355895730001322545451279996\n\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 103664, ~: 104116)\nLogs:\n  Bound result 545285154146125291397531038\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 125232, ~: 98202)\nLogs:\n  Bound result 826129653456448901604416248\n  Bound result 906133786719769977957201404\n\n[PASS] test_approve_overwritesPreviousAllowance() (gas: 92435)\n[PASS] test_approve_revertsForZeroSpender() (gas: 32889)\n[PASS] test_approve_setsAllowanceAndEmits() (gas: 64787)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8177)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 17455)\n[PASS] test_constructorTakesNoArguments() (gas: 474152)\n[PASS] test_contractDeployerReceivesWholeSupply() (gas: 185804)\n[PASS] test_deployScriptMintsToTheScriptCaller() (gas: 1053803)\n[PASS] test_metadata() (gas: 23706)\n[PASS] test_noMintOrAdminEntryPointExists() (gas: 645239)\n[PASS] test_noPrivilegedCallMovesOrFreezesAHolder() (gas: 442391)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 672978)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 17374)\n[PASS] test_transferFrom_exactAllowanceGoesToZero() (gas: 118083)\n[PASS] test_transferFrom_infiniteAllowanceIsNotDecreased() (gas: 129726)\n[PASS] test_transferFrom_movesAndDecreasesAllowance() (gas: 156550)\n[PASS] test_transferFrom_revertsOnInsufficientAllowance() (gas: 102007)\n[PASS] test_transferFrom_revertsOnInsufficientBalanceEvenWithAllowance() (gas: 152280)\n[PASS] test_transferFrom_revertsToZeroAddress() (gas: 88271)\n[PASS] test_transferFrom_revertsWithoutAnyAllowance() (gas: 40336)\n[PASS] test_transfer_movesBalanceAndEmits() (gas: 85062)\n[PASS] test_transfer_revertsFromEmptyAccount() (gas: 37634)\n[PASS] test_transfer_revertsOnInsufficientBalance() (gas: 106180)\n[PASS] test_transfer_revertsToZeroAddress() (gas: 37097)\n[PASS] test_transfer_toSelfKeepsBalance() (gas: 40411)\n[PASS] test_transfer_wholeBalance() (gas: 71938)\n[PASS] test_transfer_zeroValueSucceeds() (gas: 46735)\n[PASS] test_unknownSelectorAndPlainEtherAreRejected() (gas: 57986)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 7.44ms (30.44ms CPU time)\n\nRan 1 test suite in 8.06ms (7.44ms 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\":[\"OracleToken.approve(address,uint256)\",\"OracleToken.transfer(address,uint256)\",\"OracleToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":149,\"foundry.toml\":24,\"launch.json\":24,\"remappings.txt\":1,\"script/DeployOracleToken.s.sol\":28,\"src/OracleToken.sol\":150,\"src/interfaces/IERC20.sol\":22,\"test/OracleToken.t.sol\":379},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"787ca1e4d395538f0053ff4b4389e1b8bcccad9356ae9f4ea5f7d994db756213","verifiedTreeHash":"9f7c06ea2375fb13f20f2ba7ea871431a1d1ee47","verifierVersion":"0.1.0+21c4e407"},{"checks":[{"durationMs":975,"exitCode":0,"name":"build","output":"Compiling 24 files with Solc 0.8.26\nSolc 0.8.26 finished in 866.35ms\nCompiler run successful!\n","passed":true},{"durationMs":109,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 31 tests for test/OracleToken.t.sol:OracleTokenTest\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 99724, ~: 100008)\nLogs:\n  Bound result 242\n  Bound result 5000000000000000000\n\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 103519, ~: 104116)\nLogs:\n  Bound result 0\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 130407, ~: 154838)\nLogs:\n  Bound result 1\n  Bound result 2079261902947838293323\n\n[PASS] test_approve_overwritesPreviousAllowance() (gas: 92435)\n[PASS] test_approve_revertsForZeroSpender() (gas: 32889)\n[PASS] test_approve_setsAllowanceAndEmits() (gas: 64787)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8177)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 17455)\n[PASS] test_constructorTakesNoArguments() (gas: 474152)\n[PASS] test_contractDeployerReceivesWholeSupply() (gas: 185804)\n[PASS] test_deployScriptMintsToTheScriptCaller() (gas: 1053803)\n[PASS] test_metadata() (gas: 23706)\n[PASS] test_noMintOrAdminEntryPointExists() (gas: 645239)\n[PASS] test_noPrivilegedCallMovesOrFreezesAHolder() (gas: 442391)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 672978)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 17374)\n[PASS] test_transferFrom_exactAllowanceGoesToZero() (gas: 118083)\n[PASS] test_transferFrom_infiniteAllowanceIsNotDecreased() (gas: 129726)\n[PASS] test_transferFrom_movesAndDecreasesAllowance() (gas: 156550)\n[PASS] test_transferFrom_revertsOnInsufficientAllowance() (gas: 102007)\n[PASS] test_transferFrom_revertsOnInsufficientBalanceEvenWithAllowance() (gas: 152280)\n[PASS] test_transferFrom_revertsToZeroAddress() (gas: 88271)\n[PASS] test_transferFrom_revertsWithoutAnyAllowance() (gas: 40336)\n[PASS] test_transfer_movesBalanceAndEmits() (gas: 85062)\n[PASS] test_transfer_revertsFromEmptyAccount() (gas: 37634)\n[PASS] test_transfer_revertsOnInsufficientBalance() (gas: 106180)\n[PASS] test_transfer_revertsToZeroAddress() (gas: 37097)\n[PASS] test_transfer_toSelfKeepsBalance() (gas: 40411)\n[PASS] test_transfer_wholeBalance() (gas: 71938)\n[PASS] test_transfer_zeroValueSucceeds() (gas: 46735)\n[PASS] test_unknownSelectorAndPlainEtherAreRejected() (gas: 57986)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 7.29ms (26.66ms CPU time)\n\nRan 1 test suite in 7.77ms (7.29ms CPU time): 31 tests passed, 0 failed, 0 skipped (31 total tests)\n","passed":true},{"durationMs":57,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OracleToken.approve(address,uint256)\",\"OracleToken.transfer(address,uint256)\",\"OracleToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":149,\"foundry.toml\":24,\"remappings.txt\":1,\"script/DeployOracleToken.s.sol\":28,\"src/OracleToken.sol\":150,\"src/interfaces/IERC20.sol\":22,\"test/OracleToken.t.sol\":379},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":362,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":195,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/OracleToken.sol:37: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"99e67e54f741862978b60895c7a19a6b274415b10a57cfe44374a414ef7f366b","verifiedTreeHash":"5decbddb252053e5eaa604a98ae0ae01c37c66e9","verifierVersion":"0.1.0+21c4e407"}]}