{"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":"73c0d649-5a86-4610-b860-a3b27164069e","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"b0f6c9d3f53eefd237ee8f3e944827e104eeecfd37170858214b25e1fd582aed","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":"5b4f0e60d44865ee03aaed4177ab3f1cb948cf568c3486b0cac21f4f8913f080","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":"bdcdb7deadf725d0cfbd6b106f81a5591e67c0a471f3bc64167a6f2674de4e8e","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":"4b2343d4a8eb1cb544e55668ef7254a53e9b26831641080c489d213480a0383d","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":"341a9ef30ed650bc867e9f2a10b95c509ec823836bd491b0cced66ad484dfe12","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":"21d7546c4e970b2c9e24bdabe9fe3547ab9532219addcec70c482d6bf6a8ab1b","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"15b04fc8f60521936b9e2b37c09a804685ec689fc98cd5b04510d986d3106a15","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"15b04fc8f60521936b9e2b37c09a804685ec689fc98cd5b04510d986d3106a15","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"735ae106929417c54ae478f6c96d1e59fae675d268b7a0161959b56aed48789e","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"2b75041915a27b7402cecd6e9d54da634dd0e2bb8724a9d1aef88b931476d9da","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: Sworn (SWORN).\nToken name: Sworn\nToken symbol: SWORN\nToken supply: 1,000,000,000 with 18 decimals, all minted once to the deployer in the constructor.","parentJobId":null,"planHash":"da0bf9a4c5b163459ae9e874ccf38ef5b8fac4eb57347c985f4305b7ea271adb","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"73c0d649-5a86-4610-b860-a3b27164069e","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2840-sworn"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51530","feedbackHash":"115a909d9c2d7bb1478d5fac42eeebe28ac29f27071f187fb09039cc22dafdd6","nodeKey":"audit_economics","submissionHash":"b0f6c9d3f53eefd237ee8f3e944827e104eeecfd37170858214b25e1fd582aed","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52130","feedbackHash":"7335f18d4d05c25215864ef3da920719006e5f93da5c45c624e9b327e5aa29be","nodeKey":"audit_flow","submissionHash":"5b4f0e60d44865ee03aaed4177ab3f1cb948cf568c3486b0cac21f4f8913f080","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53927","feedbackHash":"162457c58a268d6927fc6c655b89d3f6537d45591db501a658aeb5b97a4b351a","nodeKey":"audit_judge","submissionHash":"bdcdb7deadf725d0cfbd6b106f81a5591e67c0a471f3bc64167a6f2674de4e8e","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50939","feedbackHash":"728e04546fa9b0a2fbc5128992404f079ad2652a83b73a27d60519f5629ef436","nodeKey":"audit_math","submissionHash":"4b2343d4a8eb1cb544e55668ef7254a53e9b26831641080c489d213480a0383d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51082","feedbackHash":"2ee8da74b61e7e3f79ca11251f675c209d64fb3d36e7da49ab8fe86153cafeff","nodeKey":"audit_permissions","submissionHash":"341a9ef30ed650bc867e9f2a10b95c509ec823836bd491b0cced66ad484dfe12","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52677","feedbackHash":"4c9f55f538939c0dba1e8e566aa0622f8a578d918ce29386d70dda656949268c","nodeKey":"build_contract_project","submissionHash":"21d7546c4e970b2c9e24bdabe9fe3547ab9532219addcec70c482d6bf6a8ab1b","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52287","feedbackHash":"a59bd4d1b90c569e6c3f802b4034167f1caae65b91e8efc27c5b5908ea020c89","nodeKey":"manifest","submissionHash":"735ae106929417c54ae478f6c96d1e59fae675d268b7a0161959b56aed48789e","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51876","feedbackHash":"277e4a0b9542c2d3d0efb5957fff5bb880b4fb3038a73240f74d232157352813","nodeKey":"write_foundry_tests","submissionHash":"2b75041915a27b7402cecd6e9d54da634dd0e2bb8724a9d1aef88b931476d9da","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"6a0d22028419f5fc2e3b9e8ffe60f1955de4f9d86e06ca90e319bbde812f716e","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"2f4ca87e14fb207f90bebc3329024383b9dabfee0b0eb77777f1945528c47a8e","device":"e49531c471ac7158","findings":[],"hash":"21d7546c4e970b2c9e24bdabe9fe3547ab9532219addcec70c482d6bf6a8ab1b","nodeId":"d8b4ff48-d06e-43c3-bee3-b391943d73b6","outcome":"completed","summary":"I've built the Sworn (SWORN) token. `forge build`, `forge fmt --check` and `forge test` all pass, including with the verifier's fuzz seed, and it's committed as `59cc1d2`. I couldn't run the two protected launch tests here, because they need files only the verifier has (the pool manager code and the owner checks). The token was written to meet what they check.\n\n**The token** (`src/SwornToken.sol`, `contract SwornToken`)\n- It's a standard ERC-20 named \"Sworn\" with symbol \"SWORN\" and 18 decimals.\n- The constructor mints all 1,000,000,000 tokens once, to whoever deploys it (in the launch, IMD's factory). The supply can never change after that.\n- It takes no constructor arguments.\n- There is no owner, mint, burn, pause, blacklist, transfer fee or upgrade path. Every transfer moves exactly the amount it says, so the launch's payouts, pool seed and trades all work without exemptions.\n- It doesn't call other contracts and uses no libraries, so there's nothing to link before deploying.\n\n**Tests** (`test/SwornToken.t.sol`): 18 tests, all passing. They check the name, symbol, decimals and supply; that the whole supply goes to the deployer; transfers and approvals; each failure case (not enough balance or allowance, sending to or approving the zero address); that unlimited approvals aren't used up; that the deploy script's `deploy()` works; that admin-style calls like mint, pause or blacklist don't exist; and two fuzz tests showing the total supply never changes.\n\n**Setup**\n- `foundry.toml` pins solc 0.8.26 with `bytecode_hash = \"none\"` and the optimizer on, and does not enable ffi or file access.\n- forge-std v1.9.7 is copied into `lib/forge-std` as ordinary files, not a submodule.\n- `script/DeploySworn.s.sol` is a reference deploy script for local review only; it reads no environment variables. The real launch goes through IMD's factory.\n\n**README:** it lists the token's details, assumptions and deployment parameters (none), and says there are no admin roles or \"After launch\" settings to manage. It also notes that tokens sent to the wrong address can't be recovered, and that passing tests are not a security audit.\n\nGit had no author set on this machine, so I made the commit under your name and email (Johan Struber, johanstruber@protonmail.com). I did not write a `launch.json`; that's left to the manifest step.","treeHash":"18eafb5004ad71411827b0ade758178bd36ca209","usage":{"cachedInputTokens":287316,"inputTokens":18,"model":"claude-opus-5-5","outputTokens":8310,"runtime":"claude","turns":9,"wallClockMs":80995}},{"artifacts":[],"attempt":3,"bundleHash":"af8b70b5c6d6902354068e825a5dc9da2fac0c30dac9ce32ff741d5e871e64d4","device":"d03fc84904b54d9e","findings":[{"description":"transferFrom does not reject from == address(0). With value 0 the allowance check (0 < 0 is false) and the balance check (0 < 0 is false) both pass, so any caller can make the token emit Transfer(address(0), to, 0) at any time after deployment. Supply and balances do not change, but indexers and explorers that treat Transfer events from the zero address as mints will log spurious post-launch mint events for a token whose supply is supposed to be fixed. OpenZeppelin's ERC20 rejects this with ERC20InvalidSender.","line":47,"path":"src/SwornToken.sol","reproduction":"Deploy SwornToken; from any address (e.g. 0xBEEF) call transferFrom(address(0), 0xBEEF, 0). Expected: revert (no sender is the zero address). Actual: returns true and emits Transfer(0x0, 0xBEEF, 0). totalSupply stays 1e27.","severity":"info","title":"Anyone can emit a zero-value Transfer from address(0), indistinguishable in shape from a mint event"}],"hash":"2b75041915a27b7402cecd6e9d54da634dd0e2bb8724a9d1aef88b931476d9da","nodeId":"196fd1a3-9d51-4f33-b1f7-54f910e9237c","outcome":"completed","summary":"I added tests for the Sworn (SWORN) token. `forge build` and `forge test` pass with the verifier's fuzz seed: 62 tests across 3 suites, 0 failures. I found no high or critical defects; one minor one is reported below.\n\n**Files added** (the existing `test/SwornToken.t.sol` is unchanged):\n\n- **`test/SwornToken.edge.t.sol`** (43 tests):\n  - **Supply:** exactly 1,000,000,000 × 10¹⁸, minted once to the deployer, with exactly one event.\n  - **Rejected calls:** ETH sent to the token, `mint`/`burn`/`burnFrom` and freeze-type calls all fail.\n  - **Bytecode:** the deployed code contains no DELEGATECALL, CALLCODE or SELFDESTRUCT.\n  - **Transfer edge cases:**\n    - sending the whole supply, one wei over it, and `type(uint256).max`;\n    - sending from an empty account;\n    - sending to the zero address (rejected even for 0);\n    - sending to yourself, and to the token contract itself.\n  - **Allowances:**\n    - an approval overwrites the previous one, up or down;\n    - the exact allowance can be spent, in steps, until it hits zero;\n    - an allowance one below the maximum still goes down; the maximum is treated as unlimited and logs no Approval;\n    - when both checks fail, the allowance error comes first.\n  - **Failed calls change nothing:** a failed `transferFrom` leaves both the allowance and the balance as they were.\n  - **Launch flows:** the 10% swarm share reaches the distributor and is claimed with nothing lost; an 80% pool seed by `transferFrom` arrives exact; the deployer (the launch factory) cannot move or freeze anyone else's balance.\n  - **Fuzz tests** (1,000 runs each): random amounts above the balance or allowance always fail, and successful transfers move exactly the amount asked.\n- **`test/SwornToken.invariant.t.sol`**: a handler that makes random sequences of transfers, approvals and `transferFrom` calls among five accounts plus the token's own address, including calls that should fail. It keeps its own record of what every balance and allowance should be. After every step it checks that:\n  - the total supply never changes;\n  - all balances add up to the supply;\n  - every balance and allowance matches the handler's record;\n  - every call succeeded or failed exactly as predicted;\n  - the name, symbol and decimals never change.\n\n  The run settings are in the file (256 runs, 64 calls deep, so 16,384 calls per run, with no unexpected reverts). To check that these tests can actually fail, I ran them against a deliberately broken copy of the token where `transferFrom` doesn't fully reduce the allowance. They failed on the first sequence, as they should.\n\n**Finding** (in `.imd-findings.json`, severity `info`): `transferFrom` doesn't reject `address(0)` as the sender. Anyone can call `transferFrom(address(0), anyone, 0)`; it succeeds and emits `Transfer(0x0, to, 0)`. Explorers and indexers usually read a transfer from the zero address as a new mint, so they may show fake mints on a token whose supply is meant to be fixed. The supply and balances don't change. I confirmed it with a test that expects a revert and fails on the current code. I didn't write any test that treats this behaviour as correct.","treeHash":"5523321d56e35693df2d382be20d21823c0d13be","usage":{"cachedInputTokens":410862,"inputTokens":21,"model":"claude-opus-5-5","outputTokens":19486,"runtime":"claude","turns":12,"wallClockMs":267779}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f47f953f8e35921e","findings":[{"citation":"resolved","description":"Asymmetry between the three sentinel checks: `approve` rejects a zero spender (line 39) and `_transfer` rejects a zero receiver (line 60), but `_transfer` never rejects a zero sender. The only way `from == address(0)` reaches `_transfer` is `transferFrom(address(0), to, value)`; `allowance[address(0)][msg.sender]` is always 0 and `balanceOf[address(0)]` is always 0 (no transfer can credit it), so the call succeeds exactly when `value == 0`. It then emits `Transfer(address(0), to, 0)`, the shape indexers and explorers read as a mint. No balance or supply changes, so there is no loss of funds, no privilege and no launch-flow impact; this is an event-hygiene gap only. The standard OpenZeppelin implementation reverts here with ERC20InvalidSender. A minimal fix that preserves behaviour is `if (from == address(0)) revert InvalidSender(from);` at the top of `_transfer` (or at the top of `transferFrom`), which no legitimate caller can hit.","line":60,"path":"src/SwornToken.sol","reproduction":"State: fresh SwornToken, any caller (e.g. 0xBEEF) with no balance and no allowance. Call: vm.prank(0xBEEF); token.transferFrom(address(0), 0xBEEF, 0). Expected (per OpenZeppelin semantics and the symmetry of the zero-address checks): revert for an invalid sender. Actual: returns true and emits Transfer(from=address(0), to=0xBEEF, value=0); totalSupply and all balances unchanged. Control: transferFrom(address(0), 0xBEEF, 1) reverts with InsufficientAllowance(0xBEEF, 0, 1), so nothing with value can ever be moved from the zero address.","severity":"info","snippet":"        if (to == address(0)) revert InvalidReceiver(to);\n        uint256 fromBalance = balanceOf[from];\n        if (fromBalance < value) revert InsufficientBalance(from, fromBalance, value);","title":"transferFrom accepts address(0) as `from`, letting anyone emit a mint-shaped Transfer(address(0), to, 0) event"}],"hash":"341a9ef30ed650bc867e9f2a10b95c509ec823836bd491b0cced66ad484dfe12","nodeId":"1d48ad8c-2293-4c65-b1ad-f5580546797b","outcome":"completed","summary":"The permissions review of SwornToken is complete. The findings file is written and validated, the scratch directory is removed, and the working tree holds no other changes.\n\n**Outcome.** The token has no permission surface to break. It is a 70-line fixed-supply ERC-20 with no owner, initializer, proxy, mint, burn, pause, blacklist, fee, external call, delegatecall or selfdestruct. The compiled ABI confirms only three state-changing functions, all ordinary ERC-20. Each writes only the caller's own slots or slots the owner explicitly approved. The deployer holds no power over any other holder once the constructor finishes.\n\n**One finding, severity info.** The zero-address sentinel checks are asymmetric. `approve` rejects a zero spender and transfers reject a zero receiver, but nothing rejects a zero sender. Anyone can call `transferFrom(address(0), x, 0)` and it succeeds, emitting a mint-shaped `Transfer(address(0), x, 0)` event. No balance or supply changes, and any nonzero value from the zero address reverts first on allowance, so this is event hygiene only. OpenZeppelin reverts in this case. The minimal fix is a zero-sender revert at the top of the private transfer helper. I verified the behaviour with a scratch Foundry test before reporting it.\n\n**Coverage.** All three listed entry points have rows: `approve` and `transfer` hold, `transferFrom` carries the info finding. I added rows for the constructor, the no-privileged-role invariant, fixed supply, holder-balance protection, the Trust Gap seams, the reference deploy script, and the aderyn large-literal lead, which is a style note on a constant that equals the required supply exactly.\n\n**Not reached.** The protected launch floor test could not be run locally because it depends on v4-core and launch library sources not present in this tree. By inspection the token satisfies it: no constructor arguments, exact supply minted to msg.sender, decimals 18, exact transfers on every flow, no forbidden opcodes.","treeHash":null,"usage":{"cachedInputTokens":488021,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":10344,"runtime":"claude","turns":23,"wallClockMs":169265}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"707624586655cf74","findings":[],"hash":"3c012678dca731430512b749060279a16f7e1565d996fba9747dbc6ae68b4fec","nodeId":"196fd1a3-9d51-4f33-b1f7-54f910e9237c","outcome":"failed","summary":"Claude Code can't use your Claude subscription, usually because a payment is past due · Pay or renew at https://claude.ai/… (if you just paid, try again shortly), or use an Anthropic API key instead","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":1376}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"72b617d4b615473a","findings":[{"citation":"resolved","description":"Boundary x invariant seam (Numerical Gap guide, seam 3: a zero-input fast path bypassing a guarantee the body otherwise keeps). `_transfer` rejects `to == address(0)` but never checks `from`. `transfer` cannot reach the case because msg.sender is never the zero address, but `transferFrom` can: `allowance[address(0)][anyone]` is 0, and a `value` of 0 passes the `current < value` check at line 50 without touching the allowance, then `_transfer(address(0), to, 0)` passes the `fromBalance < value` check at line 62 with 0 < 0 false, and emits `Transfer(address(0), to, 0)` at line 68. ERC-20 convention reserves a Transfer whose `from` is the zero address for minting, and the constructor is the only intended emitter of one (line 30). After deployment any address can emit as many zero-valued mint-shaped events to any recipient as it pays gas for. No balance, allowance or totalSupply changes: the arithmetic is exact and the conservation invariant `sum(balanceOf) == totalSupply == 1e27` holds. The OpenZeppelin v5 reference reverts here with `ERC20InvalidSender(address(0))`; this contract does not. Impact is limited to indexers, explorers and off-chain accounting that treat `Transfer(0x0, X, v)` as a mint of `v` to X: they record a mint of zero, and holder lists built from Transfer recipients can be spammed with zero-balance entries by an unprivileged third party. No funds are at risk, so severity is informational. Minimal fix that preserves intended behaviour: add `if (from == address(0)) revert InvalidSender(from);` in `_transfer` next to the receiver check (or check `from != address(0)` in `transferFrom`). Reproduction verified with a Foundry test under test/scratch (not kept): test_anyoneCanEmitMintShapedTransferFromZeroAddress passes on the current code, showing the call returns true and emits the event.","line":60,"path":"src/SwornToken.sol","reproduction":"State: fresh SwornToken deployed by DEPLOYER (balance 1e27). Call: from any address, e.g. 0xBAD, `token.transferFrom(address(0), 0xB0B, 0)`. Expected (OpenZeppelin v5 semantics / mint convention): revert, because the zero address is not a valid sender and only the constructor may emit a Transfer from address(0). Actual: returns true and emits `Transfer(address(0), 0xB0B, 0)`; totalSupply stays 1e27, balanceOf(0xB0B) stays 0, balanceOf(address(0)) stays 0. With value 1 instead of 0 the call reverts with `InsufficientAllowance(0xBAD, 0, 1)`, so only the zero-value boundary reaches the event.","severity":"info","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"transferFrom(address(0), to, 0) succeeds and lets any caller emit a mint-shaped Transfer(address(0), to, 0) event"}],"hash":"4b2343d4a8eb1cb544e55668ef7254a53e9b26831641080c489d213480a0383d","nodeId":"fa6737bb-b12f-43a2-a66f-49dc637747c1","outcome":"completed","summary":"The math review of the Sworn token is complete. The result is one informational finding and no defects in the arithmetic itself.\n\n**What I reviewed.** The token at `src/SwornToken.sol` is a 70-line fixed-supply ERC-20 with no owner, no mint, and no external calls. Its whole math surface is the compile-time supply constant, two unchecked subtractions, and one unchecked balance addition. I checked it against the Math Precision, Boundary and Numerical Gap guides from the Pashov reference and against the OpenZeppelin reference semantics.\n\n**What holds.**\n- The supply constant equals exactly 1e27 minor units, confirmed with `cast to-wei` and a test assertion. The aderyn \"large numeric literal\" lead is stylistic only.\n- Both unchecked subtractions run only after a strict less-than check reverts first, so neither can wrap.\n- The unchecked balance addition cannot overflow because no mint path exists after the constructor and balances always sum to 1e27. A fuzz test of three-party transfers and a full-supply hop confirm conservation.\n- Max-uint transfers, full-balance self-transfers, zero-value transfers, the infinite-allowance sentinel at exactly max and at max-1, and exact allowance consumption all behave as intended.\n- There is no division, scaling, downcast, payable path or external call, so most guide items have nothing to apply to. Sending ETH to the contract reverts.\n\n**The one finding (info).** Any caller can execute `transferFrom(address(0), to, 0)` successfully. The function checks the receiver for the zero address but never the sender, and a zero value passes both the zero allowance and the zero balance of the zero address. The result is a mint-shaped `Transfer(address(0), to, 0)` event emitted by an unprivileged third party. No balance, allowance or supply changes, so no funds are at risk. Indexers that treat a Transfer from the zero address as a mint would record a zero mint, and holder lists could be spammed. OpenZeppelin v5 reverts in this case. The minimal fix is a sender zero-address check in the internal transfer helper. Reproduction is verified by a scratch Foundry test that passes on the current code.\n\n**Deliverable.** Findings and coverage are in `.imd-findings.json` at the repository root. Coverage marks `approve` and `transfer` as holding, `transferFrom` as carrying finding 1, plus five invariant and boundary rows that hold. The scratch test lives under `test/scratch/` and is not kept. No tracked file was changed. The existing 18-test suite passes, as do my 14 scratch probes.\n\n**Not done.** No proof file was attached because the finding is informational, not critical or high. Nothing in my assigned area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":689596,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":17928,"runtime":"claude","turns":23,"wallClockMs":262776}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"1c29c7c6e4cf57eb","findings":[{"citation":"resolved","description":"_transfer validates the receiver but never the sender, and transferFrom passes a caller-chosen `from` straight into it. With from = address(0) and value = 0, both guards pass: allowance[0x0][caller] is 0 and 0 < 0 is false (line 50), balanceOf[0x0] is 0 and 0 < 0 is false (line 62). Line 68 then emits Transfer(address(0), to, 0). EIP-20 reserves from = 0x0 for token creation, and this contract documents that the supply is minted once, in the constructor, so the log stream can no longer show a single mint: any stranger can add as many mint-shaped logs as they like, naming any `to`. No state changes and no funds move: totalSupply, every balance and every allowance stay the same, and any value of 1 or more from 0x0 reverts because nobody can hold an allowance from 0x0. The harm is limited to off-chain readers that treat from == 0x0 as a mint, such as explorer mint labels and supply or token-safety scanners that look for post-launch mints. Assumption broken: the code assumes `from` is an account that can act, which is true for transfer (msg.sender) but not for transferFrom. Minimal fix: reject from == address(0) in _transfer or transferFrom with a new InvalidSender error, mirroring line 60. Launch flows are unaffected, because none of them use from = 0x0. Not part of this finding: zero-value transferFrom naming a real `from` also needs no allowance, which is the EIP-20 rule that zero-value transfers are normal transfers.","line":60,"path":"src/SwornToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test, Vm} from \"forge-std/Test.sol\";\nimport {SwornToken} from \"src/SwornToken.sol\";\n\n/// Fails today: a stranger can make the token emit a second mint-shaped Transfer(0x0, to, 0).\n/// Passes once transferFrom rejects from == address(0), as _transfer already rejects to == address(0).\ncontract ZeroSenderTest is Test {\n    function test_onlyTheConstructorEmitsTransferFromZero() public {\n        SwornToken token = new SwornToken();\n        address stranger = address(0xBEEF);\n        address victim = address(0xB0B);\n\n        vm.recordLogs();\n        vm.prank(stranger);\n        (bool ok,) = address(token).call(abi.encodeCall(SwornToken.transferFrom, (address(0), victim, 0)));\n        ok;\n\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        uint256 mintShaped;\n        for (uint256 i; i < logs.length; ++i) {\n            if (logs[i].topics[0] == keccak256(\"Transfer(address,address,uint256)\") && logs[i].topics[1] == bytes32(0)) {\n                ++mintShaped;\n            }\n        }\n        assertEq(mintShaped, 0, \"a stranger emitted a mint-shaped Transfer after construction\");\n    }\n}","reproduction":"State: freshly deployed token. Caller: any account with no balance and no allowance, e.g. 0xBEEF. Call: token.transferFrom(address(0), 0xB0B, 0). Expected: revert, so the constructor's log stays the only Transfer from 0x0. Actual: returns true and emits Transfer(0x0, 0xB0B, 0). Running the proof with `forge test --match-path test/scratch/ZeroSender.t.sol` fails on this tree with 'a stranger emitted a mint-shaped Transfer after construction: 1 != 0', and passes on a copy where _transfer rejects from == address(0).","severity":"low","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"Anyone can make the token emit a mint-shaped Transfer(0x0, to, 0) after construction"}],"hash":"5b4f0e60d44865ee03aaed4177ab3f1cb948cf568c3486b0cac21f4f8913f080","nodeId":"108e53e9-38c9-46ef-81b6-d39f4e93576a","outcome":"completed","summary":"The control-flow audit of `SwornToken` found one low-severity defect, and it's recorded in `.imd-findings.json` with 8 coverage rows. No tracked files changed, and I removed my scratch tests and build output.\n\n## Finding: anyone can emit a fake mint log (low)\n- **Location:** `src/SwornToken.sol:60`. `_transfer` checks the receiver but not the sender.\n- **Failing input:** any account can call `transferFrom(address(0), 0xB0B, 0)`. It succeeds and emits `Transfer(0x0, 0xB0B, 0)`, which looks like a mint.\n- **Impact:** no balance, allowance or supply changes, and no funds are at risk. Only off-chain readers that treat a transfer from `0x0` as a mint are misled, such as explorers or supply scanners.\n- **Fix:** reject `from == address(0)`, the same way line 60 rejects a zero receiver.\n- **Proof:** the included Foundry test fails on this code and passes on a temporary copy with that check added (the copy reused `InvalidReceiver`; the finding recommends a new `InvalidSender` error).\n\n## Coverage\n\n| Target | Verdict | Basis |\n|---|---|---|\n| `approve` | holds | Writes only the caller's own allowance; zero spender and malformed addresses revert. |\n| `transfer` | holds | Self-transfer, full balance, short calldata and attached ETH all behave correctly. |\n| `transferFrom` | finding 1 | Otherwise correct: allowance key, max-allowance handling and reverts all hold. |\n| Fixed supply | holds | 256 invariant runs (128,000 calls) passed, and the `unchecked` blocks cannot wrap. |\n| Launch flows | holds | Swarm share, claim, seed, remainder, buy and sell all moved exact amounts. |\n| Runtime bytecode | holds | No external calls, `DELEGATECALL`, `CALLCODE` or `SELFDESTRUCT`. |\n| Single mint | holds | Only the constructor sets the supply. |\n| Deploy script and README | holds | The script is reference-only and the README's claims match the code. |\n\nI went through all three guides (Execution Trace, Periphery, First Principles). Most of their items don't apply here, because the token has no external calls, assembly, oracles or libraries of its own. The aderyn large-literal lead isn't a defect: the value is exactly 10^27.\n\n## What this doesn't cover\n- **Protected floor tests:** they could not run because `src/LaunchLiquidity.sol`, `PoolInitializationGuard` and `HookFlags` aren't supplied. Instead, I ran the compiled token through the current Uniswap `v4-core` main branch in a temporary harness, with ETH and both ERC-20 currency orders.\n- **Limits of that harness:** it used a pool with no hook and my own settlement code, so it doesn't replace the floor tests.\n- **Manifest:** `launch.json` isn't in the tree yet, so it wasn't reviewed.\n- **Project tests:** all 18 pass, but the dead `type(uint256).max` branch in `testFuzz_transferFrom` never runs. That's only a test gap, since `test_infiniteAllowanceNotDecreased` and my own tests cover that behaviour, so I didn't report it.","treeHash":null,"usage":{"cachedInputTokens":543172,"inputTokens":18,"model":"claude-opus-5-5","outputTokens":26554,"runtime":"claude","turns":23,"wallClockMs":271827}},{"artifacts":[],"attempt":1,"bundleHash":"6959cf57a906226ba61c7fdd2d871399993b260d0e62aa32354c73a090ccd3a5","device":"99c6d0bcc495ad61","findings":[],"hash":"735ae106929417c54ae478f6c96d1e59fae675d268b7a0161959b56aed48789e","nodeId":"488ff4fd-9e12-47e4-b83d-8f7ea73a884d","outcome":"completed","summary":"launch.json is written and verified. Only that file changed.\n\n**What the manifest says**\n- Kind custom_token, token contract SwornToken, name Sworn, symbol SWORN, 18 decimals.\n- Empty constructorArgs, matching the accepted no-argument constructor in src/SwornToken.sol.\n- totalSupply in minor units, equal to the constant the constructor mints to msg.sender.\n\n| Field | Value |\n| --- | --- |\n| totalSupply | 1000000000000000000000000000 |\n| notes length | 916 characters |\n\n- No application contracts, since the accepted tree contains only the token.\n- Pool and economics copied verbatim from the launch terms: IMD pair, fee 12500, tick spacing 60, the given initialPrice, and the requester's economics object.\n\n**Checks run**\n- The JSON parses with exactly the schema's six top-level keys and the asserted values.\n- `forge build` compiles cleanly.\n- `forge test` with the verifier's fuzz seed passed all 18 tests.\n- `git status` shows launch.json as the only new or changed path.","treeHash":"1ce59fbe496136ba56b0b7073ad38c61617bf2f6","usage":{"cachedInputTokens":128927,"inputTokens":130,"model":"claude-fable-5-1","outputTokens":3011,"runtime":"claude","turns":10,"wallClockMs":60475}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"911c99a95f538613","findings":[],"hash":"7915a0484517b442ad392f4f7685e1069da59b40e14e7122cde43c91d7635ae2","nodeId":"196fd1a3-9d51-4f33-b1f7-54f910e9237c","outcome":"failed","summary":"API Error: Your account can't receive replies from Claude right now. You can find the next step in the Anthropic Verification Portal: https://portal.anthropic.com/…","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":3027}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"5ded77c3c883b7b0","findings":[{"citation":"resolved","description":"_transfer rejects a zero receiver but not a zero sender. In transferFrom, allowance[address(0)][msg.sender] is 0 and the check `current < value` passes when value == 0, so the call reaches _transfer with from == address(0), passes `fromBalance < value` (0 < 0 is false) and emits Transfer(address(0), to, 0). Under ERC-20 convention a Transfer whose `from` is the zero address is a mint, so any unprivileged account can make the token emit mint-shaped events at will. The reference implementation (OpenZeppelin ERC20._transfer) reverts with ERC20InvalidSender for from == address(0). No balance or totalSupply changes: sum of balances stays 1e27, totalSupply is immutable, and any value > 0 reverts with InsufficientAllowance(spender, 0, value). Impact is limited to off-chain consumers that count or alert on mint events; there is no fund impact and the launch floors (supply exact, flows exact, no privileged hand) are unaffected. Minimal fix that preserves the design: add `if (from == address(0)) revert InvalidSender(from);` at the top of _transfer (or in transferFrom).","line":59,"path":"src/SwornToken.sol","reproduction":"State: fresh SwornToken deployed by 0xFAC7 (holds 1e27). Call, from any address A with no allowance and no balance: token.transferFrom(address(0), A, 0). Expected (OpenZeppelin semantics): revert with an invalid-sender error. Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=A, value=0); balanceOf(A) == 0 and totalSupply() == 1e27 afterwards. Verified in a scratch Foundry test with vm.expectEmit(Transfer(address(0), A, 0)) which passed on the current code; the same call with value 1 reverts with InsufficientAllowance(A, 0, 1).","severity":"info","snippet":"    function _transfer(address from, address to, uint256 value) private {\n        if (to == address(0)) revert InvalidReceiver(to);","title":"transferFrom accepts from == address(0) with value 0 and emits a zero-value mint-shaped Transfer event from any caller"}],"hash":"b0f6c9d3f53eefd237ee8f3e944827e104eeecfd37170858214b25e1fd582aed","nodeId":"10cb67ce-93f4-4c24-a1e6-7121df6729d1","outcome":"completed","summary":"The review is complete and the findings file is written. The git status came back empty for tracked changes since `.imd-findings.json` is ignored, and the scratch tests are removed.\n\n**Outcome:** the Sworn token holds up under the Economic Security, Invariant and Flow Gap checks. I found no defect that affects funds, supply or the launch flows. One informational deviation from reference ERC-20 behaviour is recorded.\n\n**What I checked** in `src/SwornToken.sol` against the three guides:\n\n- **Economic Security.** No external dependencies, oracles, callbacks or low-level calls exist. The token is not fee-on-transfer, rebasing, pausable or blacklistable, and both transfer paths return true. Sentinel handling is correct: zero receiver and zero spender revert.\n- **Invariant.** Total supply is immutable and set once to exactly 1e27 in the constructor, all credited to the deployer. The ABI exposes only ERC-20 getters plus approve, transfer and transferFrom, so no path can grow or freeze balances. A multi-actor fuzz with self-transfers kept the sum of balances equal to total supply. The unchecked arithmetic is safe because that sum is bounded.\n- **Flow Gap.** Factory to distributor, pool seed, swaps and claims all move exactly the stated amount, so the protected floor's balance-delta checks are met without exemptions. The reachable-opcode scan from the protected test finds no DELEGATECALL, CALLCODE, SELFDESTRUCT or CALL.\n- **Static-analysis lead.** The aderyn large-literal note is style only. The literal evaluates to exactly the stated supply.\n\n**The one finding (info):** `transferFrom` accepts a zero-address sender when the value is zero. Any account can call it with the zero address and value 0, and the token emits a zero-value Transfer from the zero address, which indexers read as a mint. Balances and supply are untouched, and any non-zero value reverts. OpenZeppelin rejects this path. The minimal fix is a zero-sender check in the private transfer helper.\n\n**Coverage:** all three listed entry points have rows, two hold and one points to the info finding, plus four invariant rows. Nothing in my area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":389543,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":11810,"runtime":"claude","turns":23,"wallClockMs":168601}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"a8006a8757108cd3","findings":[{"citation":"resolved","description":"Merged from all five reports (audit_math, audit_flow, audit_economics, audit_permissions, write_foundry_tests): one root cause. _transfer (line 59-68) rejects a zero receiver at line 60 but never rejects a zero sender, and transferFrom (line 47) passes a caller-chosen `from` straight into it. With from = address(0) and value = 0 every guard passes: allowance[address(0)][msg.sender] is 0 and `current < value` (line 50) is 0 < 0 = false; balanceOf[address(0)] is 0 and `fromBalance < value` (line 62) is 0 < 0 = false; line 68 then emits Transfer(address(0), to, 0). EIP-20 reserves a Transfer whose `from` is the zero address for token creation, and this token documents (README, launch.json notes, the NatSpec at lines 5-7) that the only mint is the constructor's single event at line 30. After deployment any unprivileged account can add mint-shaped logs naming any recipient. Reproduced by tracing and by running the attached test: it fails on this tree with 'a stranger emitted a mint-shaped Transfer after construction: 1 != 0' and passes on a copy where _transfer reverts for from == address(0). Impact is confined to off-chain readers: explorers that label from-zero transfers as mints, token-safety scanners that alert on post-launch mints for a token advertised as fixed-supply, and holder lists built from Transfer recipients, which can be spammed with zero-balance entries. No on-chain state changes: totalSupply is immutable, every balance and allowance is unchanged, and any value >= 1 from address(0) reverts with InsufficientAllowance(msg.sender, 0, value) because nobody can hold an allowance from the zero address. The launch flows (factory to distributor, claims, seed, swaps) do not use from = 0x0 and are unaffected; the protected floor tests are unaffected. Severity recalibrated to low: no loss of funds and no broken on-chain guarantee, but a concrete, reproducible deviation from the ERC-20 mint convention that the reference OpenZeppelin v5 implementation rejects with ERC20InvalidSender. Minimal fix preserving the design: add `error InvalidSender(address sender);` and `if (from == address(0)) revert InvalidSender(from);` at the top of _transfer next to the receiver check (or at the top of transferFrom). No legitimate caller can hit it.","line":60,"path":"src/SwornToken.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test, Vm} from \"forge-std/Test.sol\";\nimport {SwornToken} from \"src/SwornToken.sol\";\n\n/// Fails today: a stranger can make the token emit a second mint-shaped Transfer(0x0, to, 0).\n/// Passes once transferFrom rejects from == address(0), as _transfer already rejects to == address(0).\ncontract ZeroSenderTest is Test {\n    function test_onlyTheConstructorEmitsTransferFromZero() public {\n        SwornToken token = new SwornToken();\n        address stranger = address(0xBEEF);\n        address victim = address(0xB0B);\n\n        vm.recordLogs();\n        vm.prank(stranger);\n        (bool ok,) = address(token).call(abi.encodeCall(SwornToken.transferFrom, (address(0), victim, 0)));\n        ok;\n\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        uint256 mintShaped;\n        for (uint256 i; i < logs.length; ++i) {\n            if (logs[i].topics[0] == keccak256(\"Transfer(address,address,uint256)\") && logs[i].topics[1] == bytes32(0)) {\n                ++mintShaped;\n            }\n        }\n        assertEq(mintShaped, 0, \"a stranger emitted a mint-shaped Transfer after construction\");\n    }\n}","reproduction":"State: fresh SwornToken deployed by any deployer D (balanceOf[D] = 1e27, totalSupply = 1e27). Caller: any account S with no balance and no allowance, e.g. 0xBEEF. Call: vm.prank(S); token.transferFrom(address(0), 0xB0B, 0). Expected: revert (the zero address is not a valid sender; only the constructor may emit a Transfer from address(0)). Actual: returns true and emits Transfer(from=0x0000000000000000000000000000000000000000, to=0xB0B, value=0); afterwards totalSupply() == 1e27, balanceOf(0xB0B) == 0, balanceOf(address(0)) == 0, allowance(address(0), S) == 0. Control: the same call with value 1 reverts with InsufficientAllowance(S, 0, 1). Run: copy the proof to test/scratch/ZeroSender.t.sol and `forge test --match-path test/scratch/ZeroSender.t.sol`: FAIL on this tree ('a stranger emitted a mint-shaped Transfer after construction: 1 != 0'); PASS once _transfer rejects from == address(0).","severity":"low","snippet":"        if (to == address(0)) revert InvalidReceiver(to);","title":"transferFrom accepts from == address(0) with value 0, so anyone can emit a mint-shaped Transfer(0x0, to, 0) after construction"}],"hash":"bdcdb7deadf725d0cfbd6b106f81a5591e67c0a471f3bc64167a6f2674de4e8e","nodeId":"8ef5660b-f6fd-46f1-b8e4-dc0e6e62e480","outcome":"completed","summary":"Review complete. The findings file is written at `.imd-findings.json` and the tree is otherwise unchanged.\n\n**Outcome:** one finding kept, at low severity, merged from all five reports. Nothing else reproduced or surfaced.\n\n- **Kept and merged.** All five specialists (math, flow, economics, permissions, and the test writer) reported the same root cause: `_transfer` rejects a zero receiver but not a zero sender, so anyone can call transferFrom with from = 0x0 and value 0 and make the token emit a mint-shaped Transfer event after construction. I traced both guards (allowance 0 < 0 false, balance 0 < 0 false) and confirmed no state changes. Recalibrated to low: no funds move and no on-chain guarantee breaks, but off-chain mint labels and holder lists can be spammed on a token advertised as fixed-supply.\n- **Proof verified.** The flow specialist's attached test fails on this tree with the stated message and passes on a copy where `_transfer` reverts for a zero sender. I attached it to the finding.\n- **My own pass found nothing further.** approve and transfer hold. Allowance handling, the infinite-allowance sentinel, unchecked arithmetic, self-transfers and supply conservation all check out. No receive, fallback, owner, mint, burn, delegatecall or selfdestruct exists. All 62 project tests pass.\n- **Manifest checked.** Empty constructorArgs match the no-argument constructor, totalSupply matches the minted amount exactly, decimals and names agree, and bytecode is far below size limits.\n- **Static analysis leads.** Slither reported nothing. Aderyn's large-numeric-literal note is a style remark on the supply constant and is not a defect.\n\nCoverage answers all three entry points plus two invariant rows. Scratch test files and the temporary fixed copy were removed.","treeHash":null,"usage":{"cachedInputTokens":250320,"inputTokens":162,"model":"claude-fable-5-1","outputTokens":7801,"runtime":"claude","turns":12,"wallClockMs":120730}}],"verification":[{"checks":[{"durationMs":939,"exitCode":0,"name":"build","output":"Compiling 23 files with Solc 0.8.26\nSolc 0.8.26 finished in 843.97ms\nCompiler run successful!\n","passed":true},{"durationMs":163,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 18 tests for test/SwornToken.t.sol:SwornTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 97924, ~: 98139)\nLogs:\n  Bound result 520056381066297784492134914\n\n[PASS] testFuzz_transferFrom(address,address,uint256,uint256) (runs: 256, μ: 121751, ~: 121749)\nLogs:\n  Bound result 999999999999999999999999998\n  Bound result 394304466043514958081796\n\n[PASS] test_RevertWhen_approveZeroSpender() (gas: 30677)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 85277)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 80344)\n[PASS] test_RevertWhen_transferFromExceedsBalance() (gas: 85778)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 33487)\n[PASS] test_RevertWhen_transferToZero() (gas: 30757)\n[PASS] test_approveAndTransferFrom() (gas: 142185)\n[PASS] test_constructorEmitsMintTransfer() (gas: 5838)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 29284)\n[PASS] test_deployScriptDeploysToCaller() (gas: 872596)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 125719)\n[PASS] test_metadata() (gas: 34928)\n[PASS] test_noPrivilegedCallsExist() (gas: 200391)\n[PASS] test_transfer() (gas: 78330)\n[PASS] test_transferToSelfKeepsBalance() (gas: 40537)\n[PASS] test_transferZeroAmount() (gas: 42903)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 9.92ms (21.45ms CPU time)\n\nRan 1 test suite in 10.55ms (9.92ms CPU time): 18 tests passed, 0 failed, 0 skipped (18 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SwornToken.approve(address,uint256)\",\"SwornToken.transfer(address,uint256)\",\"SwornToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":56,\"foundry.toml\":9,\"remappings.txt\":1,\"script/DeploySworn.s.sol\":19,\"src/SwornToken.sol\":70,\"test/SwornToken.t.sol\":182},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":473,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":249,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/SwornToken.sol:13: Large Numeric Literal","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"21d7546c4e970b2c9e24bdabe9fe3547ab9532219addcec70c482d6bf6a8ab1b","verifiedTreeHash":"18eafb5004ad71411827b0ade758178bd36ca209","verifierVersion":"0.1.0+a6eb4461"},{"checks":[{"durationMs":1981,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.88s\nCompiler run successful!\n","passed":true},{"durationMs":9377,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 18 tests for test/SwornToken.t.sol:SwornTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 98041, ~: 98133)\nLogs:\n  Bound result 7073202\n\n[PASS] testFuzz_transferFrom(address,address,uint256,uint256) (runs: 256, μ: 122755, ~: 146769)\nLogs:\n  Bound result 202818417411328308871540816\n  Bound result 89\n\n[PASS] test_RevertWhen_approveZeroSpender() (gas: 30677)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 85277)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 80344)\n[PASS] test_RevertWhen_transferFromExceedsBalance() (gas: 85778)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 33487)\n[PASS] test_RevertWhen_transferToZero() (gas: 30757)\n[PASS] test_approveAndTransferFrom() (gas: 142185)\n[PASS] test_constructorEmitsMintTransfer() (gas: 5838)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 29284)\n[PASS] test_deployScriptDeploysToCaller() (gas: 872596)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 125719)\n[PASS] test_metadata() (gas: 34928)\n[PASS] test_noPrivilegedCallsExist() (gas: 200391)\n[PASS] test_transfer() (gas: 78330)\n[PASS] test_transferToSelfKeepsBalance() (gas: 40537)\n[PASS] test_transferZeroAmount() (gas: 42903)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 44.33ms (72.66ms CPU time)\n\nRan 43 tests for test/SwornToken.edge.t.sol:SwornTokenEdgeTest\n[PASS] testFuzz_RevertWhen_overAllowance(uint256,uint256) (runs: 1000, μ: 105241, ~: 105528)\nLogs:\n  Bound result 60221904211314590\n  Bound result 83931360668814170988851254882412605330922054659595450270233\n\n[PASS] testFuzz_RevertWhen_overBalance(uint256,uint256) (runs: 1000, μ: 109851, ~: 110567)\nLogs:\n  Bound result 536525498799756402234287837\n  Bound result 1881638555556764439284165156726460583874063316149203\n\n[PASS] testFuzz_approveSetsExactly(uint256,uint256,uint256) (runs: 1000, μ: 104884, ~: 104859)\nLogs:\n  Bound result 46397487354219264066\n\n[PASS] testFuzz_transferMovesExactly(uint256,uint256,uint256) (runs: 1000, μ: 153016, ~: 153648)\nLogs:\n  Bound result 1461501637330902918203684832716283019655932542974\n  Bound result 603036711756835923437821147\n  Bound result 0\n\n[PASS] test_RevertWhen_allowanceRevokedBeforeUse() (gas: 105357)\n[PASS] test_RevertWhen_approveZeroSpenderWithZeroValue() (gas: 30667)\n[PASS] test_RevertWhen_bothShort_allowanceErrorFirst() (gas: 80423)\n[PASS] test_RevertWhen_emptyAccountSendsOneWei() (gas: 33190)\n[PASS] test_RevertWhen_infiniteAllowanceButBalanceShort() (gas: 90202)\n[PASS] test_RevertWhen_selfTransferExceedsBalance() (gas: 92169)\n[PASS] test_RevertWhen_selfTransferFromWithoutSelfAllowance() (gas: 33565)\n[PASS] test_RevertWhen_spenderUsesSomeoneElsesAllowance() (gas: 87521)\n[PASS] test_RevertWhen_transferFromBalanceShortDoesNotSpendAllowance() (gas: 155406)\n[PASS] test_RevertWhen_transferFromToZeroDoesNotSpendAllowance() (gas: 100937)\n[PASS] test_RevertWhen_transferMaxUint() (gas: 33646)\n[PASS] test_RevertWhen_transferOneWeiMoreThanSupply() (gas: 33499)\n[PASS] test_RevertWhen_transferToZeroTakesPrecedenceOverBalance() (gas: 30757)\n[PASS] test_RevertWhen_transferZeroToZeroAddress() (gas: 30767)\n[PASS] test_allowanceBelowMaxIsDecreased() (gas: 118657)\n[PASS] test_approveEmitsExactEvent() (gas: 56975)\n[PASS] test_approveIsPerOwnerAndPerSpender() (gas: 81860)\n[PASS] test_approveOverwritesBothWays() (gas: 165694)\n[PASS] test_approveSelf() (gas: 123782)\n[PASS] test_approveWithoutBalanceAndAboveSupply() (gas: 61034)\n[PASS] test_constructorEmitsExactlyOneEvent() (gas: 9464)\n[PASS] test_eachDeploymentMintsOnlyToItsOwnDeployer() (gas: 38636)\n[PASS] test_factoryCannotMoveOrFreezeAHolder() (gas: 291334)\n[PASS] test_infiniteAllowanceCanMoveWholeSupplyAndEmitsNoApproval() (gas: 124711)\n[PASS] test_launchFlowsAreExact() (gas: 338343)\n[PASS] test_nonDeployerStartsWithNothing() (gas: 42265)\n[PASS] test_rejectsEtherAndUnknownCalls() (gas: 131744)\n[PASS] test_roundTripRestoresBalances() (gas: 105893)\n[PASS] test_runtimeHasNoDelegatecallCallcodeOrSelfdestruct() (gas: 1840981)\n[PASS] test_supplyIsExactlyOneBillionWholeTokens() (gas: 49867)\n[PASS] test_transferExactBalanceEmptiesSender() (gas: 153441)\n[PASS] test_transferFromEmitsOnlyTransfer() (gas: 117131)\n[PASS] test_transferFromExactAllowanceLeavesZero() (gas: 144141)\n[PASS] test_transferFromInStepsSpendsAllowanceCumulatively() (gas: 218447)\n[PASS] test_transferFromZeroValueWithoutAllowance() (gas: 56271)\n[PASS] test_transferToTokenContractIsAcceptedAndStuck() (gas: 73677)\n[PASS] test_transferWholeSupply() (gas: 71412)\n[PASS] test_transferWholeSupplyToSelf() (gas: 43560)\n[PASS] test_zeroTransferEmitsEvent() (gas: 39461)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 55.69ms (248.82ms CPU time)\n\nRan 1 test for test/SwornToken.invariant.t.sol:SwornTokenInvariantTest\n[PASS]\nSwornTokenInvariantTest invariants:\n[PASS] invariant_balancesAndAllowancesMatchModel\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_handlerExercisesTheToken\n[PASS] invariant_metadataIsConstant\n[PASS] invariant_totalSupplyNeverChanges\n SwornTokenInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------+----------------+-------+---------+----------╮\n| Contract     | Selector       | Calls | Reverts | Discards |\n+============================================================+\n| SwornHandler | approve        | 4134  | 0       | 0        |\n|--------------+----------------+-------+---------+----------|\n| SwornHandler | transfer       | 4078  | 0       | 0        |\n|--------------+----------------+-------+---------+----------|\n| SwornHandler | transferFrom   | 4129  | 0       | 0        |\n|--------------+----------------+-------+---------+----------|\n| SwornHandler | transferToZero | 4043  | 0       | 0        |\n╰--------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 53591\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1313373042\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 409620785954737113235041920\n  Bound result 0\n  Bound result 2107\n  Bound result 6508\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 6324\n  Bound result 0\n  Bound result 244\n  Bound result 3\n  Bound result 2874\n  Bound result 0\n  Bound result 0\n  Bound result 4914\n  Bound result 0\n  Bound result 0\n  Bound result 740262706121258890507472004\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 5617\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.24s (9.24s CPU time)\n\nRan 3 test suites in 9.25s (9.34s CPU time): 62 tests passed, 0 failed, 0 skipped (62 total tests)\n","passed":true},{"durationMs":67,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SwornToken.approve(address,uint256)\",\"SwornToken.transfer(address,uint256)\",\"SwornToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":56,\"foundry.toml\":9,\"remappings.txt\":1,\"script/DeploySworn.s.sol\":19,\"src/SwornToken.sol\":70,\"test/SwornToken.edge.t.sol\":497,\"test/SwornToken.invariant.t.sol\":214,\"test/SwornToken.t.sol\":182},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2b75041915a27b7402cecd6e9d54da634dd0e2bb8724a9d1aef88b931476d9da","verifiedTreeHash":"5523321d56e35693df2d382be20d21823c0d13be","verifierVersion":"0.1.0+a6eb4461"},{"checks":[{"durationMs":953,"exitCode":0,"name":"build","output":"Compiling 23 files with Solc 0.8.26\nSolc 0.8.26 finished in 854.64ms\nCompiler run successful!\n","passed":true},{"durationMs":140,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 18 tests for test/SwornToken.t.sol:SwornTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 97924, ~: 98139)\nLogs:\n  Bound result 442\n\n[PASS] testFuzz_transferFrom(address,address,uint256,uint256) (runs: 256, μ: 121751, ~: 121749)\nLogs:\n  Bound result 499026039541260\n  Bound result 878535116000976691560938889\n\n[PASS] test_RevertWhen_approveZeroSpender() (gas: 30677)\n[PASS] test_RevertWhen_transferExceedsBalance() (gas: 85277)\n[PASS] test_RevertWhen_transferFromExceedsAllowance() (gas: 80344)\n[PASS] test_RevertWhen_transferFromExceedsBalance() (gas: 85778)\n[PASS] test_RevertWhen_transferFromWithoutAllowance() (gas: 33487)\n[PASS] test_RevertWhen_transferToZero() (gas: 30757)\n[PASS] test_approveAndTransferFrom() (gas: 142185)\n[PASS] test_constructorEmitsMintTransfer() (gas: 5838)\n[PASS] test_constructorMintsWholeSupplyToDeployer() (gas: 29284)\n[PASS] test_deployScriptDeploysToCaller() (gas: 872596)\n[PASS] test_infiniteAllowanceNotDecreased() (gas: 125719)\n[PASS] test_metadata() (gas: 34928)\n[PASS] test_noPrivilegedCallsExist() (gas: 200391)\n[PASS] test_transfer() (gas: 78330)\n[PASS] test_transferToSelfKeepsBalance() (gas: 40537)\n[PASS] test_transferZeroAmount() (gas: 42903)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 12.05ms (22.46ms CPU time)\n\nRan 1 test suite in 12.80ms (12.05ms CPU time): 18 tests passed, 0 failed, 0 skipped (18 total tests)\n","passed":true},{"durationMs":66,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SwornToken.approve(address,uint256)\",\"SwornToken.transfer(address,uint256)\",\"SwornToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":56,\"foundry.toml\":9,\"launch.json\":24,\"remappings.txt\":1,\"script/DeploySworn.s.sol\":19,\"src/SwornToken.sol\":70,\"test/SwornToken.t.sol\":182},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"735ae106929417c54ae478f6c96d1e59fae675d268b7a0161959b56aed48789e","verifiedTreeHash":"1ce59fbe496136ba56b0b7073ad38c61617bf2f6","verifierVersion":"0.1.0+a6eb4461"}]}