{"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":"205a6bd0-9a1a-4044-b7cc-50e19970ce34","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"f91de0095e03aab1052cfcbec6ddd1d0f8cc1b5cc3eb46a75489127774b63ef6","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":"7b023f861fdf9e1f0c0190899dc495b116674a2b5ed52d082325075d88ced8e9","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":"0a3152bb3885f450e767ed7b9aed52b33c8c61d8dbcedf7954f29c811c1a7e51","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":"d7b847424571e3f8a3b046aa199e52b6070ebe34f502f500a03b580fa9f90035","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":"e57638727deb54e038e72039edfadf9a798d4d1210ad620a00463d31009eed9b","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":"34ffbc610f84cea65ea474ae2813b2cb868ca03063212aa8cb61fb76ebfc42d9","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"6e3e328aa196f6965a2821b098b101e9ff09eef55cdaafaec1d6ea18007b96f6","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"6e3e328aa196f6965a2821b098b101e9ff09eef55cdaafaec1d6ea18007b96f6","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"0e308bfece35fd92189344edc13ce952cfbb7f0a573045cff5eef1241b391426","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"24abbd24591e194d2e7f28658d8ad68a11c84e12d01e7883501398526f170a55","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: Spectra (SPECTRA).\nToken name: Spectra\nToken symbol: SPECTRA\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"dcd308a7226f048fad69773a2316e1b3cbd9cfb320b256bee6bd4a7265e98eb2","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"205a6bd0-9a1a-4044-b7cc-50e19970ce34","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1171-spectra"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51154","feedbackHash":"39b39219a31aacd792f0e7f53610e08f5d2e536c8a3c23fc7e33ad2f326d1209","nodeKey":"audit_economics","submissionHash":"f91de0095e03aab1052cfcbec6ddd1d0f8cc1b5cc3eb46a75489127774b63ef6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52222","feedbackHash":"34b74cd9b9320b5ac2c36d9891badb888cb2b49a93ca01904e013ad12373b10c","nodeKey":"audit_flow","submissionHash":"7b023f861fdf9e1f0c0190899dc495b116674a2b5ed52d082325075d88ced8e9","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51878","feedbackHash":"cfe53c046473e9c1e780ce7cb41e053a8fd58c1def5273abdf176839169b9fc6","nodeKey":"audit_judge","submissionHash":"0a3152bb3885f450e767ed7b9aed52b33c8c61d8dbcedf7954f29c811c1a7e51","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50961","feedbackHash":"5d9485c07806fc3514b70ecc4851501539c1b233343c07b7d60797f754552368","nodeKey":"audit_math","submissionHash":"d7b847424571e3f8a3b046aa199e52b6070ebe34f502f500a03b580fa9f90035","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52210","feedbackHash":"e6e2dc1c040d05f9c2cbf829dcd358c08f8d782d13fe980cdd5ed246f223be23","nodeKey":"audit_permissions","submissionHash":"e57638727deb54e038e72039edfadf9a798d4d1210ad620a00463d31009eed9b","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51146","feedbackHash":"1382aedf6b619e77a930790d306011e131bdc89c5fbab1fd81ad865ce1b0a236","nodeKey":"build_contract_project","submissionHash":"34ffbc610f84cea65ea474ae2813b2cb868ca03063212aa8cb61fb76ebfc42d9","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52179","feedbackHash":"509f5a4312627c37e10cc3a334152153cc523675f79ae26969ca18d91ff7b5fb","nodeKey":"manifest","submissionHash":"0e308bfece35fd92189344edc13ce952cfbb7f0a573045cff5eef1241b391426","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51429","feedbackHash":"794c9a88f1085e1a62ca5b228b202e17cd60b89911095b3fc7d0cec2dd1b5b8d","nodeKey":"write_foundry_tests","submissionHash":"24abbd24591e194d2e7f28658d8ad68a11c84e12d01e7883501398526f170a55","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"3e5d6babc5c9bc2c1dc8e3a72e0adc64a299552753c42c679e5f939b597ab5bf","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2a6239e0c1b8c774","findings":[{"citation":"resolved","description":"Merged from audit_permissions (f53362997e5d) and audit_flow (437ed1134e79), same root cause. _transfer (line 103) rejects only `to == address(0)`, _burn (line 130) rejects nothing, and _spendAllowance (line 123) lets amount 0 through for any owner because `0 < 0` is false. Nothing in the contract rejects `from == address(0)`. Since balanceOf[address(0)] is always 0 (transfers to the zero address revert) and allowance[address(0)][x] is 0, a non-zero amount reverts with InsufficientAllowance, so balances and totalSupply can never change through this path; the defect is confined to events. Any unprivileged caller can make the token emit Transfer(address(0), X, 0), which is the exact event shape explorers, indexers and supply trackers classify as a mint, and Approval(address(0), caller, 0), and via burnFrom(address(0), 0) a Transfer(address(0), address(0), 0). The contract's NatSpec at line 50 ('Nothing can mint afterwards') and the README promise no mint-shaped activity after the constructor; OpenZeppelin's ERC20 rejects both paths with ERC20InvalidSender(address(0)). Severity low: no funds, allowance or supply are affected, only off-chain event consumers. Minimal fix preserving the agreed design: add `if (from == address(0)) revert ZeroAddress();` at the top of _transfer and of _burn (or revert in _spendAllowance when owner == address(0)). The existing test suite passes with that change; test_RevertWhen_transferFromZeroAddressSource in test/SpectraToken.edges.t.sol would then revert with ZeroAddress instead of InsufficientBalance and needs its expected error updated.","line":103,"path":"src/SpectraToken.sol","reproduction":"State: SpectraToken freshly deployed by any deployer; attacker = 0xBEEF holds nothing and has no allowance from anyone. Call 1: vm.prank(attacker); token.transferFrom(address(0), attacker, 0). Expected (ERC-20 convention, OpenZeppelin behaviour and the contract's own 'Nothing can mint afterwards'): revert. Actual: returns true and emits Approval(address(0), 0xBEEF, 0) then Transfer(address(0), 0xBEEF, 0); totalSupply stays 1000000000000000000000000000 and balanceOf(0xBEEF) stays 0. Call 2: vm.prank(attacker); token.burnFrom(address(0), 0). Expected: revert. Actual: succeeds and emits Transfer(address(0), address(0), 0), supply unchanged. Control: token.transferFrom(address(0), attacker, 1) reverts with InsufficientAllowance(address(0), 0xBEEF, 0, 1), confirming no balance impact. Reproduced in test/scratch/Review.t.sol (test_zeroSenderTransferFromEmitsMintShapedEvent, test_zeroSenderBurnFromEmitsEvent, test_zeroSenderTransferFromNonZeroReverts) with vm.expectEmit on each event; all pass against the current code, i.e. the events are emitted.","severity":"low","snippet":"        if (to == address(0)) revert ZeroAddress();","title":"transferFrom and burnFrom accept address(0) as the source, so any caller can emit mint-shaped Transfer(address(0), to, 0) and Approval(address(0), caller, 0) events after deployment"},{"citation":"resolved","description":"Merged from audit_flow (578b06637626) and audit_math (2823a887cc27), same root cause. With amount == 0 and allowance[from][msg.sender] == 0 the guard at line 123 (`current < amount`, i.e. 0 < 0) passes and the balance check at line 105 (balanceOf[from] >= 0) passes for every holder, so transferFrom(holder, to, 0) succeeds for any caller. Zero-value transfers succeeding and firing Transfer is what ERC-20 requires and what OpenZeppelin v5 does, so that part is spec-conformant; what differs from the current OpenZeppelin reference is that line 127 additionally emits Approval(holder, caller, 0) on the spend (OpenZeppelin v5 spends allowance with emitEvent = false). Consequence: wallets, indexers and alerting that key on Approval or Transfer events can show an unsolicited approval of an arbitrary address, or zero-value activity, in any holder's history (the address-poisoning primitive). No balance, allowance or supply changes, so this is informational and not a defect in the agreed design. If the author wants to match OpenZeppelin v5, drop the emit at line 127; rejecting zero-value spends without allowance would deviate from ERC-20 and from what routers and the Uniswap v4 PoolManager expect, so it is not recommended.","line":127,"path":"src/SpectraToken.sol","reproduction":"State: deployer transfers 100e18 to alice; allowance(alice, attacker) == 0. Call: vm.prank(attacker); token.transferFrom(alice, bob, 0). Expected (OpenZeppelin v5 semantics): succeeds and emits only Transfer(alice, bob, 0). Actual: returns true and emits Approval(alice, attacker, 0) followed by Transfer(alice, bob, 0); balanceOf(alice) stays 100e18, allowance stays 0. Reproduced in test/scratch/Review.t.sol test_zeroValueSpendEmitsApprovalForVictim with vm.expectEmit(true,true,true,true) on both events; passes against the current code. Control: with an unlimited allowance no Approval is emitted on spend (test_maxAllowanceNotDecrementedAndNoApprovalEvent records exactly one log).","severity":"info","snippet":"        emit Approval(owner, spender, current - amount);","title":"_spendAllowance emits Approval on every non-unlimited spend, so a zero-value transferFrom or burnFrom with no allowance lets any caller emit Approval(holder, caller, 0) and Transfer(holder, to, 0) for"},{"citation":"resolved","description":"Merged from audit_flow (0f16610ba2d7), audit_economics (59682d734ce7) and audit_math (5dcb588f18ea), same root cause. _approve sets allowance[owner][spender] = amount without reference to the prior value, so when a holder lowers a live allowance from X to Y the spender can take X before the new approve lands and Y after it. This is the allowance race inherent to ERC-20's approve semantics; OpenZeppelin v5 behaves identically and also ships no increase/decrease helpers. Each individual call behaves per spec, the launch flows (factory to distributor, pool seed through the PoolManager, claims, swaps) never depend on lowering a live allowance, and the README already documents 'Holders manage their own allowances' as the trust assumption. Recorded as a trust assumption on spenders, not a defect; no change is required to ship. Optional mitigations that keep the ERC-20 surface: add increaseAllowance/decreaseAllowance, or document the approve-to-zero-first pattern.","line":116,"path":"src/SpectraToken.sol","reproduction":"State: alice holds 150e18; alice.approve(bob, 100e18). Alice then sends approve(bob, 50e18) intending to lower bob's limit. Sequence: (1) bob front-runs: transferFrom(alice, bob, 100e18) succeeds, allowance 100e18 -> 0; (2) alice's approve(bob, 50e18) lands; (3) bob: transferFrom(alice, bob, 50e18) succeeds. Expected by alice: bob moves at most 100e18 (or 50e18). Actual: balanceOf(bob) == 150e18, balanceOf(alice) == 0. Reproduced in test/scratch/Review.t.sol test_approveOverwriteRace; passes against the current code.","severity":"info","snippet":"        allowance[owner][spender] = amount;","title":"approve overwrites the allowance unconditionally, so a spender who front-runs a reduction can spend the old and the new allowance (standard ERC-20 race; no increaseAllowance/decreaseAllowance or permi"}],"hash":"0a3152bb3885f450e767ed7b9aed52b33c8c61d8dbcedf7954f29c811c1a7e51","nodeId":"a59220df-7a3d-4aa5-b3f5-64fabc2356bf","outcome":"completed","summary":"The findings file is written and validated. Every snippet matches its source line, and git status shows only the untracked findings file plus the ignored scratch directory. Nothing else remains to do.\n\n**Outcome:** the Spectra token has no fund-affecting defect. The findings file holds one low and two informational findings, all reproduced, plus a coverage record for all five entry points and two invariants.\n\n**What the specialists reported and how I settled it:**\n\n- **Merged into finding 1 (low):** both the permissions and flow specialists found that `transferFrom` and `burnFrom` accept the zero address as the source. I reproduced it: any caller can emit a mint-shaped Transfer from the zero address with value 0, and an Approval from the zero address. Balances and supply never change because a non-zero amount reverts on allowance. Event integrity only, so low.\n- **Merged into finding 2 (info):** the flow and math specialists both noted that spending an allowance emits an Approval event, so a zero-value transferFrom with no allowance emits Approval and Transfer naming any holder. Reproduced. Zero-value transfers are required by ERC-20, and only the extra Approval differs from OpenZeppelin v5. Not a defect.\n- **Merged into finding 3 (info):** three specialists reported the approve overwrite race. Reproduced, but it is inherent to ERC-20 and documented in the README as a holder responsibility. Recorded as a trust assumption.\n\n**My own pass found nothing further.** The contract makes no external calls, has no owner or mint path, arithmetic is bounded by the fixed supply, self-transfers are correct, unlimited allowances are not decremented, and ETH is rejected. The manifest matches the argument-free constructor, the exact supply and decimals. Creation and runtime bytecode are far below the size limits and contain no delegatecall, callcode or selfdestruct. The existing 94 tests and my 10 scratch tests all pass.\n\nNo proof files were attached since nothing reached high or critical severity.","treeHash":null,"usage":{"cachedInputTokens":419486,"inputTokens":194,"model":"claude-fable-5-1","outputTokens":13068,"runtime":"claude","turns":21,"wallClockMs":194703}},{"artifacts":[],"attempt":1,"bundleHash":"2bd095d0e670d3e5efa1dbc23ace6dfb1bfe4e67398496fb7ed4fa423159ebfd","device":"02f22d6f13810ca8","findings":[],"hash":"0e308bfece35fd92189344edc13ce952cfbb7f0a573045cff5eef1241b391426","nodeId":"f92b972a-85e7-4260-8b80-3cd7e9c12573","outcome":"completed","summary":"Done. The manifest is written and verified; launch.json is the only changed file.\n\n**What the accepted tree contains**\n- One contract, SpectraToken, with a no-argument constructor that mints the whole supply to msg.sender once.\n- No application contracts. The deployment script and unit tests are not launch contracts.\n- The compiled ABI confirms the constructor takes zero inputs, so the token's constructorArgs are an empty list.\n\n**What launch.json says**\n- kind is custom_token, with token contract SpectraToken, name Spectra, symbol SPECTRA, decimals 18.\n- totalSupply is the constructor's mint in minor units, 1,000,000,000 times 10^18.\n- contracts is empty.\n- pool is IMD as paired currency, fee 12500, tick spacing 60, and the one-to-one initial price from the reference.\n- economics is the requester's object copied verbatim.\n- notes describe only SpectraToken and its launch-flow behaviour, well under the character limit.\n\n**Checks run**\n- A script confirmed the manifest uses only the schema's keys, strings for every uint256 and address, numbers for fee, tickSpacing and decimals, and a lowercase paired address.\n- `forge build` compiled cleanly and `forge test` passed all 33 existing tests.\n- Git status shows launch.json as the only new or changed path.","treeHash":"9d271c3ebd8369d41565eb6601338793b0b69ff5","usage":{"cachedInputTokens":182852,"inputTokens":130,"model":"claude-fable-5-1","outputTokens":3053,"runtime":"claude","turns":8,"wallClockMs":66139}},{"artifacts":[],"attempt":1,"bundleHash":"187c99f05b27906b614616ab35add53671c38093c6fa4e35704529c922e615da","device":"3987a51ff810f3b9","findings":[],"hash":"24abbd24591e194d2e7f28658d8ad68a11c84e12d01e7883501398526f170a55","nodeId":"c673fdc4-0031-434b-aa6e-f0b4cdc5d9f0","outcome":"completed","summary":"The suite is complete and green. `forge build` succeeds and `forge test` runs 104 tests with 0 failures, including the scratch probe that is discarded before submission.\n\n**What I added**, all under `test/` and building on the existing 33-test suite rather than rewriting it:\n\n- `test/SpectraToken.invariant.t.sol`: a handler that drives five actors through transfer, approve, transferFrom, burn and burnFrom with bounded inputs, plus eight failure-path handlers that predict the exact revert error and assert nothing changed. Invariants check conservation (actor balances sum to supply), supply never grows and equals initial minus burns, every balance and every allowance matches a ghost ledger, and the zero address never holds tokens. It runs with fail-on-revert on, so any unpredicted revert fails the run. A second open-world suite fuzzes the token directly with arbitrary recipients and keeps the supply and zero-address properties.\n- `test/SpectraToken.edges.t.sol`: 52 tests on inputs the base suite skipped. Examples: the allowance one below unlimited is decremented, unlimited allowance emits no Approval and survives draining the owner, zero-amount transferFrom and burnFrom succeed without an allowance, a reverted transferFrom or burnFrom consumes no allowance, the zero address can never be a token source, burning the whole supply leaves zero, unknown selectors and ether both revert, and standard ERC-20 four-byte selectors answer correctly as raw calldata. Oracle-style fuzz tests cover transfer, burn and burnFrom across the full input space.\n- `test/SpectraToken.launch.t.sol`: the factory flow as the launch performs it. The token deploys through raw CREATE2 from a factory contract, the swarm share and pool share and remainder leave whole and sum to the supply exactly, a pool manager pulls the seed via allowance and pays traders both ways, and the factory cannot move or freeze a holder afterwards.\n\n**Defects found:** none. I read the implementation adversarially and the handler-driven runs confirmed it. The unchecked arithmetic is bounded by the fixed supply, self-transfer reads the updated balance correctly, allowance is spent before balance is checked and the ordering is consistent, and no privileged path exists. I wrote `.imd-findings.json` with an empty findings list to state that explicitly.\n\nNo configuration, library, or source files were touched. Only the three new test files are new in the working tree.","treeHash":"9a2b1a3cb2073f0c12aeba88a23c526262c3aa7f","usage":{"cachedInputTokens":1045270,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":39593,"runtime":"claude","turns":27,"wallClockMs":583582}},{"artifacts":[],"attempt":1,"bundleHash":"f4066eb14276dd3d59548af39d17ab417f7a8de89bdc0716b92caa226735490a","device":"824e6de6196c686f","findings":[],"hash":"34ffbc610f84cea65ea474ae2813b2cb868ca03063212aa8cb61fb76ebfc42d9","nodeId":"7fa23b7d-6137-4f16-ba17-8d2cf921b2f0","outcome":"completed","summary":"The Spectra token project is complete and verified.\n\n**What was built**, a Foundry project at the repository root:\n\n- `src/SpectraToken.sol` is a self-contained fixed-supply ERC-20 named Spectra, symbol SPECTRA, 18 decimals. The constructor mints 1,000,000,000 × 10^18 once to the deployer, which is the launch factory. It has no owner, no mint, no pause, no blacklist, no fee and no exemptions, so every launch flow moves exactly what it says. Holders can burn their own tokens, and burnFrom only works against a granted allowance. It inherits nothing and calls no library, so the bytecode has no link placeholders, no DELEGATECALL, CALLCODE or SELFDESTRUCT.\n- `test/SpectraToken.t.sol` holds 33 tests: metadata and supply, success and revert cases for transfer, approve, transferFrom, burn and burnFrom, a sweep of admin-style selectors from both a stranger and the deployer confirming none exists, an opcode scan mirroring the protected harness, ETH rejection, and three fuzz tests for supply conservation and allowance handling.\n- `script/DeploySpectra.s.sol` is an argument-free deploy script whose deploy function the tests call directly. The launch itself does not use it.\n- `foundry.toml` pins solc 0.8.26 with bytecode_hash set to none, optimizer on, ffi off. forge-std v1.9.6 is vendored under lib/ as plain files with its git metadata, tests and scripts stripped, and there is no submodule.\n- `README.md` documents behaviour, errors, deployment parameters, the launch distribution, the empty \"After launch\" section, operational responsibilities and assumptions.\n\n**Check results**\n\n| Check | Result |\n| --- | --- |\n| forge build | compiles cleanly |\n| forge test | 33 passed, 0 failed |\n| forge fmt --check | clean, exit 0 |\n\nTests read no environment variables and do not depend on the caller address. No launch.json was written. The working tree contains only the project files plus ignored out/ and cache/ build output, and test/scratch is empty. Nothing was committed, since the brief did not ask for a commit.","treeHash":"5873fab35f311ec50cf838bd8fb81cee8cdc5171","usage":{"cachedInputTokens":418828,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":17271,"runtime":"claude","turns":19,"wallClockMs":207119}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"357c46e3781993d4","findings":[{"citation":"resolved","description":"Execution Trace / First Principles (sentinel bypass). `_transfer` validates only `to`; neither `_transfer` nor `_burn` rejects `from == address(0)`. `transferFrom(address(0), to, 0)` and `burnFrom(address(0), 0)` are reachable by any caller because `allowance[address(0)][caller]` is 0 and `0 >= 0` passes the `_spendAllowance` check at line 123, and `balanceOf[address(0)]` is 0 and `0 >= 0` passes the balance check at line 105 / line 132. The calls succeed (transferFrom returns true), change no balance and no supply, but emit `Transfer(address(0), to, 0)` (the exact event shape explorers and indexers classify as a mint) and `Transfer(address(0), address(0), 0)`, plus `Approval(address(0), caller, 0)`. The contract's NatSpec and README state that nothing can mint after deployment; the reference OpenZeppelin implementation rejects both paths with `ERC20InvalidSender(address(0))` / `ERC20InvalidApprover(address(0))`. Impact is confined to event-level spoofing of off-chain consumers (zero-value mint entries attributed to arbitrary recipients, Approval entries with the zero address as owner); on-chain accounting is untouched, so severity is low. Minimal fix that preserves behaviour: `if (from == address(0)) revert ZeroAddress();` at the top of `_transfer` and `_burn` (or in `_spendAllowance` on `owner`).","line":103,"path":"src/SpectraToken.sol","reproduction":"State: token freshly deployed, attacker holds nothing and has no allowance from anyone. Call 1: vm.prank(attacker); token.transferFrom(address(0), bob, 0). Expected (per README 'Nothing can mint afterwards' and per OpenZeppelin): revert. Actual: returns true and emits Approval(address(0), attacker, 0) then Transfer(address(0), bob, 0); totalSupply unchanged at 1e27. Call 2: vm.prank(attacker); token.burnFrom(address(0), 0). Expected: revert. Actual: succeeds and emits Transfer(address(0), address(0), 0). Verified with a scratch Foundry test using vm.expectEmit on both events.","severity":"low","snippet":"        if (to == address(0)) revert ZeroAddress();","title":"transferFrom/burnFrom accept address(0) as `from`, so anyone can emit mint-shaped Transfer(address(0), to, 0) events after launch"},{"citation":"resolved","description":"Execution Trace (hidden event side effect). `_spendAllowance` emits `Approval(owner, spender, current - amount)` on every non-max spend, including a spend of 0 against a 0 allowance. Because `transferFrom(victim, anyone, 0)` and `burnFrom(victim, 0)` pass both the allowance check (0 >= 0) and the balance check (balanceOf[victim] >= 0) for every `victim`, any unprivileged address can make the token emit `Approval(victim, attacker, 0)` for any holder. Zero-value transferFrom being permitted is standard ERC-20 behaviour (OpenZeppelin allows it); what differs from the current reference is the Approval emission on spend, which OpenZeppelin v5 removed (`_approve(..., emitEvent=false)`). Consequence is limited to misleading event logs for wallets, indexers and alerting that key on Approval events (an unsolicited 'approval' of the attacker appears in the victim's history). No balance, allowance or supply changes, so informational. Fix option that preserves the semantics the README documents: drop the emission in `_spendAllowance`, matching OpenZeppelin v5; optionally also reject `amount == 0` spends with zero allowance, though that is not standard.","line":127,"path":"src/SpectraToken.sol","reproduction":"State: alice holds any balance (or none); attacker has allowance[alice][attacker] == 0. Call: vm.prank(attacker); token.transferFrom(alice, bob, 0). Expected (OpenZeppelin v5 semantics): succeeds and emits only Transfer(alice, bob, 0). Actual: succeeds and additionally emits Approval(alice, attacker, 0). Verified with vm.expectEmit(true,true,true,true); emit Approval(alice, attacker, 0) in a scratch test.","severity":"info","snippet":"        emit Approval(owner, spender, current - amount);","title":"Allowance spend emits Approval, so any caller can emit Approval(victim, caller, 0) via a zero-value transferFrom with no allowance"},{"citation":"resolved","description":"Execution Trace (approval residuals, operation interleaving). `approve` unconditionally overwrites the allowance, so lowering an allowance from X to Y is racy: a spender who sees the pending approve(Y) can front-run with transferFrom(X) and then spend Y after, taking X+Y. This is the well-known ERC-20 approve race inherent to the standard, and OpenZeppelin v5 has the same property; it is reported for completeness because the README tells holders to 'approve only what is needed' and the contract offers no atomic increase/decrease path and no permit. The README 'Holders manage their own allowances' already documents the trust assumption. If the author wants to close it without changing the ERC-20 surface, add `increaseAllowance`/`decreaseAllowance` (as OpenZeppelin v4 did) or document the approve-to-zero-first pattern. Not a deviation from the agreed design; informational.","line":68,"path":"src/SpectraToken.sol","reproduction":"State: alice holds 150e18, allowance[alice][spender] == 100e18. Alice broadcasts approve(spender, 50e18) intending to reduce. Sequence: (1) spender front-runs: transferFrom(alice, spender, 100e18) succeeds; (2) alice's approve(spender, 50e18) lands; (3) spender: transferFrom(alice, spender, 50e18) succeeds. Expected by alice: spender can take at most 100e18 (or 50e18). Actual: spender holds 150e18, alice 0. Verified in a scratch test.","severity":"info","snippet":"    function approve(address spender, uint256 amount) external returns (bool) {\n        _approve(msg.sender, spender, amount);\n        return true;\n    }","title":"approve() overwrite race lets a spender consume old plus new allowance; no increase/decreaseAllowance alternative is offered"}],"hash":"7b023f861fdf9e1f0c0190899dc495b116674a2b5ed52d082325075d88ced8e9","nodeId":"658232cf-9493-4a4f-9794-895a5aff8fc5","outcome":"completed","summary":"The findings file is in place and intentionally excluded from git by the harness. The scratch tests are removed and the tree is otherwise unchanged. The review is complete.\n\n**Outcome.** The Spectra token is a sound, minimal ERC-20. No critical, high or medium defect was found in the Execution Trace, Periphery or First Principles areas. All five entry points were traced in full. Three low-impact items are recorded in `.imd-findings.json`, each with a concrete call sequence that I confirmed in Foundry before reporting.\n\n**Findings**\n- **Low.** `transferFrom(address(0), to, 0)` and `burnFrom(address(0), 0)` succeed for any caller because the balance and allowance checks pass on zero. They emit a mint-shaped `Transfer(address(0), to, 0)` event after launch, which contradicts the documented \"nothing can mint\" guarantee and differs from OpenZeppelin, which rejects a zero sender. No balance or supply changes. Fix is a one-line zero-sender revert in the internal transfer and burn.\n- **Info.** Allowance spends emit an Approval event, so any caller can make the token emit `Approval(victim, caller, 0)` through a zero-value `transferFrom`. OpenZeppelin v5 no longer emits on spend.\n- **Info.** The standard ERC-20 approve overwrite race applies, with no increase or decrease allowance helper. Reported for completeness since the README leans on holders managing allowances.\n\n**What held.** Exact-amount transfers with a 32-byte true return value, zero-address recipient and spender guards, max-allowance sentinel, burn arithmetic, the constructor minting exactly one billion tokens to msg.sender, and the absence of any admin, fallback or forbidden opcode. A stateful fuzz run confirmed the sum of balances always equals total supply. The vendored forge-std matches upstream v1.9.6 exactly once formatting is ignored and is committed as plain files, not a submodule.\n\n**Coverage.** The record has eleven rows: the five ABI entry points, the constructor, three invariants, the forge-std periphery and the deploy script. Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":748264,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":20137,"runtime":"claude","turns":29,"wallClockMs":331868}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"d68ba89c0b30801c","findings":[{"citation":"resolved","description":"Boundary (zero input) check from the Boundary guide. With amount == 0 and allowance[from][msg.sender] == 0 the guard `current < amount` is `0 < 0`, so it passes; `_transfer` then accepts amount 0 and emits `Transfer(from, to, 0)`, and `_spendAllowance` emits `Approval(from, msg.sender, 0)`. No balance moves and no funds are at risk. This is exactly what ERC-20 requires (zero-value transfers MUST fire Transfer) and matches OpenZeppelin v5, so it is not a code defect; it is reported because it lets any third party emit a Transfer event naming any holder as sender, the primitive behind zero-value address-poisoning scams that explorers and wallets display as the holder's activity. Documented so the author can decide whether to keep spec-conformant behaviour (recommended) or require `from == msg.sender || allowance > 0` for amount 0, which would deviate from ERC-20 and from what Uniswap v4 / routers expect.","line":123,"path":"src/SpectraToken.sol","reproduction":"State: deployer transfers 100e18 to victim; allowance(victim, attacker) == 0. Call: attacker calls transferFrom(victim, bob, 0). Expected (strict reading): revert for lack of allowance. Actual: returns true, emits Approval(victim, attacker, 0) and Transfer(victim, bob, 0); balanceOf(victim) stays 100e18. Verified in test/scratch/MathAudit.t.sol test_zeroValueTransferFromWithoutAllowanceEmitsEvent. Likewise burnFrom(address(0), 0) from any caller succeeds and emits Transfer(0x0, 0x0, 0) with totalSupply unchanged.","severity":"info","snippet":"        if (current < amount) revert InsufficientAllowance(owner, spender, current, amount);","title":"Zero-value transferFrom with no allowance emits Transfer/Approval events from any account (address-poisoning surface)"},{"citation":"resolved","description":"Boundary (overwrite) note. `approve` sets the allowance to the new value without reference to the old one, so a spender who sees a pending approve that lowers its allowance can spend the old amount first and then the new one. This is the well-known ERC-20 approve race, present in every spec-conformant token including OpenZeppelin v5 (which also dropped increaseAllowance/decreaseAllowance). The README already tells holders to manage allowances carefully. It is a trust assumption on spenders, not a defect in the token's arithmetic; recorded so the author can decide whether to document it or add increase/decrease helpers.","line":116,"path":"src/SpectraToken.sol","reproduction":"State: owner holds 150e18 and has approved spender for 100e18. Owner sends approve(spender, 50e18) intending to reduce. Spender front-runs with transferFrom(owner, spender, 100e18) (allowance 100 -> 0), the owner's approve then sets allowance to 50e18, spender calls transferFrom(owner, spender, 50e18). Expected by the owner: at most 50e18 spendable after the reduction. Actual: 150e18 moved, owner balance 0. Each individual call behaves per spec.","severity":"info","snippet":"        allowance[owner][spender] = amount;","title":"approve overwrites unconditionally: the standard ERC-20 allowance front-running race is present, with no increase/decrease helpers"}],"hash":"d7b847424571e3f8a3b046aa199e52b6070ebe34f502f500a03b580fa9f90035","nodeId":"6b99ed57-220a-445c-96f7-b3130dbd5263","outcome":"completed","summary":"The review is complete. The findings file is written, the snippets match the source lines, and `git status` shows no tracked file changed (the findings file is untracked, and `test/scratch/` is gitignored).\n\n**Outcome: no arithmetic defect found in the Spectra token.** The Math Precision, Boundary and Numerical Gap guides were applied in full to every entry point, and the code holds at every edge I could construct. Two spec-conformant ERC-20 properties are recorded at info severity so the author can decide whether to document them.\n\nWhat I verified, with scratch tests under `test/scratch/MathAudit.t.sol` (11 tests, fuzz at 2000 runs, all passing):\n\n- **Supply constant** evaluates to exactly 1e27. The aderyn \"large numeric literal\" lead is not a defect. The 10%, 88% and 2% launch splits divide with zero remainder.\n- **Unchecked blocks** are all guarded. Each subtraction is preceded by a `fromBalance < amount` or `current < amount` revert, and the `balanceOf[to] += amount` addition cannot overflow because the sum of balances equals totalSupply, which never exceeds 1e27.\n- **Supply invariant** `totalSupply == sum(balances)` held across fuzzed mixed sequences of transfer, transferFrom, burn, burnFrom and self-transfer, including burning the whole supply down to zero.\n- **Allowance sentinel** behaves correctly at max, max minus one and zero, and a max allowance is still bounded by the owner's balance.\n- **Self-transfers** through both transfer and transferFrom leave the balance unchanged, because the destination addition reads the already-decremented slot.\n- **Launch flows** move exactly the stated amount. There is no fee, scaling or rounding anywhere, and transfer returns true so the Uniswap v4 currency library and the protected harness accept it.\n\nFindings written (both info):\n\n1. Zero-value `transferFrom` with no allowance succeeds and emits Transfer and Approval events naming any holder as sender. This is required by ERC-20 and matches OpenZeppelin, but it is the primitive behind address-poisoning displays.\n2. `approve` overwrites unconditionally, so the standard allowance front-running race applies, and no increase/decrease helpers exist. The README already flags allowance management as the holder's responsibility.\n\nCoverage rows answer all five listed entry points plus three invariants. Nothing in my area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":486966,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":13203,"runtime":"claude","turns":17,"wallClockMs":179104}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dff6c0d3de4aa913","findings":[{"citation":"resolved","description":"Asymmetry finding (zero-address branch): _transfer rejects to == address(0) and _approve rejects spender == address(0), but neither _transfer nor _burn rejects from == address(0), and _spendAllowance lets an amount of 0 through for any owner because `0 < 0` is false (line 123). The ERC-20 convention, and the contract's own NatSpec ('Nothing can mint afterwards', line 50), is that a Transfer whose `from` is address(0) is a mint and one whose `to` is address(0) is a burn. After deployment any unprivileged caller can therefore make the contract emit Transfer(address(0), X, 0) via transferFrom(address(0), X, 0), plus Approval(address(0), caller, 0) from line 127, and Transfer(address(0), address(0), 0) via burnFrom(address(0), 0). Balances and totalSupply are untouched (a non-zero amount from address(0) reverts with InsufficientAllowance because allowance[0][caller] is 0, and balanceOf[0] is always 0 since transfers to 0 revert), so this is an event-integrity defect only: indexers, explorers and supply trackers that reconstruct mints/burns from Transfer events see spurious mint and burn records attributed to the token after launch, and a holder can be shown a spurious Approval granted by the zero address. OpenZeppelin's ERC20 rejects this path with ERC20InvalidSender. Minimal fix that preserves behaviour: add `if (from == address(0)) revert ZeroAddress();` at the top of _transfer (line 102) and _burn (line 130); alternatively, revert in _spendAllowance when owner == address(0). The project's existing tests all still pass with that change.","line":103,"path":"src/SpectraToken.sol","reproduction":"State: freshly deployed SpectraToken (any deployer). Call from an arbitrary unprivileged account A = 0xBEEF: token.transferFrom(address(0), A, 0). Expected (ERC-20 convention / OZ behaviour, and the contract's 'nothing can mint afterwards' claim): revert, no Transfer from address(0) after the constructor. Actual: returns true and emits Approval(address(0), A, 0) and Transfer(address(0), A, 0); totalSupply stays 1_000_000_000e18 and balanceOf(A) stays 0. Likewise token.burnFrom(address(0), 0) from A emits Transfer(address(0), address(0), 0). Verified with a Foundry test using vm.expectEmit for both events (test/scratch/ZeroSender.t.sol, passes against current code showing the events are emitted). Non-zero amount: token.transferFrom(address(0), A, 1) reverts with InsufficientAllowance(address(0), A, 0, 1), confirming no balance impact.","severity":"low","snippet":"        if (to == address(0)) revert ZeroAddress();","title":"transferFrom/burnFrom accept address(0) as the sender, so anyone can emit a zero-value Transfer from address(0) (a fake mint event) and a fake Approval after deployment"}],"hash":"e57638727deb54e038e72039edfadf9a798d4d1210ad620a00463d31009eed9b","nodeId":"940d4658-1b34-4c43-b9b7-29f65d5c31da","outcome":"completed","summary":"The findings file is excluded by the harness's own `.git/info/exclude`, which is expected for a review output. The file is in place, valid JSON, and the cited snippet matches the tree. No source files were changed.\n\n**Review complete.** The Spectra token has no privileged surface at all: no owner, no roles, no modifiers, no initializer, no receive or fallback, and no proxy or delegatecall. Across the Access Control, Trust Gap and Asymmetry guides there is no actor who can be escalated, no setter that redirects value, and no paired function whose state writes fail to mirror. The build passes and all 33 project tests pass. The static-analysis lead (large numeric literal) is the supply constant and is not a defect.\n\n**One low finding** was recorded in `.imd-findings.json`:\n\n- **Zero-address sender is accepted.** The internal transfer and burn helpers reject a zero recipient and a zero spender, but never reject a zero sender. Because a zero amount passes the allowance check, any account can call `transferFrom(address(0), X, 0)` and make the token emit a Transfer from the zero address, which indexers read as a mint, plus an Approval granted by the zero address. Balances and supply are untouched. The reproduction is confirmed with a scratch test under test/scratch that asserts both events. The minimal fix is a zero-sender revert at the top of the internal transfer and burn helpers.\n\n**Coverage.** All five ABI entry points have rows. Approve, burn and transfer hold. TransferFrom and burnFrom carry the one finding. Two extra rows record the constructor and the no-privilege and supply-conservation invariants, both of which hold. Nothing in the assigned area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":491699,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":12139,"runtime":"claude","turns":23,"wallClockMs":188598}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"27168b1ff68f84d2","findings":[{"citation":"resolved","description":"This is the well-known ERC-20 approve race, inherent to the standard's overwrite semantics and present in OpenZeppelin's ERC20 as well. It is reported for completeness under the Economic Security guide's 'legitimate features turned against the protocol' item and is NOT a defect in this implementation: the token behaves exactly as ERC-20 specifies, the README already tells holders to manage allowances carefully, and the launch flows (factory -> distributor, pool seed, PoolManager swaps, claims) never depend on reducing a live allowance. The contract offers no atomic increaseAllowance/decreaseAllowance helper, so a holder who wants to lower an allowance safely must first approve(spender, 0), confirm inclusion, then approve the new value. No fix is required to ship; adding the two helpers is optional and would not change any agreed economics. Not covered by the 4-proof budget on purpose, since it does not reopen work.","line":116,"path":"src/SpectraToken.sol","reproduction":"State: alice holds the supply, alice.approve(bob, 100e18). alice broadcasts approve(bob, 50e18) intending to LOWER bob's limit. bob front-runs with transferFrom(alice, bob, 100e18) (allowance 100e18 -> 0), alice's approve(bob, 50e18) then lands, bob calls transferFrom(alice, bob, 50e18). Expected (from alice's intent): bob can move at most 100e18. Actual: bob's balance is 150e18. Reproduced in test/scratch/ApproveRace.t.sol (passes, i.e. demonstrates the race). The same sequence yields the same result on any ERC-20 that implements approve as an overwrite.","severity":"info","snippet":"        allowance[owner][spender] = amount;","title":"approve() overwrites the allowance, so a spender who front-runs a reduction can spend old plus new (standard ERC-20 race; no increaseAllowance/decreaseAllowance offered)"}],"hash":"f91de0095e03aab1052cfcbec6ddd1d0f8cc1b5cc3eb46a75489127774b63ef6","nodeId":"9771b1d5-8ebf-4de2-a65a-a21b23a94757","outcome":"completed","summary":"The findings file is excluded by the harness's own rule in `.git/info/exclude`, so it is read from disk as the task describes and no tracked file changed. The review is complete.\n\n**Result: no defects in the Spectra token for the Economic Security, Invariant and Flow Gap areas.** The findings file `.imd-findings.json` holds one informational note and ten coverage rows, every one of the five entry points answered.\n\n**What I checked**\n\n- **Conservation laws.** Sum of balances equals total supply, and total supply never exceeds the initial mint. A stateful fuzz in test/scratch mixed transfer, transferFrom, approve, burn and burnFrom across six actors for 128,000 calls with no violation. Self-transfer of the full balance and transferFrom with an unlimited allowance both conserve.\n- **Burn paths.** Both burn functions check the balance before the unchecked block, so neither balance nor supply can underflow. The deployer or factory cannot burn a holder's tokens without an allowance, which matches the protected floor's privileged-hand test.\n- **Launch flows.** There is no fee, exemption or callback code, so the factory to distributor transfer, pool seed, claims and swaps move exact amounts. A scratch flow test split the supply 10 percent, 88 percent and 2 percent exactly and round-tripped a trader through a manager stand-in.\n- **Supply and metadata.** The literal flagged by aderyn equals one billion times ten to the eighteenth. Decimals, name and symbol match the brief. No constructor arguments, so the CREATE2-deploying factory receives the whole supply.\n- **Privilege surface.** The ABI has only the five state-changing functions plus views, three storage slots, no owner or mint path. Runtime bytecode contains no DELEGATECALL, CALLCODE, SELFDESTRUCT, CALL, STATICCALL, CREATE or TSTORE. One early scan of mine mis-skipped PUSH data and flagged false hits. I corrected it and reconfirmed clean.\n\n**The informational note** is the standard ERC-20 approve overwrite race. A spender who front-runs an allowance reduction from 100 to 50 can move 150. It is inherent to the standard, present in OpenZeppelin's ERC20 too, does not affect any launch flow, and needs no fix to ship. I labelled it info so it does not reopen work.\n\n**Not reached.** Nothing in my area. The manifest and economics beyond what the README documents are outside this repository and were not reviewed against a launch.json, since none exists yet.","treeHash":null,"usage":{"cachedInputTokens":910376,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":17451,"runtime":"claude","turns":30,"wallClockMs":339162}}],"verification":[{"checks":[{"durationMs":879,"exitCode":0,"name":"build","output":"Compiling 22 files with Solc 0.8.26\nSolc 0.8.26 finished in 776.93ms\nCompiler run successful!\n","passed":true},{"durationMs":146,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 33 tests for test/SpectraToken.t.sol:SpectraTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 119596, ~: 119706)\nLogs:\n  Bound result 655107945441572327660168678\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 121995, ~: 123934)\nLogs:\n  Bound result 16452224703287904921919264\n  Bound result 580390073134842778439333918\n\n[PASS] testFuzz_transferOverBalanceReverts(uint256,uint256) (runs: 256, μ: 99467, ~: 100074)\nLogs:\n  Bound result 16452224703287904921919264\n  Bound result 1460829536184078415658360583977841307756011468238750655651854550011266970\n\n[PASS] test_RevertWhen_approveZeroAddressSpender() (gas: 32483)\n[PASS] test_RevertWhen_burnExceedsBalance() (gas: 34940)\n[PASS] test_RevertWhen_burnFromWithoutAllowance() (gas: 106868)\n[PASS] test_RevertWhen_deployerPullsFromHolderWithoutAllowance() (gas: 98158)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 92452)\n[PASS] test_RevertWhen_transferFromEmptyAccount() (gas: 37719)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 88052)\n[PASS] test_RevertWhen_transferFromExceedsBalanceEvenWithAllowance() (gas: 95109)\n[PASS] test_RevertWhen_transferFromToZeroAddress() (gas: 89799)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 40524)\n[PASS] test_RevertWhen_transferToZeroAddress() (gas: 32549)\n[PASS] test_approveOverwritesPriorAllowance() (gas: 95261)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68045)\n[PASS] test_burnFromSpendsAllowance() (gas: 182350)\n[PASS] test_burnReducesBalanceAndSupply() (gas: 117156)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8198)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 23223)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1052883)\n[PASS] test_metadata() (gas: 26579)\n[PASS] test_noAdminCallExistsOrGrowsSupply() (gas: 694456)\n[PASS] test_rejectsEther() (gas: 39407)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 2137322)\n[PASS] test_supplyGoesToTheContractThatDeploys() (gas: 237902)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 28865)\n[PASS] test_transferFromSpendsAllowance() (gas: 172716)\n[PASS] test_transferFromWithMaxAllowanceDoesNotDecrement() (gas: 135481)\n[PASS] test_transferMovesExactAmount() (gas: 95714)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43613)\n[PASS] test_transferWholeBalance() (gas: 78175)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47520)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 23.79ms (64.46ms CPU time)\n\nRan 1 test suite in 24.43ms (23.79ms CPU time): 33 tests passed, 0 failed, 0 skipped (33 total tests)\n","passed":true},{"durationMs":43,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SpectraToken.approve(address,uint256)\",\"SpectraToken.burn(uint256)\",\"SpectraToken.burnFrom(address,uint256)\",\"SpectraToken.transfer(address,uint256)\",\"SpectraToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":124,\"foundry.toml\":20,\"launch.json\":24,\"remappings.txt\":1,\"script/DeploySpectra.s.sol\":25,\"src/SpectraToken.sol\":139,\"test/SpectraToken.t.sol\":370},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0e308bfece35fd92189344edc13ce952cfbb7f0a573045cff5eef1241b391426","verifiedTreeHash":"9d271c3ebd8369d41565eb6601338793b0b69ff5","verifierVersion":"0.1.0+c4d32abc"},{"checks":[{"durationMs":2591,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.47s\nCompiler run successful!\n","passed":true},{"durationMs":8832,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/SpectraToken.launch.t.sol:SpectraTokenLaunchTest\n[PASS] testFuzz_anySplitArrivesWhole(uint256) (runs: 256, μ: 244967, ~: 246306)\nLogs:\n  Bound result 5807\n\n[PASS] test_creationCodeTakesNoArguments() (gas: 488091)\n[PASS] test_factoryCannotMoveOrFreezeAHolderAfterwards() (gas: 491985)\n[PASS] test_fullPayoutSumsToSupplyExactly() (gas: 258878)\n[PASS] test_poolManagerPullsSeedAndPaysTradersExactly() (gas: 556016)\n[PASS] test_supplyMintedToTheFactory() (gas: 43855)\n[PASS] test_swarmShareArrivesWholeAndIsClaimableWhole() (gas: 150774)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 93.01ms (74.97ms CPU time)\n\nRan 33 tests for test/SpectraToken.t.sol:SpectraTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 119605, ~: 119658)\nLogs:\n  Bound result 22463\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 125200, ~: 149386)\nLogs:\n  Bound result 11000000000000000000\n  Bound result 2739854338\n\n[PASS] testFuzz_transferOverBalanceReverts(uint256,uint256) (runs: 256, μ: 99718, ~: 100130)\nLogs:\n  Bound result 944935850791\n  Bound result 4878148513243098753867041001030199137909931360003320024493838197831449\n\n[PASS] test_RevertWhen_approveZeroAddressSpender() (gas: 32483)\n[PASS] test_RevertWhen_burnExceedsBalance() (gas: 34940)\n[PASS] test_RevertWhen_burnFromWithoutAllowance() (gas: 106868)\n[PASS] test_RevertWhen_deployerPullsFromHolderWithoutAllowance() (gas: 98158)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 92452)\n[PASS] test_RevertWhen_transferFromEmptyAccount() (gas: 37719)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 88052)\n[PASS] test_RevertWhen_transferFromExceedsBalanceEvenWithAllowance() (gas: 95109)\n[PASS] test_RevertWhen_transferFromToZeroAddress() (gas: 89799)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 40524)\n[PASS] test_RevertWhen_transferToZeroAddress() (gas: 32549)\n[PASS] test_approveOverwritesPriorAllowance() (gas: 95261)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68045)\n[PASS] test_burnFromSpendsAllowance() (gas: 182350)\n[PASS] test_burnReducesBalanceAndSupply() (gas: 117156)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8198)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 23223)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1052883)\n[PASS] test_metadata() (gas: 26579)\n[PASS] test_noAdminCallExistsOrGrowsSupply() (gas: 694456)\n[PASS] test_rejectsEther() (gas: 39407)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 2137322)\n[PASS] test_supplyGoesToTheContractThatDeploys() (gas: 237902)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 28865)\n[PASS] test_transferFromSpendsAllowance() (gas: 172716)\n[PASS] test_transferFromWithMaxAllowanceDoesNotDecrement() (gas: 135481)\n[PASS] test_transferMovesExactAmount() (gas: 95714)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43613)\n[PASS] test_transferWholeBalance() (gas: 78175)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47520)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 93.04ms (228.82ms CPU time)\n\nRan 52 tests for test/SpectraToken.edges.t.sol:SpectraTokenEdgesTest\n[PASS] testFuzz_approveRoundTrip(address,address,uint256) (runs: 1000, μ: 99114, ~: 99397)\n[PASS] testFuzz_burnFromOracle(uint256,uint256,uint256) (runs: 1000, μ: 169818, ~: 161430)\nLogs:\n  Bound result 0\n\n[PASS] testFuzz_burnOracle(uint256,uint256) (runs: 1000, μ: 135532, ~: 129377)\nLogs:\n  Bound result 830588265366\n\n[PASS] testFuzz_burnsAccumulateExactly(uint256,uint256) (runs: 1000, μ: 103726, ~: 103751)\nLogs:\n  Bound result 1\n  Bound result 1183263447522525\n\n[PASS] testFuzz_noCallerCanGrowSupply(address,bytes4,uint256,uint256) (runs: 1000, μ: 47425, ~: 47468)\n[PASS] testFuzz_selfTransferIsIdentity(uint256,uint256) (runs: 1000, μ: 115513, ~: 115854)\nLogs:\n  Bound result 830588265366\n  Bound result 426022981430\n\n[PASS] testFuzz_splitTransfersSumExactly(uint256,uint256) (runs: 1000, μ: 124601, ~: 125379)\nLogs:\n  Bound result 999999999999999999999999997\n  Bound result 355489705514214112316642820\n\n[PASS] testFuzz_strangerCannotMoveHolderBalance(address,uint256,uint256) (runs: 1000, μ: 138547, ~: 138498)\nLogs:\n  Bound result 1035794\n  Bound result 167552143601016023196304591823545042589392986186860601384908959987200\n\n[PASS] testFuzz_transferOracle(uint256,uint256) (runs: 1000, μ: 156593, ~: 148352)\nLogs:\n  Bound result 177362148\n\n[PASS] testFuzz_transferRoundTripRestoresBalances(uint256) (runs: 1000, μ: 116759, ~: 116613)\nLogs:\n  Bound result 8150\n\n[PASS] testFuzz_unlimitedAllowanceNeverChanges(uint256,uint256) (runs: 1000, μ: 190001, ~: 190196)\nLogs:\n  Bound result 830588265366\n  Bound result 906490298591824218867817554\n\n[PASS] test_RevertWhen_burnFromExceedsAllowance() (gas: 102101)\n[PASS] test_RevertWhen_burnFromExceedsBalanceConsumesNoAllowance() (gas: 176617)\n[PASS] test_RevertWhen_burnFromSelfWithoutAllowance() (gas: 35908)\n[PASS] test_RevertWhen_burnMaxUint() (gas: 35400)\n[PASS] test_RevertWhen_burnOneOverBalance() (gas: 95495)\n[PASS] test_RevertWhen_deployerBurnsFromHolderWithBoolEncodedAmount() (gas: 106575)\n[PASS] test_RevertWhen_etherSentWithKnownSelector() (gas: 48143)\n[PASS] test_RevertWhen_ownerTransferFromSelfWithoutAllowance() (gas: 38518)\n[PASS] test_RevertWhen_selfTransferExceedsBalance() (gas: 36058)\n[PASS] test_RevertWhen_transferFromOverBalanceConsumesNoAllowance() (gas: 170042)\n[PASS] test_RevertWhen_transferFromToZeroWithUnlimitedAllowance() (gas: 92197)\n[PASS] test_RevertWhen_transferFromZeroAddressSource() (gas: 94495)\n[PASS] test_RevertWhen_transferMaxUint() (gas: 38211)\n[PASS] test_RevertWhen_transferSupplyPlusOne() (gas: 38068)\n[PASS] test_RevertWhen_transferZeroAmountToZeroAddress() (gas: 32571)\n[PASS] test_RevertWhen_unknownSelectorIsCalled() (gas: 74076)\n[PASS] test_allowanceIsDirectional() (gas: 155665)\n[PASS] test_allowanceIsPerSpender() (gas: 187457)\n[PASS] test_allowanceMaxMinusOneIsDecremented() (gas: 130882)\n[PASS] test_approveCanExceedBalance() (gas: 65614)\n[PASS] test_approveSelfIsAllowed() (gas: 146171)\n[PASS] test_approveZeroClearsAllowanceAndEmits() (gas: 131301)\n[PASS] test_burnFromEmitsApprovalAndTransfer() (gas: 106199)\n[PASS] test_burnFromWithUnlimitedAllowanceDoesNotDecrement() (gas: 126035)\n[PASS] test_burnFromZeroWithoutAllowanceSucceeds() (gas: 51111)\n[PASS] test_burnWholeSupplyLeavesZero() (gas: 130593)\n[PASS] test_burnZeroEmitsAndChangesNothing() (gas: 46281)\n[PASS] test_metadataExactBytes() (gas: 35323)\n[PASS] test_runtimeFitsEip170() (gas: 7903)\n[PASS] test_sameTransferTwiceFailsTheSecondTime() (gas: 147452)\n[PASS] test_standardSelectorsAnswer() (gas: 222275)\n[PASS] test_standardSelectorsByRawBytes() (gas: 243308)\n[PASS] test_supplyInWholeTokens() (gas: 32145)\n[PASS] test_transferFromExactAllowanceLeavesZero() (gas: 161457)\n[PASS] test_transferFromZeroAmountWithoutAllowanceSucceeds() (gas: 59660)\n[PASS] test_transferOneWeiRepeatedUntilEmpty() (gas: 237919)\n[PASS] test_transferToTokenContractIsAllowedButStranded() (gas: 77946)\n[PASS] test_twoDeploymentsAreIndependent() (gas: 83153)\n[PASS] test_unlimitedAllowanceEmitsNoApprovalOnSpend() (gas: 127002)\n[PASS] test_unlimitedAllowanceSurvivesDrainingTheOwner() (gas: 171634)\n[PASS] test_zeroValueTransferEmitsEvent() (gas: 43578)\nSuite result: ok. 52 passed; 0 failed; 0 skipped; finished in 93.16ms (1.01s CPU time)\n\nRan 1 test for test/SpectraToken.invariant.t.sol:SpectraTokenOpenInvariantTest\n[PASS]\nSpectraTokenOpenInvariantTest invariants:\n[PASS] invariant_knownBalancesBoundedBySupply\n[PASS] invariant_metadataIsConstant\n[PASS] invariant_supplyNeverGrows\n[PASS] invariant_zeroAddressHoldsNothing\n SpectraTokenOpenInvariantTest invariants (runs: 256, calls: 16384, reverts: 9281)\n\n╭--------------+--------------+-------+---------+----------╮\n| Contract     | Selector     | Calls | Reverts | Discards |\n+==========================================================+\n| SpectraToken | approve      | 3316  | 16      | 0        |\n|--------------+--------------+-------+---------+----------|\n| SpectraToken | burn         | 3236  | 1348    | 0        |\n|--------------+--------------+-------+---------+----------|\n| SpectraToken | burnFrom     | 3144  | 3108    | 0        |\n|--------------+--------------+-------+---------+----------|\n| SpectraToken | transfer     | 3317  | 1475    | 0        |\n|--------------+--------------+-------+---------+----------|\n| SpectraToken | transferFrom | 3371  | 3334    | 0        |\n╰--------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 707.85ms (705.46ms CPU time)\n\nRan 1 test for test/SpectraToken.invariant.t.sol:SpectraTokenInvariantTest\n[PASS]\nSpectraTokenInvariantTest invariants:\n[PASS] invariant_allowancesMatchLedger\n[PASS] invariant_eachBalanceMatchesLedger\n[PASS] invariant_metadataIsConstant\n[PASS] invariant_noBalanceExceedsSupply\n[PASS] invariant_supplyEqualsSumOfBalances\n[PASS] invariant_supplyNeverGrowsAndTracksBurns\n[PASS] invariant_zeroAddressHoldsNothing\n SpectraTokenInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭----------------+---------------------------+-------+---------+----------╮\n| Contract       | Selector                  | Calls | Reverts | Discards |\n+=========================================================================+\n| SpectraHandler | approve                   | 1377  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | approveZeroAddress        | 1344  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | burn                      | 1328  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | burnFrom                  | 1415  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | burnFromOverLimit         | 1325  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | burnOverBalance           | 1303  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transfer                  | 1324  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transferFrom              | 1365  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transferFromOverLimit     | 1363  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transferFromToZeroAddress | 1368  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transferOverBalance       | 1452  | 0       | 0        |\n|----------------+---------------------------+-------+---------+----------|\n| SpectraHandler | transferToZeroAddress     | 1420  | 0       | 0        |\n╰----------------+---------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 2054\n  Bound result 4\n  Bound result 347933234455288406505564118251235470042666062887195911080440\n  Bound result 4\n  Bound result 2\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3971\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 3\n  Bound result 614177534613597280024854910193568325093385084016214050695476521\n  Bound result 2\n  Bound result 2\n  Bound result 9300580031494707357201999029203758700533633164690121860939231895468479\n  Bound result 4\n  Bound result 2\n  Bound result 0\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 17907\n  Bound result 4\n  Bound result 0\n  Bound result 3\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 18441\n  Bound result 2\n  Bound result 1375886630885131\n  Bound result 4\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 899998999999999999999999998\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 3\n  Bound result 3\n  Bound result 5000000000000000000\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 10\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 7059\n  Bound result 2\n  Bound result 0\n  Bound result 14171\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 2835717307\n  Bound result 4\n  Bound result 4\n  Bound result 5000000000000000001\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 19124\n  Bound result 2\n  Bound result 11849\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 244\n  Bound result 2\n  Bound result 2\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 31309\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 3709\n  Bound result 4\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 2739854338\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 127\n  Bound result 1\n  Bound result 3058\n  Bound result 2\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.74s (8.74s CPU time)\n\nRan 5 test suites in 8.75s (9.73s CPU time): 94 tests passed, 0 failed, 0 skipped (94 total tests)\n","passed":true},{"durationMs":51,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SpectraToken.approve(address,uint256)\",\"SpectraToken.burn(uint256)\",\"SpectraToken.burnFrom(address,uint256)\",\"SpectraToken.transfer(address,uint256)\",\"SpectraToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":124,\"foundry.toml\":20,\"remappings.txt\":1,\"script/DeploySpectra.s.sol\":25,\"src/SpectraToken.sol\":139,\"test/SpectraToken.edges.t.sol\":638,\"test/SpectraToken.invariant.t.sol\":440,\"test/SpectraToken.launch.t.sol\":183,\"test/SpectraToken.t.sol\":370},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"24abbd24591e194d2e7f28658d8ad68a11c84e12d01e7883501398526f170a55","verifiedTreeHash":"9a2b1a3cb2073f0c12aeba88a23c526262c3aa7f","verifierVersion":"0.1.0+c4d32abc"},{"checks":[{"durationMs":822,"exitCode":0,"name":"build","output":"Compiling 22 files with Solc 0.8.26\nSolc 0.8.26 finished in 727.68ms\nCompiler run successful!\n","passed":true},{"durationMs":105,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 33 tests for test/SpectraToken.t.sol:SpectraTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 119294, ~: 119706)\nLogs:\n  Bound result 46049551571460525733153174\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256) (runs: 256, μ: 119750, ~: 96334)\nLogs:\n  Bound result 727\n  Bound result 11243\n\n[PASS] testFuzz_transferOverBalanceReverts(uint256,uint256) (runs: 256, μ: 99368, ~: 100048)\nLogs:\n  Bound result 183068256606454550156880059\n  Bound result 37306311070313404980569871962\n\n[PASS] test_RevertWhen_approveZeroAddressSpender() (gas: 32483)\n[PASS] test_RevertWhen_burnExceedsBalance() (gas: 34940)\n[PASS] test_RevertWhen_burnFromWithoutAllowance() (gas: 106868)\n[PASS] test_RevertWhen_deployerPullsFromHolderWithoutAllowance() (gas: 98158)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 92452)\n[PASS] test_RevertWhen_transferFromEmptyAccount() (gas: 37719)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 88052)\n[PASS] test_RevertWhen_transferFromExceedsBalanceEvenWithAllowance() (gas: 95109)\n[PASS] test_RevertWhen_transferFromToZeroAddress() (gas: 89799)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 40524)\n[PASS] test_RevertWhen_transferToZeroAddress() (gas: 32549)\n[PASS] test_approveOverwritesPriorAllowance() (gas: 95261)\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 68045)\n[PASS] test_burnFromSpendsAllowance() (gas: 182350)\n[PASS] test_burnReducesBalanceAndSupply() (gas: 117156)\n[PASS] test_constructorEmitsMintTransfer() (gas: 8198)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 23223)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1052883)\n[PASS] test_metadata() (gas: 26579)\n[PASS] test_noAdminCallExistsOrGrowsSupply() (gas: 694456)\n[PASS] test_rejectsEther() (gas: 39407)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 2137322)\n[PASS] test_supplyGoesToTheContractThatDeploys() (gas: 237902)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 28865)\n[PASS] test_transferFromSpendsAllowance() (gas: 172716)\n[PASS] test_transferFromWithMaxAllowanceDoesNotDecrement() (gas: 135481)\n[PASS] test_transferMovesExactAmount() (gas: 95714)\n[PASS] test_transferToSelfKeepsBalance() (gas: 43613)\n[PASS] test_transferWholeBalance() (gas: 78175)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47520)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 7.62ms (30.08ms CPU time)\n\nRan 1 test suite in 8.99ms (7.62ms CPU time): 33 tests passed, 0 failed, 0 skipped (33 total tests)\n","passed":true},{"durationMs":28,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SpectraToken.approve(address,uint256)\",\"SpectraToken.burn(uint256)\",\"SpectraToken.burnFrom(address,uint256)\",\"SpectraToken.transfer(address,uint256)\",\"SpectraToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":124,\"foundry.toml\":20,\"remappings.txt\":1,\"script/DeploySpectra.s.sol\":25,\"src/SpectraToken.sol\":139,\"test/SpectraToken.t.sol\":370},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":312,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":208,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/SpectraToken.sol:22: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"34ffbc610f84cea65ea474ae2813b2cb868ca03063212aa8cb61fb76ebfc42d9","verifiedTreeHash":"5873fab35f311ec50cf838bd8fb81cee8cdc5171","verifierVersion":"0.1.0+c4d32abc"}]}