{"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":"96b74c3a-6fb3-41c1-af24-67de402d3ce9","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"5293f339b71b5297c0459c3cc9cfc9149819ee7c305cb6b250dbb27c0d83e014","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"20e71a9ece73ec084aac19c97648d1284890985938696b282c398ba715584962","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"67769399d2726d20d86124213fe8d372187f9af013bd073c5013e01b5e119f4c","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","subagents":4,"tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"11062224afd4663320da57285fbf52a4c40932d33b1ae0be4f830d0a29aff0a3","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"399e1419710e38c33a36b1a7e4bfd55610683ac49d6b86f09ce43f1b4827a186","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"6f4b88758542c5cf568dac8faf89f274ee21abfe9d74996ad2746e51d789a81e","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"816fe39c7efd64504a19175b0f4dd9186d61069f37a22684c90358a18c60bddc","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"816fe39c7efd64504a19175b0f4dd9186d61069f37a22684c90358a18c60bddc","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"cc89295c8c35ac56d06acdd3b92fd64bc57e609b32929beff1e0520d0643bba3","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"4b407f3e8c9cb49a343bd9f6fe6fc3a122c39d18e7f24d0a5bf483ea88362630","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"606842ccca0e7c5d3017a54684625438eab9b351eb51dcf0cf88c43d1ea41464","skillId":"write-foundry-tests","subagents":4,"tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"606842ccca0e7c5d3017a54684625438eab9b351eb51dcf0cf88c43d1ea41464","skillId":"write-foundry-tests","state":"accepted"}],"objective":"A custom token: Paperclash (PAPER).\nToken name: Paperclash\nToken symbol: PAPER\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.\nWhat it does: Powered by imd","parentJobId":null,"planHash":"4905af5771bc0950f6c8c0f0c785c113b5124570bbb28a072a38caedb702b8f9","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"96b74c3a-6fb3-41c1-af24-67de402d3ce9","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2615-paperclash"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52734","feedbackHash":"470087e9f06c36f279d61294fd4c2574e3d05227d677ca87cb18596db330365d","nodeKey":"audit_economics","submissionHash":"5293f339b71b5297c0459c3cc9cfc9149819ee7c305cb6b250dbb27c0d83e014","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52397","feedbackHash":"29e4dc1a24a69cb9a0d4d79dd5c23bad267136652c23c6c3b3358f83f8d96fc7","nodeKey":"audit_flow","submissionHash":"20e71a9ece73ec084aac19c97648d1284890985938696b282c398ba715584962","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52120","feedbackHash":"c7eb31e225272bd53cb7549f083aad66f72c9effa4ea65bc4d8b23172969636e","nodeKey":"audit_judge","submissionHash":"67769399d2726d20d86124213fe8d372187f9af013bd073c5013e01b5e119f4c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52214","feedbackHash":"2b72dbb71ae0db275c86ae38c2c7959fd4e4636e548998676a7eb9792da18fd5","nodeKey":"audit_math","submissionHash":"11062224afd4663320da57285fbf52a4c40932d33b1ae0be4f830d0a29aff0a3","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52261","feedbackHash":"35b1c1ced851af044bb7ba37b9a022f1957058c0519e031faf4ed5e6efd85592","nodeKey":"audit_permissions","submissionHash":"399e1419710e38c33a36b1a7e4bfd55610683ac49d6b86f09ce43f1b4827a186","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52396","feedbackHash":"202e9877158967fb6cc97b19a120fcf1e76c0943235f68b9a8512cffdc27668e","nodeKey":"build_contract_project","submissionHash":"6f4b88758542c5cf568dac8faf89f274ee21abfe9d74996ad2746e51d789a81e","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52681","feedbackHash":"301a4422618891b6c581fcab4be161738733a5e165cf3d39314d2b6df18e2de9","nodeKey":"manifest","submissionHash":"cc89295c8c35ac56d06acdd3b92fd64bc57e609b32929beff1e0520d0643bba3","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52600","feedbackHash":"16cd487acf5625d3910af51b1bb28b6a58ded347de3bb8d782e7dc582da56c24","nodeKey":"write_foundry_tests","submissionHash":"4b407f3e8c9cb49a343bd9f6fe6fc3a122c39d18e7f24d0a5bf483ea88362630","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"4e97cf27921fffd2f938dd26f4f1ce1d36e26ada7139276ae6292cbbc016aeae","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"6b47d1bf92391c22","findings":[],"hash":"11062224afd4663320da57285fbf52a4c40932d33b1ae0be4f830d0a29aff0a3","nodeId":"748b0b4e-0061-46ab-a5e8-6f9ad0d36e0a","outcome":"completed","summary":"I found no math defects in the Paperclash token. `.imd-findings.json` has an empty findings list and a coverage row for each of the three entry points, all marked `holds`, plus two rows for the supply and exact-amount checks. The file is valid JSON.\n\n**What I checked:** `src/PaperclashToken.sol` is a plain OpenZeppelin 5.4.0 ERC20. It doesn't change any transfer or approval logic, and I read the library code to confirm it is the standard version. I covered the Math Precision, Boundary and Numerical Gap guides:\n- **Supply:** `TOTAL_SUPPLY = 1_000_000_000 * 10 ** 18` comes to exactly 1e27, which fits easily in a uint256. It is minted once, to the deployer, in the constructor, and no mint or burn function is exposed. The aderyn large-literal warning on line 28 is harmless.\n- **Edge cases:** sending more than the balance or allowance, even by 1, reverts. The unchecked arithmetic can't overflow because no balance or allowance can exceed the fixed supply. Zero-amount, self, and full-balance transfers are exact. An unlimited (max) allowance is never decremented.\n- **Exact amounts:** there is no fee, burn or rounding, so the transfers to the distributor, the pool seed and swaps all arrive whole.\n- **Tests:** the project's 31 tests pass.\n\n**Not covered:** I didn't count the known ERC-20 `approve` front-running race as a finding. It is standard ERC-20 behaviour, falls outside the math area, and isn't a defect in this code. There's no `launch.json` yet, so I had nothing to review there. Apart from the findings file, I changed no files.","treeHash":null,"usage":{"cachedInputTokens":124604,"inputTokens":10,"model":"claude-opus-5-5","outputTokens":2113,"runtime":"claude","turns":5,"wallClockMs":36066}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"827152cce766ca0d","findings":[],"hash":"20e71a9ece73ec084aac19c97648d1284890985938696b282c398ba715584962","nodeId":"0273eda8-24e6-4c8e-881b-b625ec309a98","outcome":"completed","summary":"I found no defects I could back with a reproduction, so `.imd-findings.json` has an empty findings list and a coverage record. That file is the only thing I wrote; no source, test or config file was changed.\n\n**What the code is:** `src/PaperclashToken.sol` is OpenZeppelin 5.4.0's standard `ERC20` with nothing changed. It adds a few constants and a constructor that mints `1_000_000_000 * 10**18` to `msg.sender` once. It has no `_update` override, no owner, no mint or burn functions, no pause, no assembly and no external calls. The library code under `lib/openzeppelin-contracts` has no local changes.\n\n**Execution Trace pass:**\n- **`transfer` and `transferFrom`:** both run straight through OpenZeppelin's `_transfer` → `_update`. They move exactly the amount asked for, and revert if the sender or recipient is the zero address or the balance is too small. There are no callbacks, so there is nothing to re-enter.\n- **Allowance:** `transferFrom` checks and spends the allowance before moving tokens, all in one call. An unlimited allowance is not reduced.\n- **`approve`:** this is OpenZeppelin's `_approve`. The \"change an approval and get front-run\" race is how every standard ERC-20 behaves, not a defect in this code.\n\n**Periphery pass:**\n- **Launch flows:** transfers from the factory, the distributor and the PoolManager arrive whole, because there is no fee or burn on transfer.\n- **Constructor:** it takes no arguments, so the manifest's `token.constructorArgs` must be `[]`.\n- **Deploy script:** `script/DeployPaperclash.s.sol` is a reference script only and gives no one any special role.\n\n**First Principles pass:**\n- **Supply:** it can never grow after deployment.\n- **No privileged control:** nobody can move or freeze a holder's balance.\n- **Forbidden opcodes:** none of the code uses DELEGATECALL, CALLCODE or SELFDESTRUCT.\n\n**Static analysis:** aderyn flagged a \"large numeric literal\" at line 28. The value is 1e27, which fits easily, so that note is about style and isn't a defect. slither reported nothing.\n\n**Checks I ran:** the existing test suite passes, 31 of 31. I did not run the protected launch tests in `.imd/reads/protected/` because they need the launch harness and its environment settings. I checked by reading the code what they test: the supply is minted to the factory, the launch flows arrive whole, and no admin call can mint or freeze balances.\n\n**Coverage:** all three listed entry points are marked `holds`, plus two invariant rows (fixed supply, and no forbidden opcodes or special powers). Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":143940,"inputTokens":10,"model":"claude-opus-5-5","outputTokens":2560,"runtime":"claude","turns":5,"wallClockMs":38319}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dedc96e38388cb45","findings":[{"citation":"resolved","description":"Area: Asymmetry (approve <-> pull pair) and Trust Gap (access x asymmetry). PaperclashToken inherits OpenZeppelin v5.4.0 ERC20 unmodified (vendored files hash-identical to upstream v5.4.0). `approve` writes `_allowances[owner][spender] = value` unconditionally (lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol:280) while `transferFrom` decrements it via `_spendAllowance` (ERC20.sol:294-304). The two sides of the pair are not atomic with respect to each other, so when a holder lowers an existing non-zero allowance the approved spender can observe the pending `approve` and pull the old amount first, then the new amount after it lands. This is the well-known ERC-20 approve race inherent to the standard the brief asked for; OpenZeppelin v5 removed increaseAllowance/decreaseAllowance deliberately. It is NOT a privilege bypass: only an address the holder itself approved can exploit it, and only when the holder reduces a non-zero allowance in one step. Reported at info level so the author can decide whether to document it or add optional additive helpers (e.g. increaseAllowance/decreaseAllowance, or advising holders to approve 0 first). No change to the agreed design is needed; the token otherwise has no owner, role, modifier, initializer, proxy, external call, or privileged path of any kind.","line":14,"path":"src/PaperclashToken.sol","reproduction":"State: token deployed by FACTORY (holds 1e27); FACTORY.transfer(ALICE, 1000e18). Sequence: (1) ALICE calls approve(BOB, 100e18). (2) ALICE broadcasts approve(BOB, 50e18) intending to reduce. (3) BOB, seeing (2) in the mempool, front-runs with transferFrom(ALICE, BOB, 100e18) -> succeeds, allowance becomes 0. (4) ALICE's approve(BOB, 50e18) lands and overwrites the allowance to 50e18 unconditionally. (5) BOB calls transferFrom(ALICE, BOB, 50e18) -> succeeds. Expected by ALICE: BOB can spend at most 50e18 in total after the reduction. Actual: balanceOf(BOB) == 150e18, balanceOf(ALICE) == 850e18. Verified with a Foundry test (test/scratch, not kept): sequence above passes with assertEq(token.balanceOf(BOB), 150 ether).","severity":"info","snippet":"contract PaperclashToken is ERC20 {","title":"approve/transferFrom asymmetry: unconditional allowance overwrite lets a spender front-run an allowance reduction (standard ERC-20 approve race)"}],"hash":"399e1419710e38c33a36b1a7e4bfd55610683ac49d6b86f09ce43f1b4827a186","nodeId":"4acd8dc0-65ad-49c4-a5e9-3bf742256a3f","outcome":"completed","summary":"The permissions review of Paperclash (PAPER) is complete. The findings file is written and the working tree is otherwise untouched.\n\n**Outcome: no permission defect.** The token is OpenZeppelin ERC20 v5.4.0 with a no-argument constructor that mints the whole supply to the deployer. It has no owner, role, modifier, initializer, proxy, hook, external call, receive or fallback. The compiled ABI exposes exactly three state-changing functions, each acting only on the caller's own balance or allowance row.\n\n**What I verified**\n\n- **Access Control.** The permission map is empty beyond the constructor's one mint. Balances are written only through the shared transfer path, allowances only by the owner's own approve or by a spender within its allowance. The factory has no pull right over holders, and the supply cannot grow or shrink after construction since burn is unreachable.\n- **Asymmetry.** The approve and transferFrom pair mirror each other correctly, including the documented infinite-allowance branch. The mint and burn branches inside the update routine are reachable only from the constructor.\n- **Trust Gap.** There is no economic formula inside the token and no privileged actor, so none of the four seams exist.\n- **Supply chain.** The five vendored OpenZeppelin files are hash-identical to upstream v5.4.0, so the inherited code is what it claims to be.\n- **Tooling.** The project builds and all 31 tests pass with the verifier's fuzz seed. The static analysis leads were a large numeric literal only.\n\n**One informational finding.** The standard ERC-20 approve race is present because approve overwrites the allowance unconditionally. A spender the holder already approved can front-run an allowance reduction and spend old plus new amounts. I reproduced it with a scratch test, which I then removed. This is inherent to the plain ERC-20 the brief asked for and is not a privilege bypass, so it is recorded at info level with an optional additive mitigation.\n\n**Coverage.** All three entry points have rows, plus five invariant and trust-assumption rows. Nothing in the assigned area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":569308,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":13955,"runtime":"claude","turns":30,"wallClockMs":199650}},{"artifacts":[],"attempt":1,"bundleHash":"0ac32fd119e0937ff5f49820026eeb3ce36a8dac773e171004eb202f57738b16","device":"fa4b91aed45c94fa","findings":[],"hash":"4b407f3e8c9cb49a343bd9f6fe6fc3a122c39d18e7f24d0a5bf483ea88362630","nodeId":"6f8d1760-94d0-4f2f-958d-e8b816ab8fc0","outcome":"completed","summary":"I've added two test files for the Paperclash (PAPER) token, and found no defects. The full suite passes with the verifier's fuzz seed: 45 tests across 3 suites. I left the existing `test/PaperclashToken.t.sol` (31 tests) as it was, and nothing is committed.\n\nThe token is a plain OpenZeppelin 5.4 ERC-20. It mints 1,000,000,000 × 10¹⁸ to whoever deploys it, and has no owner, mint function, tax or other admin control. So I didn't write `.imd-findings.json`.\n\n**`test/PaperclashToken.invariant.t.sol`** is the invariant suite the acceptance criteria ask for:\n- A handler drives random sequences of calls across five actors: the deployer, two holders, a pool and a distributor.\n- It mixes normal calls (transfer, approve, transferFrom, including unlimited approvals) with calls that must fail: overspending a balance, overspending an allowance, pulling more than the owner holds, sending to the zero address, approving the zero address, and a stranger pulling tokens without approval.\n- Each failing call must revert with the exact OpenZeppelin error, and the suite stops on any unexpected revert. So a call that succeeds when it should fail, or the reverse, breaks the run.\n- The handler keeps its own record of every balance and allowance. After each step the checks confirm:\n  - the total supply stays fixed and the zero address holds nothing;\n  - the actors' balances add up to the total supply;\n  - every balance and allowance matches the handler's record;\n  - name, symbol and decimals never change.\n- It runs 256 sequences of 64 calls (16,384 calls) with no failures; all nine handler functions were called.\n\n**`test/PaperclashToken.edges.t.sol`** has 13 tests for edge cases the existing suite didn't cover:\n- Transferring the whole supply, then trying to send 1 more wei; and a transfer of the maximum possible amount.\n- A new approval replacing an old one rather than adding to it; revoking an approval; using an allowance up exactly, then failing on the next wei.\n- A holder pulling from their own account needs an approval too.\n- A zero-amount pull works without any allowance; pulls to or from the zero address revert, and a reverted pull leaves the allowance untouched.\n- Spending against an unlimited allowance doesn't emit an Approval event.\n- Fuzz tests (1,000 runs each): an approval sets exactly the amount given, and a random stranger can't pull from the deployer.","treeHash":"4c3b4a7b32e880c1447080dafa11fdfaa1887845","usage":{"cachedInputTokens":220752,"inputTokens":14,"model":"claude-opus-5-5","outputTokens":10871,"runtime":"claude","turns":8,"wallClockMs":107855}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"d32559488518f947","findings":[{"citation":"resolved","description":"Not a defect in the deployed state: decimals() (inherited OpenZeppelin ERC20.decimals, hard-coded 18) and DECIMALS both return 18 today, and the scratch invariant test confirms decimals() == DECIMALS and TOTAL_SUPPLY == 1e9 * 10**decimals(). The gap is a state coupling (Invariant guide, Step 1): TOTAL_SUPPLY on line 28 is derived from DECIMALS, but the ERC-20-visible decimals() never reads DECIMALS, and the manifest/README cite DECIMALS as the authority. A later edit of DECIMALS alone would change the minted supply while decimals() stayed at 18, and the launch floor's test_decimalsMatchTheManifest compares decimals(), not DECIMALS. Minimal fix that preserves behaviour: add `function decimals() public pure override returns (uint8) { return DECIMALS; }`, which keeps 18 today and binds the three facts together. No funds are at risk now; recorded so the judge can see the coupling was checked.","line":25,"path":"src/PaperclashToken.sol","reproduction":"Current tree: deploy PaperclashToken; call decimals() -> 18, DECIMALS() -> 18, TOTAL_SUPPLY() -> 1000000000000000000000000000. Holds. The coupling gap: the value returned by decimals() comes from lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol line 78 (`return 18;`), not from src/PaperclashToken.sol line 25; nothing in the token overrides decimals(). Scratch test test/scratch/EconomicsInvariants.t.sol::invariant_decimalsCoupling passes on this tree.","severity":"info","snippet":"    uint8 public constant DECIMALS = 18;","title":"decimals() is not bound to the DECIMALS constant that sizes TOTAL_SUPPLY; the two agree only by convention"},{"citation":"resolved","description":"Inherent property of the ERC-20 approve semantics the brief asked for, not a deviation from it. OpenZeppelin v5.4.0 ERC20 (vendored byte-identical to upstream, hashes checked) no longer ships increaseAllowance/decreaseAllowance, and the token adds no ERC-2612 permit, so holders have no race-free way to adjust an allowance other than approve(spender, 0) first and checking it landed. Who loses: a holder who lowers a non-zero allowance to a spender that watches the mempool; the spender can take old + new. Documented here as a trust assumption on spenders, not as a code defect; adding increaseAllowance/decreaseAllowance would widen the agreed ABI and is the requester's call.","line":14,"path":"src/PaperclashToken.sol","reproduction":"State: FACTORY transfers 150e18 PAPER to ALICE; ALICE approve(BOB, 100e18). ALICE then submits approve(BOB, 50e18). BOB front-runs with transferFrom(ALICE, BOB, 100e18) (succeeds, allowance 0), ALICE's approve(BOB, 50e18) lands, BOB calls transferFrom(ALICE, BOB, 50e18). Expected by ALICE: BOB can take at most 100e18. Actual: BOB holds 150e18. Shown by test/scratch/EconomicsInvariants.t.sol::test_approveRaceLetsSpenderSpendOldPlusNew (passes on this tree, i.e. the race is reproducible).","severity":"info","snippet":"contract PaperclashToken is ERC20 {","title":"Standard ERC-20 approve race: a spender can spend the old and the new allowance when the owner lowers it (no increase/decreaseAllowance or permit)"}],"hash":"5293f339b71b5297c0459c3cc9cfc9149819ee7c305cb6b250dbb27c0d83e014","nodeId":"20671e5e-b655-4717-8407-f1bf035e3dc2","outcome":"completed","summary":"Review complete. The findings file is valid JSON with both snippets matching the tree, and the working tree reports no tracked changes (the findings file and `test/scratch/` are ignored by git).\n\n**Outcome: no exploitable defect in the economics area.** The token is OpenZeppelin ERC20 v5.4.0 with a single constructor mint of 1e27 units to `msg.sender`, and nothing else.\n\nWhat I checked, across the Economic Security, Invariant and Flow Gap passes:\n\n- **Dependency integrity.** All five vendored OpenZeppelin files hash identically to the upstream v5.4.0 tag, so no fee, blacklist or pause logic entered through the library.\n- **Conservation and exactness.** A scratch StdInvariant run over six actors (factory, distributor, pool manager, requester, two holders) never broke sum of balances equal to total supply. Every launch flow moves exactly the requested amount, and the 10/80/10 split leaves the factory at exactly zero.\n- **Supply immutability.** The compiled ABI has only `approve`, `transfer` and `transferFrom` as state-changing functions, no fallback or receive, no owner. Nothing can mint, burn, freeze or seize after deployment.\n- **Flow Gap seams.** The token makes no external calls and has no hooks, so there is no periphery seam to cross. Constructor arguments are empty and the manifest supply figure matches the constant.\n- **Boundaries.** Whole-supply transfer in one call succeeds, one wei more reverts, self-transfer nets to zero, infinite allowance is not decremented.\n\nTwo info-level notes were recorded, each with a concrete reproduction, neither a defect in the deployed state:\n\n1. `decimals()` returns the inherited hard-coded 18 and never reads the `DECIMALS` constant that sizes `TOTAL_SUPPLY`. They agree today; a one-line override would bind them.\n2. The standard ERC-20 approve race applies, since OpenZeppelin v5 dropped `increaseAllowance`/`decreaseAllowance` and no permit was added. Reproduced in the scratch test.\n\nCoverage: all three listed entry points are marked `holds`, plus six invariant and dependency rows. Nothing in my area was left unreached. The aderyn large-literal lead on line 28 is the intended supply constant and was not promoted.","treeHash":null,"usage":{"cachedInputTokens":580813,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":13502,"runtime":"claude","turns":23,"wallClockMs":235736}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"a5c5e95a2ed07117","findings":[{"citation":"resolved","description":"Merged duplicate: audit_economics (id 639041d7...) and audit_permissions (id 6b7b156a...) report the same root cause. PaperclashToken inherits OpenZeppelin v5.4.0 ERC20 unmodified; I re-hashed the five vendored files (ERC20.sol, IERC20.sol, IERC20Metadata.sol, Context.sol, draft-IERC6093.sol) against raw.githubusercontent.com tag v5.4.0 and all five are byte-identical. approve() calls _approve which writes `_allowances[owner][spender] = value` unconditionally (lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol:280), while transferFrom decrements through _spendAllowance (ERC20.sol:294-304). So a holder who reduces a non-zero allowance in one approve call can be front-run by the approved spender, who pulls the old amount before the reduction lands and the new amount after. OZ v5 deliberately ships no increaseAllowance/decreaseAllowance and the token adds no permit. This is the ERC-20 semantics the brief asked for, exploitable only by an address the holder itself approved, and only while the holder lowers a non-zero allowance; it is not a privilege bypass and no funds are at risk in any launch flow (factory, distributor, PoolManager do not rely on allowance reduction). Severity stays info: a documented trust assumption on spenders, not a defect to fix. Optional additive mitigation for the author: document that holders should approve(spender, 0) first and confirm it landed, or add increaseAllowance/decreaseAllowance; either widens the agreed ABI and is the requester's call.","line":14,"path":"src/PaperclashToken.sol","reproduction":"Reproduced with test/scratch/JudgeRepro.t.sol::test_approveRaceOldPlusNew (passes on this tree, i.e. the race happens). State: FACTORY deploys the token (holds 1e27) and transfers 1000e18 to ALICE. (1) ALICE approve(BOB, 100e18). (2) ALICE submits approve(BOB, 50e18) to reduce. (3) BOB front-runs with transferFrom(ALICE, BOB, 100e18): succeeds, allowance 0. (4) ALICE's approve(BOB, 50e18) lands and overwrites the allowance to 50e18. (5) BOB transferFrom(ALICE, BOB, 50e18): succeeds. Expected by ALICE: BOB can take at most 100e18 in total. Actual: balanceOf(BOB) == 150e18, balanceOf(ALICE) == 850e18.","severity":"info","snippet":"contract PaperclashToken is ERC20 {","title":"Standard ERC-20 approve race: a spender can spend the old and the new allowance when the owner lowers it in one step (merged from audit_economics and audit_permissions)"},{"citation":"resolved","description":"Kept from audit_economics (id ddfb1298...) at info because it reproduces as a coupling gap, not as a deployed defect. TOTAL_SUPPLY on line 28 is `1_000_000_000 * 10 ** uint256(DECIMALS)`, but the ERC-20-visible decimals() comes from lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol:77-79 (`return 18;`) and nothing in the token overrides it. The protected floor's test_decimalsMatchTheManifest compares decimals(), and the manifest states decimals 18 and totalSupply 1000000000000000000000000000, so the deployed state is correct: decimals() == 18, DECIMALS == 18, totalSupply == 1e9 * 10**decimals(). The only risk is a later edit of DECIMALS alone silently changing the minted supply while decimals() stays 18. Minimal behaviour-preserving fix: `function decimals() public pure override returns (uint8) { return DECIMALS; }`. No funds at risk; no action required for this launch. The aderyn large-numeric-literal lead on line 28 is the same expression and is exactly the supply the brief requires, so it is not a defect.","line":25,"path":"src/PaperclashToken.sol","reproduction":"test/scratch/JudgeRepro.t.sol::test_supplyAndDecimals passes on this tree: deploy PaperclashToken from FACTORY; decimals() returns 18, DECIMALS() returns 18, TOTAL_SUPPLY() and totalSupply() return 1000000000000000000000000000 == 1e9 * 10**decimals(), balanceOf(FACTORY) equals the whole supply. The gap is structural: grep the token for `decimals(` finds no override, so the value returned by decimals() is OZ ERC20.sol line 78, not src/PaperclashToken.sol line 25. Expected and actual agree today; the finding records that nothing in the code enforces the agreement.","severity":"info","snippet":"    uint8 public constant DECIMALS = 18;","title":"decimals() is inherited from OpenZeppelin (hard-coded 18) and is not bound to the DECIMALS constant that sizes TOTAL_SUPPLY; they agree today only by convention"}],"hash":"67769399d2726d20d86124213fe8d372187f9af013bd073c5013e01b5e119f4c","nodeId":"8e5349b6-b756-45ae-b19b-04bd5c121e79","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds the result. No tracked file was changed.\n\n**Outcome:** no defect in the Paperclash token. The three specialist findings were all reproduced and reduced to two info notes.\n\n- **Merged** the approve-race reports from the economics and permissions specialists into one info finding. The race reproduces exactly as described in my scratch test. It is the inherent ERC-20 approve semantics of unmodified OpenZeppelin v5.4.0, exploitable only by a spender the holder already approved, so it stays info as a documented trust assumption.\n- **Kept** the decimals coupling note at info. The inherited `decimals()` returns 18 from OpenZeppelin, and the constant that sizes the supply is 18 by convention. Deployed state is correct, so no action is required for this launch.\n- **Dropped** the aderyn large-literal lead. The literal is exactly the required supply.\n\n**What I verified myself:**\n\n- The five vendored OpenZeppelin files hash byte-identical to the upstream v5.4.0 tag.\n- The constructor takes no arguments and mints the whole supply to the deployer. The ABI exposes no mint, owner, pause or burnFrom path.\n- Creation and runtime bytecode are far under the CREATE2 deployment limits, and the manifest's empty constructorArgs, supply, decimals, name length and field types are all valid.\n- The repository's 45 existing tests and my 3 scratch tests pass.\n\n**Coverage:** all three entry points answered as holds, plus three invariant rows. No proof files were needed since nothing reached high severity.","treeHash":null,"usage":{"cachedInputTokens":469941,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":9266,"runtime":"claude","turns":12,"wallClockMs":235207}},{"artifacts":[],"attempt":1,"bundleHash":"e227fab6dde3aa5ca94b35f72672a17cbdc39c5103e2a4c811ca5431c45bfba7","device":"a11137177fc72d8b","findings":[],"hash":"6f4b88758542c5cf568dac8faf89f274ee21abfe9d74996ad2746e51d789a81e","nodeId":"2b8087d6-38e9-4443-a5be-b8707b53714b","outcome":"completed","summary":"The Paperclash token project is complete, committed, and verified locally.\n\n**What was built**\n\n- `src/PaperclashToken.sol`: `PaperclashToken`, OpenZeppelin ERC20 v5.4.0 with name Paperclash, symbol PAPER, 18 decimals. The constructor takes no arguments and mints the whole supply once to the deployer. No owner, mint, pause, blacklist, burn-from, tax, upgrade path or external call.\n- `foundry.toml`: solc pinned to 0.8.26, optimizer on, `bytecode_hash = \"none\"`, ffi off, no fs permissions, remappings inline.\n- `lib/`: forge-std v1.11.0 and the five OpenZeppelin ERC20 files vendored as plain files with licenses. No submodules.\n- `script/DeployPaperclash.s.sol`: reviewable reference deployment. Its deploy function reads no environment and is tested directly.\n- `test/PaperclashToken.t.sol`: 31 tests covering metadata, supply, success and failure paths for transfer, approve and transferFrom, exact launch flows through a factory stub, every mint and privileged selector the launch floor probes, bytecode scan for DELEGATECALL, CALLCODE and SELFDESTRUCT, and four fuzz tests for conservation and allowance semantics.\n- `README.md`: assumptions, launch parameters, \"After launch\" (nothing to configure), operational responsibilities, security notes, and the manifest values the manifest step needs.\n\n**Verification**\n\n| Check | Result |\n| --- | --- |\n| forge build | passes on solc 0.8.26 |\n| forge test with the verifier's fuzz seed | 31 passed, 0 failed |\n| forge fmt --check | clean |\n\nSlither and Mythril were not available on this machine and were not run. The code avoids all six rejecting detectors by construction.\n\n**Committed** as one commit on main containing only the project paths above. The supply total for the manifest is 1000000000000000000000000000 minor units, and the token constructor takes no arguments.","treeHash":"d741e8abd5e008f856146ea0d97c287f633d8272","usage":{"cachedInputTokens":444077,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":20449,"runtime":"claude","turns":19,"wallClockMs":292982}},{"artifacts":[],"attempt":1,"bundleHash":"7d499abe8fd311270edb656c14a8134b07f3a67dbba065cc02816aa134e41ec4","device":"1a7606be97f168d4","findings":[],"hash":"cc89295c8c35ac56d06acdd3b92fd64bc57e609b32929beff1e0520d0643bba3","nodeId":"09cc94dc-57aa-4a5e-bc9c-d0e00d3dc437","outcome":"completed","summary":"Done. `launch.json` is written and is the only file changed.\n\n**What the manifest says**\n- kind `custom_token`, token contract `PaperclashToken`, name Paperclash, symbol PAPER, 18 decimals.\n- Empty constructorArgs. The accepted constructor takes no parameters, confirmed against the compiled ABI.\n- totalSupply is 1,000,000,000 times 10^18 as a decimal string, exactly what the constructor mints to msg.sender.\n- No application contracts, matching the accepted tree, which contains only the token.\n- pool and economics copied verbatim from the launch terms: IMD pair address, fee 12500, tick spacing 60, the one-to-one provenance price, and the requester's economics object.\n- notes describe the token's fixed supply and lack of privileged functions, at about 1,100 characters.\n\n**Checks run**\n- `forge build` compiled cleanly with solc 0.8.26.\n- `forge test` with the verifier's fuzz seed passed all 31 tests.\n- A scratch script checked the manifest's keys, types, lowercase addresses, name length, notes length, and that constructorArgs length matches the ABI's constructor parameter count.\n- `git status` shows only the new launch.json as untracked. No other file was touched.","treeHash":"57418c36adcee8a7897d701aab5b3ef89714fb22","usage":{"cachedInputTokens":172217,"inputTokens":162,"model":"claude-fable-5-1","outputTokens":3421,"runtime":"claude","turns":10,"wallClockMs":70904}}],"verification":[{"checks":[{"durationMs":1751,"exitCode":0,"name":"build","output":"Compiling 30 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.65s\nCompiler run successful!\n","passed":true},{"durationMs":8485,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 13 tests for test/PaperclashToken.edges.t.sol:PaperclashTokenEdgesTest\n[PASS] testFuzz_approveSetsExactly(address,address,uint256) (runs: 1000, μ: 72052, ~: 72403)\nLogs:\n  Bound result 1022824131562125040188719996313938727834059813348\n  Bound result 519741159760164846930952527675239914933264518165\n\n[PASS] testFuzz_strangerCannotPull(address,uint256) (runs: 1000, μ: 44897, ~: 44680)\nLogs:\n  Bound result 53591\n  Bound result 984089564973339212406267137\n\n[PASS] test_allowanceIsSpentExactlyThenExhausted() (gas: 189156)\n[PASS] test_approveOverwritesRatherThanAdds() (gas: 121029)\n[PASS] test_infiniteAllowanceSpendEmitsNoApproval() (gas: 115697)\n[PASS] test_revokedAllowanceBlocksPull() (gas: 105879)\n[PASS] test_selfTransferFromNeedsAllowance() (gas: 145930)\n[PASS] test_transferFromToZeroAddressReverts() (gas: 95792)\n[PASS] test_transferFromZeroAddressReverts() (gas: 33472)\n[PASS] test_transferMaxUintReverts() (gas: 37607)\n[PASS] test_transferWholeSupplyThenNothingLeft() (gas: 98610)\n[PASS] test_zeroAmountApproveEmits() (gas: 39983)\n[PASS] test_zeroAmountTransferFromWithoutAllowanceSucceeds() (gas: 50657)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 16.26ms (30.57ms CPU time)\n\nRan 31 tests for test/PaperclashToken.t.sol:PaperclashTokenTest\n[PASS] testFuzz_multiHopTransfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 236797, ~: 239777)\nLogs:\n  Bound result 906971194791666476031025333\n  Bound result 35782936241\n  Bound result 10328525801\n\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 97224, ~: 97440)\nLogs:\n  Bound result 999999999\n  Bound result 999999999999999999000056978\n\n[PASS] testFuzz_transferConservesSupplyAndIsExact(address,uint256) (runs: 256, μ: 99581, ~: 99860)\nLogs:\n  Bound result 742735742302089759986220864\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256,uint256) (runs: 256, μ: 177950, ~: 168212)\nLogs:\n  Bound result 479984213560378244386088978\n  Bound result 496550907227495554422257141\n  Bound result 154436\n\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 60012)\n[PASS] test_approveToZeroAddressReverts() (gas: 30803)\n[PASS] test_constructorEmitsSingleMintTransfer() (gas: 14174)\n[PASS] test_contractDeployerThroughCreate2HoldsSupply() (gas: 263161)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1566555)\n[PASS] test_deployerCannotTransferFromHolderWithoutApproval() (gas: 89817)\n[PASS] test_launchDistributionArrivesWhole() (gas: 498117)\n[PASS] test_metadata() (gas: 62038)\n[PASS] test_noMintOrAdminSelectorIncreasesSupply() (gas: 637758)\n[PASS] test_noOwnerAccessor() (gas: 26692)\n[PASS] test_noPrivilegedSelectorMovesOrFreezesHolder() (gas: 443910)\n[PASS] test_rejectsEtherAndUnknownCalls() (gas: 58147)\n[PASS] test_roundTripThroughPoolPreservesBalances() (gas: 172845)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1233454)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 19239)\n[PASS] test_transferFromAboveAllowanceReverts() (gas: 133070)\n[PASS] test_transferFromAboveBalanceRevertsEvenWithAllowance() (gas: 138645)\n[PASS] test_transferFromInfiniteAllowanceIsNotDecremented() (gas: 168256)\n[PASS] test_transferFromWithinAllowance() (gas: 191280)\n[PASS] test_transferFromWithoutAllowanceReverts() (gas: 89830)\n[PASS] test_transferMovesExactAmount() (gas: 80119)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 33140)\n[PASS] test_transferRevertsWhenExceedingBalanceByOne() (gas: 33584)\n[PASS] test_transferToSelfKeepsBalance() (gas: 38095)\n[PASS] test_transferToZeroAddressReverts() (gas: 30730)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47568)\n[PASS] test_wholeSupplyMintedToDeployerOnce() (gas: 23099)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 22.04ms (85.45ms CPU time)\n\nRan 1 test for test/PaperclashToken.invariant.t.sol:PaperclashTokenInvariantTest\n[PASS]\nPaperclashTokenInvariantTest invariants:\n[PASS] invariant_allowancesMatchModel\n[PASS] invariant_balancesMatchModel\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_metadataNeverChanges\n[PASS] invariant_supplyIsFixed\n PaperclashTokenInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+----------------------------+-------+---------+----------╮\n| Contract          | Selector                   | Calls | Reverts | Discards |\n+=============================================================================+\n| PaperclashHandler | approve                    | 1810  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | approveZeroSpender         | 1837  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | strangerPull               | 1821  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transfer                   | 1816  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transferFrom               | 1748  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transferFromAboveAllowance | 1846  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transferFromAboveBalance   | 1846  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transferToZero             | 1803  | 0       | 0        |\n|-------------------+----------------------------+-------+---------+----------|\n| PaperclashHandler | transferTooMuch            | 1857  | 0       | 0        |\n╰-------------------+----------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 489\n  Bound result 3\n  Bound result 508\n  Bound result 605149265444149566044300293\n  Bound result 0\n  Bound result 3204908883108482141123781889549788855866151942964\n  Bound result 2714384308\n  Bound result 4288775753\n  Bound result 0\n  Bound result 411\n  Bound result 2531\n  Bound result 0\n  Bound result 0\n  Bound result 7739\n  Bound result 0\n  Bound result 24256\n  Bound result 53591\n  Bound result 60000000000000000000\n  Bound result 242\n  Bound result 0\n  Bound result 2\n  Bound result 175191314079536175318898748515\n  Bound result 0\n  Bound result 0\n  Bound result 248139606204642164212576801912114474825768741665421582655662\n  Bound result 11000000000000000000\n  Bound result 0\n  Bound result 36865\n  Bound result 0\n  Bound result 0\n  Bound result 734\n  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129639935\n  Bound result 2267\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 6648\n  Bound result 3966\n  Bound result 0\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n  Bound result 0\n  Bound result 2827\n  Bound result 3504\n  Bound result 0\n  Bound result 1000000000000000000\n  Bound result 36300426954451577246607677074485562344127344681139728103677340726497384595467\n  Bound result 7000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 4620\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.36s (8.35s CPU time)\n\nRan 3 test suites in 8.36s (8.40s CPU time): 45 tests passed, 0 failed, 0 skipped (45 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PaperclashToken.approve(address,uint256)\",\"PaperclashToken.transfer(address,uint256)\",\"PaperclashToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":7,\"README.md\":127,\"foundry.toml\":27,\"script/DeployPaperclash.s.sol\":26,\"src/PaperclashToken.sol\":35,\"test/PaperclashToken.edges.t.sol\":163,\"test/PaperclashToken.invariant.t.sol\":241,\"test/PaperclashToken.t.sol\":456},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"4b407f3e8c9cb49a343bd9f6fe6fc3a122c39d18e7f24d0a5bf483ea88362630","verifiedTreeHash":"4c3b4a7b32e880c1447080dafa11fdfaa1887845","verifierVersion":"0.1.0+260efc41"},{"checks":[{"durationMs":1240,"exitCode":0,"name":"build","output":"Compiling 28 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.13s\nCompiler run successful!\n","passed":true},{"durationMs":147,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 31 tests for test/PaperclashToken.t.sol:PaperclashTokenTest\n[PASS] testFuzz_multiHopTransfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 236338, ~: 239777)\nLogs:\n  Bound result 1226622913\n  Bound result 24256\n  Bound result 13600\n\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 97132, ~: 97429)\nLogs:\n  Bound result 999999999\n  Bound result 1000000000000000000000000000\n\n[PASS] testFuzz_transferConservesSupplyAndIsExact(address,uint256) (runs: 256, μ: 99576, ~: 99848)\nLogs:\n  Bound result 8000\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256,uint256) (runs: 256, μ: 177758, ~: 168212)\nLogs:\n  Bound result 906971194791666476031025333\n  Bound result 35782936241\n  Bound result 184668593036735362316908678\n\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 60012)\n[PASS] test_approveToZeroAddressReverts() (gas: 30803)\n[PASS] test_constructorEmitsSingleMintTransfer() (gas: 14174)\n[PASS] test_contractDeployerThroughCreate2HoldsSupply() (gas: 263161)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1566555)\n[PASS] test_deployerCannotTransferFromHolderWithoutApproval() (gas: 89817)\n[PASS] test_launchDistributionArrivesWhole() (gas: 498117)\n[PASS] test_metadata() (gas: 62038)\n[PASS] test_noMintOrAdminSelectorIncreasesSupply() (gas: 637758)\n[PASS] test_noOwnerAccessor() (gas: 26692)\n[PASS] test_noPrivilegedSelectorMovesOrFreezesHolder() (gas: 443910)\n[PASS] test_rejectsEtherAndUnknownCalls() (gas: 58147)\n[PASS] test_roundTripThroughPoolPreservesBalances() (gas: 172845)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1233454)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 19239)\n[PASS] test_transferFromAboveAllowanceReverts() (gas: 133070)\n[PASS] test_transferFromAboveBalanceRevertsEvenWithAllowance() (gas: 138645)\n[PASS] test_transferFromInfiniteAllowanceIsNotDecremented() (gas: 168256)\n[PASS] test_transferFromWithinAllowance() (gas: 191280)\n[PASS] test_transferFromWithoutAllowanceReverts() (gas: 89830)\n[PASS] test_transferMovesExactAmount() (gas: 80119)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 33140)\n[PASS] test_transferRevertsWhenExceedingBalanceByOne() (gas: 33584)\n[PASS] test_transferToSelfKeepsBalance() (gas: 38095)\n[PASS] test_transferToZeroAddressReverts() (gas: 30730)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47568)\n[PASS] test_wholeSupplyMintedToDeployerOnce() (gas: 23099)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 17.01ms (64.47ms CPU time)\n\nRan 1 test suite in 18.09ms (17.01ms CPU time): 31 tests passed, 0 failed, 0 skipped (31 total tests)\n","passed":true},{"durationMs":41,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PaperclashToken.approve(address,uint256)\",\"PaperclashToken.transfer(address,uint256)\",\"PaperclashToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":7,\"README.md\":127,\"foundry.toml\":27,\"script/DeployPaperclash.s.sol\":26,\"src/PaperclashToken.sol\":35,\"test/PaperclashToken.t.sol\":456},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":778,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":403,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/PaperclashToken.sol:28: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6f4b88758542c5cf568dac8faf89f274ee21abfe9d74996ad2746e51d789a81e","verifiedTreeHash":"d741e8abd5e008f856146ea0d97c287f633d8272","verifierVersion":"0.1.0+260efc41"},{"checks":[{"durationMs":1039,"exitCode":0,"name":"build","output":"Compiling 28 files with Solc 0.8.26\nSolc 0.8.26 finished in 950.01ms\nCompiler run successful!\n","passed":true},{"durationMs":117,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 31 tests for test/PaperclashToken.t.sol:PaperclashTokenTest\n[PASS] testFuzz_multiHopTransfersConserveSupply(uint256,uint256,uint256) (runs: 256, μ: 236338, ~: 239777)\nLogs:\n  Bound result 1226622913\n  Bound result 24256\n  Bound result 13600\n\n[PASS] testFuzz_transferAboveBalanceReverts(uint256,uint256) (runs: 256, μ: 97132, ~: 97429)\nLogs:\n  Bound result 999999999\n  Bound result 1000000000000000000000000000\n\n[PASS] testFuzz_transferConservesSupplyAndIsExact(address,uint256) (runs: 256, μ: 99576, ~: 99848)\nLogs:\n  Bound result 10887\n\n[PASS] testFuzz_transferFromRespectsAllowance(uint256,uint256,uint256) (runs: 256, μ: 177758, ~: 168212)\nLogs:\n  Bound result 1226622913\n  Bound result 24256\n  Bound result 13600\n\n[PASS] test_approveSetsAllowanceAndEmits() (gas: 60012)\n[PASS] test_approveToZeroAddressReverts() (gas: 30803)\n[PASS] test_constructorEmitsSingleMintTransfer() (gas: 14174)\n[PASS] test_contractDeployerThroughCreate2HoldsSupply() (gas: 263161)\n[PASS] test_deployScriptFunctionMintsToCaller() (gas: 1566555)\n[PASS] test_deployerCannotTransferFromHolderWithoutApproval() (gas: 89817)\n[PASS] test_launchDistributionArrivesWhole() (gas: 498117)\n[PASS] test_metadata() (gas: 62038)\n[PASS] test_noMintOrAdminSelectorIncreasesSupply() (gas: 637758)\n[PASS] test_noOwnerAccessor() (gas: 26692)\n[PASS] test_noPrivilegedSelectorMovesOrFreezesHolder() (gas: 443910)\n[PASS] test_rejectsEtherAndUnknownCalls() (gas: 58147)\n[PASS] test_roundTripThroughPoolPreservesBalances() (gas: 172845)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1233454)\n[PASS] test_supplyIsOneBillionWithEighteenDecimals() (gas: 19239)\n[PASS] test_transferFromAboveAllowanceReverts() (gas: 133070)\n[PASS] test_transferFromAboveBalanceRevertsEvenWithAllowance() (gas: 138645)\n[PASS] test_transferFromInfiniteAllowanceIsNotDecremented() (gas: 168256)\n[PASS] test_transferFromWithinAllowance() (gas: 191280)\n[PASS] test_transferFromWithoutAllowanceReverts() (gas: 89830)\n[PASS] test_transferMovesExactAmount() (gas: 80119)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 33140)\n[PASS] test_transferRevertsWhenExceedingBalanceByOne() (gas: 33584)\n[PASS] test_transferToSelfKeepsBalance() (gas: 38095)\n[PASS] test_transferToZeroAddressReverts() (gas: 30730)\n[PASS] test_transferZeroAmountSucceeds() (gas: 47568)\n[PASS] test_wholeSupplyMintedToDeployerOnce() (gas: 23099)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 13.30ms (48.62ms CPU time)\n\nRan 1 test suite in 14.00ms (13.30ms CPU time): 31 tests passed, 0 failed, 0 skipped (31 total tests)\n","passed":true},{"durationMs":37,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PaperclashToken.approve(address,uint256)\",\"PaperclashToken.transfer(address,uint256)\",\"PaperclashToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":7,\"README.md\":127,\"foundry.toml\":27,\"launch.json\":24,\"script/DeployPaperclash.s.sol\":26,\"src/PaperclashToken.sol\":35,\"test/PaperclashToken.t.sol\":456},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"cc89295c8c35ac56d06acdd3b92fd64bc57e609b32929beff1e0520d0643bba3","verifiedTreeHash":"57418c36adcee8a7897d701aab5b3ef89714fb22","verifierVersion":"0.1.0+260efc41"}]}